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; + } + } + }