Website Summary Files Commits Branches @commit @diff @stats
path: root / Week09 / Exercise02 / Vector.cpp
diff options
context:
space:
mode:
Commitb38346eebca9a007971af02fb3bb9472c5e16d0c (patch)
Author
 Syndamia <kamen@syndamia.com>
2026-04-26 21:43:31 +0300
Committer
 Syndamia <kamen@syndamia.com>
2026-04-26 21:43:31 +0300
Files575a64089a17be271aec84683f426252d8f5d1f9 /Week09/Exercise02/Vector.cpp
oop-2025-solutions-b38346eebca9a007971af02fb3bb9472c5e16d0c.tar
oop-2025-solutions-b38346eebca9a007971af02fb3bb9472c5e16d0c.tar.gz
oop-2025-solutions-b38346eebca9a007971af02fb3bb9472c5e16d0c.zip
Parent7d98b664c9e459a08f2e6e6fa5b636686dfed554 (diff)
feat(Week09): Add solutions
1 files changed, 203 insertions, 0 deletions
-rw-r--r--Week09/Exercise02/Vector.cpp203
diff --git a/Week09/Exercise02/Vector.cpp b/Week09/Exercise02/Vector.cpp
new file mode 100644
index 0000000..8de9091
--- /dev/null
+++ b/Week09/Exercise02/Vector.cpp
@@ -0,0 +1,203 @@
+#include "Vector.h"
+#include <cmath>
+#include <cstring>
+
+void Vector::free() {
+ delete[] numbers;
+}
+
+void Vector::copyFrom(const Vector& other) {
+ numbersCount = other.numbersCount;
+ numbersAlloc = other.numbersAlloc;
+
+ numbers = new double[numbersAlloc];
+ for (unsigned i = 0; i < numbersCount; ++i)
+ numbers[i] = other.numbers[i];
+}
+
+Vector::Vector() {
+ numbers = nullptr;
+ numbersCount = numbersAlloc = 0;
+}
+
+Vector::~Vector() {
+ free();
+}
+
+Vector::Vector(const Vector& other) {
+ copyFrom(other);
+}
+
+Vector& Vector::operator=(const Vector& other) {
+ if (this != other.ptr()) {
+ free();
+ copyFrom(other);
+ }
+ return *this;
+}
+
+Vector::Vector(Vector&& other) {
+ numbers = other.numbers;
+ numbersCount = other.numbersCount;
+ numbersAlloc = other.numbersAlloc;
+
+ other.numbers = nullptr;
+ other.numbersCount = other.numbersAlloc = 0;
+}
+
+Vector& Vector::operator=(Vector&& other) {
+ if (this != other.ptr()) {
+ free();
+
+ numbers = other.numbers;
+ numbersCount = other.numbersCount;
+ numbersAlloc = other.numbersAlloc;
+
+ other.numbers = nullptr;
+ other.numbersCount = other.numbersAlloc = 0;
+ }
+ return *this;
+}
+
+unsigned Vector::GetCount() const {
+ return numbersCount;
+}
+
+const double* Vector::GetNumbers() const {
+ return numbers;
+}
+
+Vector& Vector::operator+=(const Vector& other) {
+ unsigned minLen = numbersCount < other.numbersCount ? numbersCount : other.numbersCount;
+ for (unsigned i = 0; i < minLen; ++i)
+ numbers[i] += other.numbers[i];
+
+ return *this;
+}
+
+Vector& Vector::operator-=(const Vector& other) {
+ unsigned minLen = numbersCount < other.numbersCount ? numbersCount : other.numbersCount;
+ for (unsigned i = 0; i < minLen; ++i)
+ numbers[i] -= other.numbers[i];
+
+ return *this;
+}
+
+
+Vector& Vector::operator*=(double scalar) {
+ for (unsigned i = 0; i < numbersCount; ++i)
+ numbers[i] *= scalar;
+
+ return *this;
+}
+
+double Vector::operator*=(const Vector& other) {
+ double dotProduct = 0.0;
+ unsigned minLen = numbersCount < other.numbersCount ? numbersCount : other.numbersCount;
+
+ for (unsigned i = 0; i < minLen; ++i)
+ dotProduct += numbers[i] * other.numbers[i];
+
+ return dotProduct;
+}
+
+Vector& Vector::operator^=(const Vector& other) {
+ // Припомняме си, че векторното умножение работи само върху
+ // триизмерни вектори
+ if (numbersCount != 3 || other.numbersCount != 3)
+ return *this;
+
+ double s[3];
+ double *a = numbers, *b = other.numbers;
+
+ s[0] = a[1] * b[2] - a[2] * b[1];
+ s[1] = a[2] * b[0] - a[0] * b[2];
+ s[2] = a[0] * b[1] - a[1] * b[0];
+
+ memcpy(a, s, sizeof(double) * 3);
+
+ return *this;
+}
+
+double Vector::operator&() const {
+ double sum = 0.0;
+ for (unsigned i = 0; i < numbersCount; ++i)
+ sum += numbers[i] * numbers[i];
+ return sqrt(sum);
+}
+
+Vector* Vector::ptr() {
+ return this;
+}
+
+const Vector* Vector::ptr() const {
+ return this;
+}
+
+Vector operator+(const Vector& lhs, const Vector& rhs) {
+ Vector ret(lhs);
+ ret += rhs;
+ return ret;
+}
+
+Vector operator-(const Vector& lhs, const Vector& rhs) {
+ // Не трябва да е нужно да обясняваме защо това
+ // е напълно същото като логиката при operator+
+ return Vector(lhs) -= rhs;
+}
+
+Vector operator*(const Vector& lhs, double scalar) {
+ return Vector(lhs) *= scalar;
+}
+
+Vector operator*(double scalar, const Vector& rhs) {
+ return rhs * scalar;
+}
+
+double operator*(const Vector& lhs, const Vector& rhs) {
+ return Vector(lhs) *= rhs;
+}
+
+Vector operator^(const Vector& lhs, const Vector& rhs) {
+ return Vector(lhs) ^= rhs;
+}
+
+bool operator||(const Vector& lhs, const Vector& rhs) {
+ unsigned minLen = lhs.GetCount() < rhs.GetCount() ? lhs.GetCount() : rhs.GetCount();
+
+ // Под "паралелни" вектори говорим повече за "колинеарни" вектори.
+ // Или с други думи, считаме дали правите, образувани от центъра 0 и
+ // един вектор съвпада с правата, образувана от центъра 0 и другия вектор.
+ // Щом лежат на една права, можем да скалираме единия вектор,
+ // така че той да стане равен на другия.
+ // С други думи, за вектори x и y, и скалар s, имаме че
+ // x || y тогава и само тогава когато съществува s: x = s*y,
+ // тстк същ. s: за всяко i: x[i] = s * y[i]
+ // тстк същ. s: вс. i: x[i] / y[i] = s
+ // тстк x[0] / y[0] = x[1] / y[1] = x[2] / y[2] = ...
+ //
+ // Алтернативно можем да вземем точковото умножение на вектори x и y,
+ // и чрез него да намерим ъгъла между двата вектора.
+ // Те ще лежат на една права ако ъгъла е 0 или 180 градуса.
+ // С други думи, ако arccos((x * y) / (&x * &y)) е 0 или PI
+ for (unsigned i = 0; i < minLen - 1; ++i) {
+ // Това коректно ли е? Възможно ли е да имаме проблеми с такова директно сравнение?
+ if (lhs.GetNumbers()[i] / rhs.GetNumbers()[i] != lhs.GetNumbers()[i+1] / rhs.GetNumbers()[i+1])
+ return false;
+ }
+ return true;
+}
+
+bool operator==(const Vector& lhs, const Vector& rhs) {
+ if (lhs.GetCount() != rhs.GetCount())
+ return false;
+
+ for (unsigned i = 0; i < lhs.GetCount(); ++i)
+ if (lhs.GetNumbers()[i] != rhs.GetNumbers()[i])
+ return false;
+ return true;
+}
+
+bool operator!=(const Vector& lhs, const Vector& rhs) {
+ return !(lhs == rhs);
+}