diff --git a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/BoringVector.Tests.csproj b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/BoringVector.Tests.csproj
new file mode 100644
index 00000000..9836aa25
--- /dev/null
+++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/BoringVector.Tests.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net5.0
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/UnitTest1.cs b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/UnitTest1.cs
new file mode 100644
index 00000000..ab7284a2
--- /dev/null
+++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/UnitTest1.cs
@@ -0,0 +1,161 @@
+using NUnit.Framework;
+using BoringVector;
+
+namespace BoringVector.Tests
+{
+ public class SquareLengthTests
+ {
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Vector vector = new Vector(3, 4);
+ Assert.IsTrue(vector.SquareLength() == 25);
+ }
+
+ [Test]
+ public void Test2()
+ {
+ Vector vector = new Vector(0, 0);
+ Assert.IsTrue(vector.SquareLength() == 0);
+ }
+
+ [Test]
+ public void Test3()
+ {
+ Vector vector = new Vector(-1, -1);
+ Assert.IsTrue(vector.SquareLength() == 2);
+ }
+ }
+
+ public class AddTests
+ {
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(3, 4);
+ Vector vector3 = new Vector(6, 8);
+ Assert.IsTrue(vector1.Add(vector2) == vector3);
+ }
+
+ [Test]
+ public void Test2()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(-3, -4);
+ Vector vector3 = new Vector(0, 0);
+ Assert.IsTrue(vector1.Add(vector2) == vector3);
+ }
+ }
+
+ public class ScaleTests
+ {
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(6, 8);
+ Assert.IsTrue(vector1.Scale(2) == vector2);
+ }
+
+ [Test]
+ public void Test2()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(0, 0);
+ Assert.IsTrue(vector1.Scale(0) == vector2);
+ }
+
+ [Test]
+ public void Test3()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(-3, -4);
+ Assert.IsTrue(vector1.Scale(-1) == vector2);
+ }
+ }
+
+ public class DotProductTests
+ {
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(3, 4);
+ Assert.IsTrue(vector1.DotProduct(vector2) == 25);
+ }
+
+ [Test]
+ public void Test2()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(0, 0);
+ Assert.IsTrue(vector1.DotProduct(vector2) == 0);
+ }
+
+ [Test]
+ public void Test3()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(-1, -1);
+ Assert.IsTrue(vector1.DotProduct(vector2) == -7);
+ }
+ }
+
+ public class CrossProductTests
+ {
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(3, 4);
+ Assert.IsTrue(vector1.CrossProduct(vector2) == 0);
+ }
+
+ [Test]
+ public void Test2()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(0, 0);
+ Assert.IsTrue(vector1.CrossProduct(vector2) == 0);
+ }
+
+ [Test]
+ public void Test3()
+ {
+ Vector vector1 = new Vector(3, 4);
+ Vector vector2 = new Vector(-1, -1);
+ Assert.IsTrue(vector1.CrossProduct(vector2) == 1);
+ }
+ }
+}
\ No newline at end of file
diff --git a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.sln b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.sln
index ef06cdd5..c9e99913 100644
--- a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.sln
+++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.27004.2002
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoringVector", "BoringVector\BoringVector.csproj", "{7B438112-6A12-47BC-B494-FF8850924783}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoringVector.Tests", "BoringVector.Tests\BoringVector.Tests.csproj", "{5D9FAAB2-4B20-40E5-A7B5-9BFCC83FEC84}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{7B438112-6A12-47BC-B494-FF8850924783}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7B438112-6A12-47BC-B494-FF8850924783}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7B438112-6A12-47BC-B494-FF8850924783}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5D9FAAB2-4B20-40E5-A7B5-9BFCC83FEC84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5D9FAAB2-4B20-40E5-A7B5-9BFCC83FEC84}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5D9FAAB2-4B20-40E5-A7B5-9BFCC83FEC84}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5D9FAAB2-4B20-40E5-A7B5-9BFCC83FEC84}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Program.cs b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Program.cs
index f5873162..5a88f4a1 100644
--- a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Program.cs
+++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Program.cs
@@ -1,4 +1,8 @@
using System;
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("BoringVector.Tests")]
+
namespace BoringVector
{
diff --git a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Vector.cs b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Vector.cs
index bb9db585..0d6a8310 100644
--- a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Vector.cs
+++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/Vector.cs
@@ -7,13 +7,35 @@ namespace BoringVector
/*
Реализуй структуру Vector - см. комментарии внутри нее.
*/
-
+
+ ///
+ /// Совсем не скучный вектор.
+ ///
internal struct Vector
{
/*
Vector задается парой вещественных координат X и Y.
*/
-
+
+ ///
+ /// 1 координата вектора.
+ ///
+ public readonly double X;
+
+ ///
+ /// 2 координата вектора.
+ ///
+ public readonly double Y;
+
+
+ ///
+ /// Конструктор класса.
+ ///
+ public Vector(double init_x, double init_y)
+ {
+ X = init_x;
+ Y = init_y;
+ }
/*
На месте заглушек добавь реализацию базовых методов вектора:
@@ -23,31 +45,58 @@ internal struct Vector
- скалярное произведение
- векторное произведение (= площадь параллелограмма)
*/
-
+
+ ///
+ /// Возвращает квадрат длины вектора.
+ ///
public double SquareLength()
{
- throw new NotImplementedException();
+ return X * X + Y * Y;
}
+
+ ///
+ /// Складывает два вектора.
+ ///
+ /// Объект типа , который надо прибавить к данному.
+ /// Объект типа , равный сумме двух векторов.
public Vector Add(Vector v)
{
- throw new NotImplementedException();
+ return new Vector(this.X + v.X, this.Y + v.Y);
}
+
+ ///
+ /// Умножает вектор на число.
+ ///
+ /// Число, на которое умножается вектор.
+ /// Объект типа , равный данному вектору, умноженному на аргумент.
public Vector Scale(double k)
{
- throw new NotImplementedException();
+ return new Vector(this.X * k, this.Y * k);
}
+
+ ///
+ /// Возвращает скалярное произведение векторов.
+ ///
+ /// Объект типа , скалярное произведение с которым нужно получить.
+ /// Число, равное скалярному произведению векторов.
+
public double DotProduct(Vector v)
{
- throw new NotImplementedException();
+ return this.X * v.X + this.Y * v.Y;
}
public double CrossProduct(Vector v)
{
- throw new NotImplementedException();
+ return this.X * v.Y - this.Y * v.X;
}
- /*
- Переопредели ниже метод ToString - пусть выводит (X; Y)
- */
+ ///
+ /// Строковое представление вектора.
+ ///
+
+ public override string ToString()
+ {
+ return $"({this.X}; {this.Y})";
+ }
#region operators
@@ -59,6 +108,97 @@ public double CrossProduct(Vector v)
*/
#endregion
+
+ ///
+ /// Складывает два вектора.
+ ///
+ /// Объект типа , слагаемое.
+ /// Объект типа , слагаемое.
+ /// Объект типа , равный сумме векторов.
+ public static Vector operator +(Vector v, Vector u)
+ {
+ return new Vector(v.X + u.X, v.Y + u.Y);
+ }
+
+ ///
+ /// Складывает два вектора.
+ ///
+ /// Объект типа , из которого вычитаем.
+ /// Объект типа , который вычитаем.
+ /// Объект типа , равный разности векторов.
+
+ public static Vector operator -(Vector v, Vector u)
+ {
+ return new Vector(v.X - u.X, v.Y - u.Y);
+ }
+
+ ///
+ /// Умножает вектор на число.
+ ///
+ /// Число, на которое умножается вектор.
+ /// Объект типа , который умножаем на данное число.
+ /// Объект типа , равный данному вектору, умноженному на аргумент.
+ public static Vector operator *(Vector v, double k)
+ {
+ return new Vector(v.X * k, v.Y * k);
+ }
+
+ ///
+ /// Умножает вектор на число.
+ ///
+ /// Число, на которое умножается вектор.
+ /// Объект типа , который умножаем на данное число.
+ /// Объект типа , равный данному вектору, умноженному на аргумент.
+
+ public static Vector operator *(double k, Vector v)
+ {
+ return new Vector(v.X * k, v.Y * k);
+ }
+
+ ///
+ /// Делит вектор на число.
+ ///
+ /// Число, на которое делится вектор.
+ /// Объект типа , который делим на данное число.
+ /// Объект типа , равный данному вектору, поделенному на аргумент.
+
+ public static Vector operator /(double k, Vector v)
+ {
+ return new Vector(v.X / k, v.Y / k);
+ }
+
+ ///
+ /// Возвращает данный вектор со знаком +.
+ ///
+ public static Vector operator +(Vector v)
+ {
+ return v;
+ }
+
+ ///
+ /// Возвращает противоположный вектор.
+ ///
+ public static Vector operator -(Vector v)
+ {
+ return new Vector(-v.X, -v.Y);
+ }
+
+ ///
+ /// Проверяет два вектора на равенство.
+ ///
+ public static bool operator ==(Vector v, Vector u)
+ {
+ return v.X == u.X && v.Y == u.Y;
+ }
+
+ ///
+ /// Проверяет два вектора на неравенство.
+ ///
+ public static bool operator !=(Vector v, Vector u)
+ {
+ return v.X != u.X || v.Y != u.Y;
+ }
+
}
#endregion
diff --git a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/VectorExtensions.cs b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/VectorExtensions.cs
index 525be40f..256e964b 100644
--- a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/VectorExtensions.cs
+++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector/VectorExtensions.cs
@@ -1,4 +1,6 @@
-namespace BoringVector
+using System;
+
+namespace BoringVector
{
/*
Здесь тебе нужно написать класс с методами-расширениями структуры Vector:
@@ -7,4 +9,50 @@
- GetAngleBetween: возвращает угол между двумя векторами в радианах. Примечание: нулевой вектор сонаправлен любому другому.
- GetRelation: возвращает значение перечесления VectorRelation(General, Parallel, Orthogonal) - отношение между двумя векторами("общий случай", параллельны, перпендикулярны). Перечисление задавать тоже тебе)
*/
+
+ public static class VectorEx
+ {
+ internal static bool IsZero(this Vector v)
+ {
+ return (Math.Abs(v.X) < 1e-6) && (Math.Abs(v.Y) < 1e-6);
+ }
+
+ internal static Vector Normalize(this Vector v)
+ {
+ return v.Scale(1/Math.Sqrt(v.SquareLength()));
+ }
+
+ internal static double GetAngleBetween(this Vector v, Vector u)
+ {
+ if (IsZero(v) || IsZero(u))
+ {
+ return 0;
+ }
+
+ return Math.Acos(Normalize(v).DotProduct(Normalize(u)));
+ }
+
+ internal enum VectorRelation
+ {
+ General,
+ Parallel,
+ Orthogonal
+ }
+
+ internal static VectorRelation GetRelation(this Vector v, Vector u)
+ {
+ if (GetAngleBetween(u, v) == 0)
+ {
+ return VectorRelation.Parallel;
+ }
+
+ if (u.DotProduct(v) == 0)
+ {
+ return VectorRelation.Orthogonal;
+ }
+
+ return VectorRelation.General;
+ }
+ }
+
}