From 5e9cb4ddc811465731596d8ee684f3d8cd5a6aea Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sat, 2 May 2026 16:05:06 +0300 Subject: feat(Week11): Add solutions --- Week11/Exercise01/Pair.hpp | 43 ++++++++ Week11/Exercise02/Option.hpp | 68 ++++++++++++ Week11/Exercise02/main.cpp | 25 +++++ Week11/Exercise03/SharedPointer.hpp | 129 +++++++++++++++++++++++ Week11/Exercise03/main.cpp | 17 +++ Week11/Exercise04/Vector.hpp | 147 ++++++++++++++++++++++++++ Week11/Exercise04/main.cpp | 23 +++++ Week11/Exercise05/DoubleVector.hpp | 201 ++++++++++++++++++++++++++++++++++++ Week11/Exercise05/Pair.hpp | 43 ++++++++ Week11/Exercise06/UniquePointer.hpp | 75 ++++++++++++++ Week11/Exercise06/main.cpp | 9 ++ Week11/README.md | 3 + 12 files changed, 783 insertions(+) create mode 100644 Week11/Exercise01/Pair.hpp create mode 100644 Week11/Exercise02/Option.hpp create mode 100644 Week11/Exercise02/main.cpp create mode 100644 Week11/Exercise03/SharedPointer.hpp create mode 100644 Week11/Exercise03/main.cpp create mode 100644 Week11/Exercise04/Vector.hpp create mode 100644 Week11/Exercise04/main.cpp create mode 100644 Week11/Exercise05/DoubleVector.hpp create mode 100644 Week11/Exercise05/Pair.hpp create mode 100644 Week11/Exercise06/UniquePointer.hpp create mode 100644 Week11/Exercise06/main.cpp create mode 100644 Week11/README.md (limited to 'Week11') diff --git a/Week11/Exercise01/Pair.hpp b/Week11/Exercise01/Pair.hpp new file mode 100644 index 0000000..4fd47fd --- /dev/null +++ b/Week11/Exercise01/Pair.hpp @@ -0,0 +1,43 @@ +#ifndef _PAIR +#define _PAIR + +template +class Pair { + T left; + U right; + +public: + Pair(const T& left, const U& right); + + T& Left(); + const T& Left() const; + + U& Right(); + const U& Right() const; +}; + +template +Pair::Pair(const T& left, const U& right) : left(left), right(right) +{ } + +template +T& Pair::Left() { + return left; +} + +template +const T& Pair::Left() const { + return left; +} + +template +U& Pair::Right() { + return right; +} + +template +const U& Pair::Right() const { + return right; +} + +#endif /* _PAIR */ diff --git a/Week11/Exercise02/Option.hpp b/Week11/Exercise02/Option.hpp new file mode 100644 index 0000000..69f7297 --- /dev/null +++ b/Week11/Exercise02/Option.hpp @@ -0,0 +1,68 @@ +#ifndef _OPTION +#define _OPTION + +template +class Option { + T obj; + bool isSomething; + + Option(); +public: + static Option Some(T value); + static Option None(); + + bool IsSome() const; + bool IsNone() const; + T Unwrap(); +}; + +template +Option::Option() : obj(), isSomething(false) +{ } + +template +Option Option::Some(T value) { + Option op; + op.isSomething = true; + op.obj = value; + return op; +} + +// Какво запазваме, когато искаме да запазим нищо? +// Ако работехме с T*, щяхме да запазим nullptr. +// В нашия случай, няма голямо значение каква е стойността на obj, +// затова просто ще запазим стойността по подразбиране. +// Ако съответния тип няма конструктор по подразбиране, тогава ще +// получим грешка по време на компилация. +template +Option Option::None() { + return Option(); +} + +template +bool Option::IsSome() const { + return isSomething; +} + +template +bool Option::IsNone() const { + return !isSomething; +} + +// Както при None метода, тук е нужно T да има имплементиран +// копиращи и/или преместващи семантики (конструктор и operator=). +// +// Обаче, ако ние сме създали обект чрез None, тогава Unwrap ще ни +// върне потенциално валидна стойност: тази по подразбиране. +// Коректното решение тук е да имаме проверка за isSomething, +// и ако не е, да "хвърлим грешка". Но това още не сме го учили. +// +// За момента ще приемем, че ако програмист направи Unwrap на обект, +// създаден чрез None, тогава това е негов пропуск, който сам трябва +// да си оправи. +template +T Option::Unwrap() { + return obj; +} + +#endif /* _OPTION */ diff --git a/Week11/Exercise02/main.cpp b/Week11/Exercise02/main.cpp new file mode 100644 index 0000000..f734373 --- /dev/null +++ b/Week11/Exercise02/main.cpp @@ -0,0 +1,25 @@ +#include "Option.hpp" +#include +#include + +Option trySqrt(double x) { + if (x < 0.0) + return Option::None(); + return Option::Some(sqrt(x)); +} + +int main() { + double num; + std::cin >> num; + + Option numRoot = trySqrt(num); + + if (numRoot.IsSome()) { + std::cout << numRoot.Unwrap() << std::endl; + } + else { + std::cout << "Couldn't find square root!" << std::endl; + } + + return 0; +} diff --git a/Week11/Exercise03/SharedPointer.hpp b/Week11/Exercise03/SharedPointer.hpp new file mode 100644 index 0000000..06f9bbb --- /dev/null +++ b/Week11/Exercise03/SharedPointer.hpp @@ -0,0 +1,129 @@ +#ifndef _SHAREDPOINTER +#define _SHAREDPOINTER + +template +class SharedPointer { + T* value; + unsigned* instances; + + void free(); + void copyFrom(const SharedPointer& other); + +public: + SharedPointer(T* value); + + SharedPointer(); + ~SharedPointer(); + SharedPointer(const SharedPointer& other); + SharedPointer& operator=(const SharedPointer& other); + + SharedPointer(SharedPointer&& other); + SharedPointer& operator=(SharedPointer&& other); + + T& operator*(); + const T& operator*() const; + T* operator->(); + const T* operator->() const; + + unsigned RefCount() const; +}; + +template +void SharedPointer::free() { + if (instances == nullptr) + return; + + --*instances; + if (*instances == 0) { + delete instances; + delete value; + } +} + +template +void SharedPointer::copyFrom(const SharedPointer& other) { + this->instances = other.instances; + this->value = other.value; + ++*instances; +} + +template +SharedPointer::SharedPointer(T* value) : instances(new unsigned), value(value) +{ + *instances = 1; +} + +template +SharedPointer::SharedPointer() : instances(), value() +{ } + +template +SharedPointer::~SharedPointer() { + free(); +} + +template +SharedPointer::SharedPointer(const SharedPointer& other) { + copyFrom(other); +} + +template +SharedPointer& SharedPointer::operator=(const SharedPointer& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +template +SharedPointer::SharedPointer(SharedPointer&& other) { + instances = other.instances; + value = other.value; + + other.instances = nullptr; + other.value = nullptr; +} + +template +SharedPointer& SharedPointer::operator=(SharedPointer&& other) { + if (this != &other) { + free(); + + instances = other.instances; + value = other.value; + + other.instances = nullptr; + other.value = nullptr; + } + return *this; +} + +template +T& SharedPointer::operator*() { + return *value; +} + +template +const T& SharedPointer::operator*() const { + return *value; +} + +template +T* SharedPointer::operator->() { + return value; +} + +template +const T* SharedPointer::operator->() const { + return value; +} + +template +unsigned SharedPointer::RefCount() const { + if (instances == nullptr) + return 0; + return *instances; +} + +#endif /* _SHAREDPOINTER */ diff --git a/Week11/Exercise03/main.cpp b/Week11/Exercise03/main.cpp new file mode 100644 index 0000000..d8a4d66 --- /dev/null +++ b/Week11/Exercise03/main.cpp @@ -0,0 +1,17 @@ +#include "SharedPointer.hpp" +#include + +void inc(SharedPointer val) { + (*val)++; +} + +int main() { + SharedPointer x(new int); + SharedPointer y = x; + *x = 5; + std::cout << *x << ' ' << *y << std::endl; + inc(y); + std::cout << *x << ' ' << *y << std::endl; + + return 0; +} diff --git a/Week11/Exercise04/Vector.hpp b/Week11/Exercise04/Vector.hpp new file mode 100644 index 0000000..78dba08 --- /dev/null +++ b/Week11/Exercise04/Vector.hpp @@ -0,0 +1,147 @@ +#ifndef _VECTOR +#define _VECTOR + +template +class Vector { + T* objects; + unsigned objectsCount; + unsigned objectsAlloc; + + void free(); + void copyFrom(const Vector& other); + + void resize(); + +public: + Vector(); + ~Vector(); + Vector(const Vector& other); + Vector& operator=(const Vector& other); + + Vector(Vector&& other); + Vector& operator=(Vector&& other); + + unsigned Count() const; + void PushBack(const T& object); + + T& operator[](unsigned index); + const T& operator[](unsigned index) const; + + Vector& operator+=(const Vector& rhs); +}; + +template +Vector operator+(const Vector& lhs, const Vector& rhs); + +template +void Vector::free() { + delete[] objects; +} + +template +void Vector::copyFrom(const Vector& other) { + objectsCount = other.objectsCount; + objectsAlloc = other.objectsAlloc; + + objects = new T[objectsAlloc]; + for (unsigned i = 0; i < objectsCount; ++i) + objects[i] = other.objects[i]; +} + +template +void Vector::resize() { + objectsAlloc = objectsAlloc == 0 ? 8 : objectsAlloc * 2; + T* objectsLarger = new T[objectsAlloc]; + + for (unsigned i = 0; i < objectsCount; ++i) + objectsLarger[i] = objects[i]; + + delete[] objects; + objects = objectsLarger; +} + +template +Vector::Vector() : objects(), objectsAlloc(), objectsCount() +{ } + +template +Vector::~Vector() { + free(); +} + +template +Vector::Vector(const Vector& other) { + copyFrom(other); +} + +template +Vector& Vector::operator=(const Vector& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +template +Vector::Vector(Vector&& other) { + objects = other.objects; + objectsCount = other.objectsCount; + objectsAlloc = other.objectsAlloc; + + other.objects = nullptr; + other.objectsCount = other.objectsAlloc = 0; +} + +template +Vector& Vector::operator=(Vector&& other) { + if (this != &other) { + free(); + + objects = other.objects; + objectsCount = other.objectsCount; + objectsAlloc = other.objectsAlloc; + + other.objects = nullptr; + other.objectsCount = other.objectsAlloc = 0; + } + return *this; +} + +template +unsigned Vector::Count() const { + return objectsCount; +} + +template +void Vector::PushBack(const T& object) { + if (objectsCount >= objectsAlloc) + resize(); + objects[objectsCount++] = object; +} + +template +T& Vector::operator[](unsigned index) { + return objects[index]; +} + +template +const T& Vector::operator[](unsigned index) const { + return objects[index]; +} + +template +Vector& Vector::operator+=(const Vector& rhs) { + for (unsigned i = 0; i < rhs.objectsCount; ++i) + PushBack(rhs.objects[i]); + return *this; +} + +template +Vector operator+(const Vector& lhs, const Vector& rhs) { + Vector val(lhs); + val += rhs; + return val; +} + +#endif /* _VECTOR */ diff --git a/Week11/Exercise04/main.cpp b/Week11/Exercise04/main.cpp new file mode 100644 index 0000000..cdf3555 --- /dev/null +++ b/Week11/Exercise04/main.cpp @@ -0,0 +1,23 @@ +#include "Vector.hpp" +#include + +void print(const Vector numbers) { + for (unsigned i = 0; i < numbers.Count(); ++i) + std::cout << numbers[i] << ' '; + std::cout << std::endl; +} + +int main() { + Vector nums; + nums.PushBack(1); + nums.PushBack(2); + nums.PushBack(3); + + Vector numsMore(nums); + numsMore.PushBack(4); + numsMore.PushBack(5); + + print(nums + numsMore); + + return 0; +} diff --git a/Week11/Exercise05/DoubleVector.hpp b/Week11/Exercise05/DoubleVector.hpp new file mode 100644 index 0000000..7ffe26c --- /dev/null +++ b/Week11/Exercise05/DoubleVector.hpp @@ -0,0 +1,201 @@ +#ifndef _DOUBLEVECTOR +#define _DOUBLEVECTOR + +#include "Pair.hpp" + +template +class DoubleVector { + T* first; + unsigned firstCount; + unsigned firstAlloc; + + T* second; + unsigned secondCount; + unsigned secondAlloc; + + void free(); + void copyFrom(const DoubleVector& other); + + void firstResize(); + void secondResize(); + +public: + DoubleVector(); + ~DoubleVector(); + DoubleVector(const DoubleVector& other); + DoubleVector& operator=(const DoubleVector& other); + + DoubleVector(DoubleVector&& other); + DoubleVector& operator=(DoubleVector&& other); + + Pair Count() const; + + void FirstPushBack(const T& object); + void SecondPushBack(const U& object); + + Pair operator[](unsigned index); + const Pair operator[](unsigned index) const; + + DoubleVector& operator+=(const DoubleVector& rhs); +}; + +template +DoubleVector operator+(const DoubleVector& lhs, const DoubleVector& rhs); + +template +void DoubleVector::free() { + delete[] first; + delete[] second; +} + +template +void DoubleVector::copyFrom(const DoubleVector& other) { + firstCount = other.firstCount; + firstAlloc = other.firstAlloc; + + first = new T[firstAlloc]; + for (unsigned i = 0; i < firstCount; ++i) + first[i] = other.first[i]; + + secondCount = other.secondCount; + secondAlloc = other.secondAlloc; + + second = new T[secondAlloc]; + for (unsigned i = 0; i < secondCount; ++i) + second[i] = other.second[i]; +} + +template +void DoubleVector::firstResize() { + firstAlloc = firstAlloc == 0 ? 8 : firstAlloc * 2; + T* firstLarger = new T[firstAlloc]; + + for (unsigned i = 0; i < firstCount; ++i) + firstLarger[i] = first[i]; + + delete[] first; + first = firstLarger; +} + +template +void DoubleVector::secondResize() { + secondAlloc = secondAlloc == 0 ? 8 : secondAlloc * 2; + U* secondLarger = new U[secondAlloc]; + + for (unsigned i = 0; i < secondCount; ++i) + secondLarger[i] = second[i]; + + delete[] second; + second = secondLarger; +} + +template +DoubleVector::DoubleVector() + : first(), firstAlloc(), firstCount(), + second(), secondAlloc(), secondCount() +{ } + +template +DoubleVector::~DoubleVector() { + free(); +} + +template +DoubleVector::DoubleVector(const DoubleVector& other) { + copyFrom(other); +} + +template +DoubleVector& DoubleVector::operator=(const DoubleVector& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +template +DoubleVector::DoubleVector(DoubleVector&& other) { + first = other.first; + firstCount = other.firstCount; + firstAlloc = other.firstAlloc; + + second = other.second; + secondCount = other.secondCount; + secondAlloc = other.secondAlloc; + + other.first = nullptr; + other.firstCount = other.firstAlloc = 0; + + other.second = nullptr; + other.secondCount = other.secondAlloc = 0; +} + +template +DoubleVector& DoubleVector::operator=(DoubleVector&& other) { + if (this != &other) { + free(); + + first = other.first; + firstCount = other.firstCount; + firstAlloc = other.firstAlloc; + + second = other.second; + secondCount = other.secondCount; + secondAlloc = other.secondAlloc; + + other.first = nullptr; + other.firstCount = other.firstAlloc = 0; + + other.second = nullptr; + other.secondCount = other.secondAlloc = 0; + } + return *this; +} + +template +Pair DoubleVector::Count() const { + return Pair(firstCount, secondCount); +} + +template +void DoubleVector::FirstPushBack(const T& object) { + if (firstCount >= firstAlloc) + firstResize(); + first[firstCount++] = object; +} + +template +void DoubleVector::SecondPushBack(const U& object) { + if (secondCount >= secondAlloc) + secondResize(); + second[secondCount++] = object; +} + +template +Pair DoubleVector::operator[](unsigned index) { + return Pair(first[index], second[index]); +} + +template +const Pair DoubleVector::operator[](unsigned index) const { + return Pair(first[index], second[index]); +} + +template +DoubleVector& DoubleVector::operator+=(const DoubleVector& rhs) { + for (unsigned i = 0; i < rhs.firstCount; ++i) + FirstPushBack(rhs.first[i]); + for (unsigned i = 0; i < rhs.secondCount; ++i) + SecondPushBack(rhs.second[i]); + return *this; +} + +template +DoubleVector operator+(const DoubleVector& lhs, const DoubleVector& rhs) { + DoubleVector val(lhs); + val += rhs; + return val; +} + +#endif /* _DOUBLEVECTOR */ diff --git a/Week11/Exercise05/Pair.hpp b/Week11/Exercise05/Pair.hpp new file mode 100644 index 0000000..4fd47fd --- /dev/null +++ b/Week11/Exercise05/Pair.hpp @@ -0,0 +1,43 @@ +#ifndef _PAIR +#define _PAIR + +template +class Pair { + T left; + U right; + +public: + Pair(const T& left, const U& right); + + T& Left(); + const T& Left() const; + + U& Right(); + const U& Right() const; +}; + +template +Pair::Pair(const T& left, const U& right) : left(left), right(right) +{ } + +template +T& Pair::Left() { + return left; +} + +template +const T& Pair::Left() const { + return left; +} + +template +U& Pair::Right() { + return right; +} + +template +const U& Pair::Right() const { + return right; +} + +#endif /* _PAIR */ diff --git a/Week11/Exercise06/UniquePointer.hpp b/Week11/Exercise06/UniquePointer.hpp new file mode 100644 index 0000000..fe95234 --- /dev/null +++ b/Week11/Exercise06/UniquePointer.hpp @@ -0,0 +1,75 @@ +#ifndef _UNIQUEPOINTER +#define _UNIQUEPOINTER + +template +class UniquePointer { + T* value; + +public: + UniquePointer(T* value); + + UniquePointer(); + ~UniquePointer(); + + UniquePointer(UniquePointer&& other); + UniquePointer& operator=(UniquePointer&& other); + + T& operator*(); + const T& operator*() const; + T* operator->(); + const T* operator->() const; +}; + +template +UniquePointer::UniquePointer(T* value) : value(value) +{ } + +template +UniquePointer::UniquePointer() : value() +{ } + +template +UniquePointer::~UniquePointer() { + delete value; +} + +template +UniquePointer::UniquePointer(UniquePointer&& other) { + value = other.value; + + other.value = nullptr; +} + +template +UniquePointer& UniquePointer::operator=(UniquePointer&& other) { + if (this != &other) { + delete value; + + value = other.value; + + other.value = nullptr; + } + return *this; +} + +template +T& UniquePointer::operator*() { + return *value; +} + +template +const T& UniquePointer::operator*() const { + return *value; +} + +template +T* UniquePointer::operator->() { + return value; +} + +template +const T* UniquePointer::operator->() const { + return value; +} + +#endif /* _UNIQUEPOINTER */ diff --git a/Week11/Exercise06/main.cpp b/Week11/Exercise06/main.cpp new file mode 100644 index 0000000..8853a90 --- /dev/null +++ b/Week11/Exercise06/main.cpp @@ -0,0 +1,9 @@ +#include "UniquePointer.hpp" +#include + +int main() { + UniquePointer ptr(new int); + // Този ред, без "std::move", ще хвърли грешка, + // понеже нямаме копиращи семантики + UniquePointer ptr1 = std::move(ptr); +} diff --git a/Week11/README.md b/Week11/README.md new file mode 100644 index 0000000..22e82b0 --- /dev/null +++ b/Week11/README.md @@ -0,0 +1,3 @@ +# Задачи + + -- cgit v1.3.1-23-gd82d