Skip to content
Snippets Groups Projects
Commit 6ad2bb59 authored by Kerdo Kurs's avatar Kerdo Kurs
Browse files

add kodu6

parent 1116940f
No related branches found
No related tags found
No related merge requests found
#pragma once
#include <vector>
std::vector<int> vLisaCopy(std::vector<int> v, int i) {
v.push_back(i);
return v;
}
std::vector<int> &vLisaRef(std::vector<int> &v, int i) {
v.push_back(i);
return v;
}
std::vector<int> *vLisaPtr(std::vector<int> *v, int i) {
v->push_back(i);
return v;
}
std::vector<int *> iota(const int n) {
std::vector<int *> v(n);
for (int i = 0; i < n; ++i) {
v[i] = new int(i + 1);
}
return v;
}
void destroy(std::vector<int *> &v) {
for (auto &ptr : v) {
delete ptr;
ptr = nullptr;
}
}
\ No newline at end of file
#pragma once
#include <cassert>
#include <optional>
template<typename T>
class MinuVektor {
public:
MinuVektor() {
m_Buffer = new T[m_Capacity];
}
explicit MinuVektor(size_t capacity)
: m_Capacity(capacity) {
m_Buffer = new T[capacity];
}
MinuVektor(size_t capacity, T initial)
: m_Size(capacity), m_Capacity(capacity) {
m_Buffer = new T[capacity];
for (size_t i = 0; i < m_Capacity; i++) {
m_Buffer[i] = initial;
}
}
~MinuVektor() {
delete[] m_Buffer;
}
void push_back(T value) {
if (m_Size >= m_Capacity) {
resize(m_Capacity * 2);
}
m_Buffer[m_Size++] = value;
}
std::optional<T> get(size_t idx) {
if (idx >= m_Size) {
return std::nullopt;
}
return m_Buffer[idx];
}
std::optional<T> front() {
return get(0);
}
std::optional<T> back() {
return get(m_Size - 1);
}
T operator[](size_t idx) {
assert(idx < m_Size);
return *get(idx);
}
template<typename U = T>
requires std::integral<U>
static MinuVektor<U> iota(size_t sz) {
MinuVektor v(sz);
for (size_t i = 0; i < sz; i++) {
v.push_back(i);
}
return v;
}
template<typename U>
MinuVektor<U> transform(auto fn) const {
MinuVektor<U> v(size());
for (auto i = 0u; i < size(); i++) {
v.push_back(fn(m_Buffer[i]));
}
return v;
}
[[nodiscard]] const T *buf() const { return m_Buffer; }
[[nodiscard]] auto size() const { return m_Size; }
[[nodiscard]] auto capacity() const { return m_Capacity; }
private:
void resize(const size_t newCapacity) {
if (newCapacity < m_Capacity) {
return;
}
T *newBuffer = new T[newCapacity];
for (size_t i = 0; i < m_Capacity; i++) {
newBuffer[i] = m_Buffer[i];
}
delete[] m_Buffer;
m_Buffer = newBuffer;
m_Capacity = newCapacity;
}
private:
size_t m_Size{0};
size_t m_Capacity{2};
T *m_Buffer = nullptr;
};
template<typename T>
std::ostream &operator<<(std::ostream &os, MinuVektor<T> &v) {
os << '{';
for (size_t i = 0; i < v.size(); i++) {
os << v[i];
if (i != v.size() - 1) {
os << ", ";
}
}
os << '}';
return os;
}
\ No newline at end of file
#pragma once
#include <cstdlib>
#include <vector>
// Ülesanne 1. Funktsiooniobjektid ("funktor").
// Kirjuta klass `Sequence`, mis modelleerib sisult jada, mis hoiab sealt elementide võtmisel järge ning selle klassi
// objekti "kutsumisel" tagastatakse järjekorras järgmine element.
// Klass peab sisemiselt andmeid hoidma kuhimälus oleval mälul. Klass ei tohi kasutada STL-is olemasolevat konteinerit,
// vaid peab ise dünaamiliselt mälu haldama.
// Võid eeldada, et jadasse elemente peale selle konstrueerimist juurde ei lisata.
// Vihjeks: on vajalik vaid üks `new` ja `delete`. Puhvrit suuremaks ega väiksemaks tegema ei pea.
//
// Klass peab käituma järgmiselt:
//
// Klassil on 2 konstruktorit:
// - `Sequence(const std::vector<int> &values)` - konstrueerib jada ning kopeerib kõik väärtused kuhimällu.
// - `Sequence(const std::initializer_list<int> list)` - konstrueerib jada ning kopeerib initsialiseerimisnimekirja
// elemendid kuhimällu.
// Klass ei tohi olla vaikimisi konstrueeritav! S.t, et `Sequence s;` ei tohi töötada (näites olemas).
// Klassi kustutamisel peab destruktor küsitud mälu vabastama.
//
// Klass peab olema "kutsutav" (funktsiooniobjekti omadustega), s.t, et sellele on "kutseoperaator".
//
// Klassil peavad olema järgmised kutseoperaatorid
// - Ilma argumendita operaator, mis tagastab jada järjekorras järgmise elemendi ning liigutab "järge" edasi.
// - Operaator ühe argumendiga tüüpi `size_t skip`, mis jätab vahele `skip` elementi ning tagastab vastava elemendi.
// Samuti liigutab "järge" edasi vastavalt vahele jäetud elementide arvust.
//
// Näide:
// Sequence s = {1, 2, 3, 4, 5};
// const auto x = s(); // x = 1
// // s() tagastaks hetkel 2
// const auto y = s(1); // y = 3
// const auto z = s(); // z = 4
// const auto w = s(1); // peaks krahhima programmi
//
// - Operaator, mille abil on võimalik klassiobjekt teisendada tõeväärtuseks (`bool`).
// Näide:
// const Sequence s = {1};
// const bool b = static_cast<bool>(s); // b = true
// // const bool b2 = s; // pane tähele, et operaator peab olema `explicit`, et see rida ei töötaks.
//
// Klassil on ka järgmised liikmefunktsioonid
// NB! Pane tähele, et liikmefunktsioonid, mis klassi sisu ei muuda, peavad olema märgitud võtmesõnaga `const`.
// Lisaks oleks hea, kui funktsioonid, mis tagastavad midagi, võiksid olla märgitud atribuudiga `[[nodiscard]]`.
//
// - `int *end()` - tagastab viimasest elemendist järgmise. Tegelikult on see allokeeritud puhvrist väljas, aga hea
// markeering selleks, et oleme jõudnud puhvri lõppu. Kõik STL-i konteinerid teevad seda sarnaselt (vt std::vector::end()).
// - `size_t available()` - tagastab alles olevate elementide arvu.
// - `std::vector<int> vec()` - tagastab alles olevad elemendid uues vektoris ning ei tohi jada järge edasi liigutada.
//
// Klassil on järgmised staatilised funktsioonid:
// - `Sequence seq(const Sequence &s)` - mis konstrueerib ja tagastab jadas `s` alles jäänud elementidest uue jada.
// Vihje: Antud funktsioon on lahenduv 2 reaga ;)
//
// Soovitus: Alusta lahendamist all antud mallist.
//
// NB! Pane tähele, et ilmutatud ("explicit") teste automaatselt ei tehta. Need vaatan käsitsi.
class Sequence {
public:
Sequence() = delete;
explicit Sequence(const std::vector<int> &values);
Sequence(std::initializer_list<int> list);
// !!! Ära neid 2 modifitseeri
Sequence(const Sequence &) = delete;
Sequence &operator=(const Sequence &) = delete;
// !!!
~Sequence();
static Sequence sec(const Sequence &s);
[[nodiscard]] auto end() const;
[[nodiscard]] auto available() const -> size_t;
int operator()();
int operator()(size_t skip);
explicit operator bool() const;
[[nodiscard]] std::vector<int> vec() const;
private:
int *m_Head;
size_t m_Size;
int *m_Ptr{};
};
#pragma once
#include <print>
#include <functional>
#include <iostream>
#include <sstream>
// Ära neid muutujaid ja funktsioone redigeeri.
static inline int g_TotalTestCount = 0;
static inline int g_SuccessfulTestCount = 0;
#define TEST(condition) testAssert(condition, __FILE__, __LINE__)
inline void testAssert(bool condition, const char *file, int line) {
g_TotalTestCount++;
if (!condition) {
std::cout << "VIGA: Kontroll asukohas " << file << ":" << line << " ei olnud õige.\n";
} else {
g_SuccessfulTestCount++;
}
}
template<typename T>
auto equal(const T &a, const T &b) {
if (a.size() != b.size()) {
return false;
}
return std::equal(a.begin(), a.end(), b.begin());
}
auto all(const auto begin, const auto end, const auto val) {
const auto fn = [&val](const auto v) -> bool { return v == val; };
return std::all_of(begin, end, fn);
}
auto all(const auto &c, const auto val) {
return all(std::begin(c), std::end(c), val);
}
class CoutCapture {
std::stringstream &m_Buffer;
std::streambuf *m_Prevcout;
public:
explicit CoutCapture(std::stringstream &buf) : m_Buffer(buf) {
m_Prevcout = std::cout.rdbuf(m_Buffer.rdbuf());
}
~CoutCapture() {
std::cout.rdbuf(m_Prevcout);
}
explicit operator bool() const {
return m_Prevcout != std::cout.rdbuf();
}
static bool expect(const std::string &str, auto fn) {
std::stringstream buf;
if (const CoutCapture cap(buf); cap) {
if constexpr (std::is_same_v<decltype(fn()), bool>) {
auto res = fn();
if (!res) {
return false;
}
} else {
fn();
}
}
return buf.str() == str;
}
};
\ No newline at end of file
#include <algorithm>
#include <iostream>
#include <map>
#include <numeric>
#include <ranges>
#include "MinuVektor.hpp"
#include "Funktsioonid.hpp"
#include "Sequence.hpp"
#include "Tester.hpp"
int main() {
// Ülesanne 1. Sequence
{
// Konstruktor `Sequence(const std::vector<int> &values)`
const std::vector v = {1, 2, 3};
const Sequence s(v);
TEST(s.available() == v.size());
}
{
// Konstruktor `Sequence(const std::initializer_list<int> list)`
const Sequence s = {1, 2, 3, 4};
TEST(s.available() == 4);
}
{
// operator()
Sequence s = {1, 2, 3, 4};
std::vector<int> v(s.available());
for (size_t i = 0; i < 4; ++i) {
v[i] = s();
}
TEST(v.size() == 4);
TEST(equal(v, {1, 2, 3, 4}));
TEST(s.available() == 0);
// s(); // - see peaks programmi krahhima
}
{
// Konstruktor `Sequence(const Sequence &s)`
Sequence s = {1, 2, 3};
s();
const auto s2 = Sequence::sec(s);
TEST(equal(s2.vec(), {2, 3}));
}
{
// operator(size_t)
Sequence s = {1, 2, 3, 4, 5};
s();
TEST(s(1) == 3);
TEST(s.available() > 0);
TEST(s() == 4);
TEST(s() == 5);
TEST(s.available() == 0);
// s(); // - see peaks programmi krahhima
}
{
[[maybe_unused]] Sequence s = {1};
// s(1); // - see peaks programmi krahhima
}
{
// operator bool
Sequence s = {1};
TEST(static_cast<bool>(s));
s();
TEST(!static_cast<bool>(s));
}
{
// vec
const Sequence s = {1, 2};
const auto vec = s.vec();
TEST(equal(vec, {1, 2}));
Sequence s2 = {1, 2};
TEST(s2(1) == 2);
const auto vec2 = s2.vec();
TEST(vec2.empty());
}
{
Sequence s = {1, 2, 3, 4, 5, 6};
int current = 1;
bool result = true;
// Siin on operator bool kasulik:
while (s && result) {
const auto correct = (current++) == s();
result &= correct;
}
TEST(result);
}
// Ülesanne 2. Funktsioonid
// Kirjuta lahendus korrektselt päise- ja lähtekoodifailidesse nii, et
// allolevad testid läbiksid Vaata, et lisaksid ka lähtekoodifaili faili
// CMakeLists.txt ning impordiksid päisefaili õigesti NB! Pane tähele, et
// funktsioonid ei ole mallid, s.t peavad olema jaotatud nii päise- kui ka
// lähtekoodifailide vahel.
// Antud ülesande lahendamisel ignoreeri CLion'i antud hoiatusi koopiate ja
// reference'ide kohta.
{
std::vector v = {1, 2, 3};
const std::vector v2 = vLisaCopy(v, 4);
TEST(equal(v2, {1, 2, 3, 4}));
TEST(equal(v, {1, 2, 3}));
}
{
std::vector v = {1, 2, 3};
const auto &v2 = vLisaRef(v, 4);
// Funktsioon peab tagastama sama vektori, mis talle anti
TEST(&v == &v2);
TEST(equal(v, {1, 2, 3, 4}));
TEST(equal(v2, {1, 2, 3, 4}));
}
{
std::vector v = {1, 2, 3};
const auto *v2 = vLisaPtr(&v, 4);
// Funktsioon peab tagastama sama vektori, mis talle anti
TEST(&v == v2);
TEST(equal(v, {1, 2, 3, 4}));
// Mõtle ja katseta, kas allolev rida teeb vektorist koopia?
const auto &v2Ref = *v2;
TEST(equal(v2Ref, {1, 2, 3, 4}));
}
// Ülesanne 3. Vektor viitadest
// Kirjuta funktsioon `std::vector<int *> iota(int n)`, mis tagastab vektori,
// kus on kuhimälus allokeeritud täisarvud, mis sisaldavad väärtuseid [0, ...,
// n]. Võid eeldada, et `n > 0`. Kirjuta funktsioon `destroy(std::vector<int
// *> &v)`, mis vabastab kõik täisarvud ning seab vektori viidad võrduma
// väärtusega `nullptr`. Vasta ka küsimusele, miks argument peab olema viite
// tüüpi ning miks ei tohi vektorit ennast "kustutada".
{
const int N = 10;
auto vec = iota(N);
bool result = true;
for (int i = 0; i < N; ++i) {
const auto ptr = vec[i];
const auto correct = *ptr == (i + 1);
result &= correct;
}
TEST(result);
destroy(vec);
TEST(all(vec, nullptr));
}
std::cout << "Testide tulemus: " << g_SuccessfulTestCount << "/"
<< g_TotalTestCount << '\n';
return g_SuccessfulTestCount != g_TotalTestCount;
}
#include "Sequence.hpp"
#include <cassert>
Sequence::Sequence(const std::vector<int> &values)
: m_Size(values.size()) {
m_Head = new int[m_Size];
m_Ptr = m_Head;
for (size_t i = 0; i < m_Size; ++i) {
m_Ptr[i] = values[i];
}
}
Sequence::Sequence(const std::initializer_list<int> list)
: m_Size(list.size()) {
m_Head = new int[m_Size];
m_Ptr = m_Head;
auto ptr = list.begin();
for (size_t i = 0; i < m_Size; ++i, ++ptr) {
m_Ptr[i] = *ptr;
}
}
Sequence::~Sequence() {
delete []m_Head;
}
auto Sequence::end() const {
return m_Head + m_Size;
}
auto Sequence::available() const -> size_t {
return end() - m_Ptr;
}
int Sequence::operator()() {
assert(available());
const auto value = *m_Ptr;
m_Ptr++;
return value;
}
int Sequence::operator()(const size_t skip) {
assert(skip < available());
for (size_t i = 0; i < skip; ++i) {
m_Ptr++;
}
const auto value = *m_Ptr;
m_Ptr++;
return value;
}
Sequence::operator bool() const {
return available() != 0;
}
std::vector<int> Sequence::vec() const {
const auto size = available();
std::vector<int> v(size);
for (size_t i = 0; i < size; ++i) {
v[i] = m_Ptr[i];
}
return v;
}
Sequence Sequence::sec(const Sequence &s) {
const auto vec = s.vec();
return Sequence(vec);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment