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..6025fe64 --- /dev/null +++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/BoringVector.Tests.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp3.1 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + 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..c7c4bbf1 --- /dev/null +++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/UnitTest1.cs @@ -0,0 +1,42 @@ +using System; +using Xunit; + +namespace BoringVector.Tests +{ + public class UnitTest1 + { + [Theory] + [InlineData(0, 0, 0)] + [InlineData(3, 4, 25)] + [InlineData(0, 1, 1)] + [InlineData(1, 1, 2)] + public void Test_SquareLength(double x, double y, double z) + { + Assert.Equal(new Vector(x, y).SquareLength(), z); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(3, 4, 25, 123)] + [InlineData(0, 1, 1, 10)] + [InlineData(1, 5, 1, 2)] + public void Test_Add(double x, double y, double a, double b) + { + var tmp = new Vector(x, y).Add(new Vector(a, b)); + Assert.Equal(x + a, tmp.X); + Assert.Equal(y + b, tmp.Y); + } + + [Theory] + [InlineData(0, 5, 0)] + [InlineData(4, 25, 123)] + [InlineData(1, 1, 10)] + [InlineData(5, 1, 2)] + public void Test_Scale(double x, double y, double k) + { + var tmp = new Vector(x, y).Scale(k); + Assert.Equal(x * k, tmp.X); + Assert.Equal(y * k, tmp.Y); + } + } +} 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..33ed6758 100644 --- a/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.sln +++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.sln @@ -1,9 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2002 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31229.75 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoringVector", "BoringVector\BoringVector.csproj", "{7B438112-6A12-47BC-B494-FF8850924783}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BoringVector", "BoringVector\BoringVector.csproj", "{7B438112-6A12-47BC-B494-FF8850924783}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BoringVector.Tests", "BoringVector.Tests\BoringVector.Tests.csproj", "{F43CA846-71FE-4428-BAD4-A4ADDBF9A784}" + ProjectSection(ProjectDependencies) = postProject + {7B438112-6A12-47BC-B494-FF8850924783} = {7B438112-6A12-47BC-B494-FF8850924783} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +20,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 + {F43CA846-71FE-4428-BAD4-A4ADDBF9A784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F43CA846-71FE-4428-BAD4-A4ADDBF9A784}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F43CA846-71FE-4428-BAD4-A4ADDBF9A784}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F43CA846-71FE-4428-BAD4-A4ADDBF9A784}.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..ace88470 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,6 @@ 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..b9bc95cc 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,12 +7,16 @@ namespace BoringVector /* Реализуй структуру Vector - см. комментарии внутри нее. */ - + /// + /// Структура вектора в двумерном пространстве. + /// internal struct Vector { - /* - Vector задается парой вещественных координат X и Y. - */ + /// + /// Координаты вектора X и Y. + /// + public readonly double X; + public readonly double Y; /* @@ -23,32 +27,72 @@ internal struct Vector - скалярное произведение - векторное произведение (= площадь параллелограмма) */ - + /// + /// Констурктор вектора по координатам X и Y. + /// + /// Координата вектора по Ox. + /// Координата вектора по Oy. + public Vector(double x, double y) + { + X = x; + Y = y; + } + /// + /// Возвращает квадрат длины вектора. + /// + /// Вещественное число. public double SquareLength() { - throw new NotImplementedException(); + return X * X + Y * Y; } + /// + /// Прибавление другого вектора к исходному. + /// + /// Вектор. + /// Результирующий вектор. public Vector Add(Vector v) { - throw new NotImplementedException(); + return new Vector(X + v.X, Y + v.Y); } + /// + /// Умножение вектора на коэффициент k. + /// + /// Коэффициент. + /// Результирующий вектор. public Vector Scale(double k) { - throw new NotImplementedException(); + return new Vector(k * X, k * Y); } + /// + /// Скалярное произведение векторов. + /// + /// Вектор, с которым происхоит умножение. + /// Вещественное число. public double DotProduct(Vector v) { - throw new NotImplementedException(); + return X * v.X + Y * v.Y; } + /// + /// Векторное произведение векторов. + /// + /// Вектор, с которым происхоит умножение. + /// Вещественное число. public double CrossProduct(Vector v) { - throw new NotImplementedException(); + return X * v.Y - Y * v.X; } /* Переопредели ниже метод ToString - пусть выводит (X; Y) */ - + /// + /// Вектор в формате (X; Y). + /// + /// Строка. + public override string ToString() + { + return String.Format("({0}; {1})", X, Y); + } #region operators /* @@ -57,6 +101,76 @@ public double CrossProduct(Vector v) - k * v, v * k, v / k - +v, -v */ + /// + /// Вычисление суммы векторов. + /// + /// Первый вектор. + /// Второй вектор. + /// Результирующий вектор от суммы. + public static Vector operator +(Vector v, Vector u) + { + return v.Add(u); + } + /// + /// Вычисление разности векторов. + /// + /// Первый вектор. + /// Второй вектор. + /// Результирующий вектор от разности. + public static Vector operator -(Vector v, Vector u) + { + return v.Add(u.Scale(-1)); + } + /// + /// Умножение вектора на коэффициент. + /// + /// Исходный вектор. + /// Коэффициент. + /// Результирующий вектор от уможения. + public static Vector operator *(Vector v, double k) + { + return v.Scale(k); + } + /// + /// Умножение вектора на коэффициент. + /// + /// Коэффициент. + /// Исходный вектор. + /// Результирующий вектор от уможения. + public static Vector operator *(double k, Vector v) + { + return v.Scale(k); + } + /// + /// Деление вектора на коэффициент. + /// + /// Исходный вектор. + /// Коэффициент. + /// Результирующий вектор от деления. + public static Vector operator /(Vector v, double k) + { + if (k == 0) + throw new DivideByZeroException(); + return v.Scale(1 / k); + } + /// + /// Возвращает вектор. + /// + /// Исходный вектор. + /// Исходынй вектор. + public static Vector operator +(Vector v) + { + return v; + } + /// + /// Возвращает противоположный вектор. + /// + /// Исходынй вектор. + /// Противоположный вектор. + public static Vector operator -(Vector v) + { + return v.Scale(-1); + } #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..2caea2e9 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,77 @@ - GetAngleBetween: возвращает угол между двумя векторами в радианах. Примечание: нулевой вектор сонаправлен любому другому. - GetRelation: возвращает значение перечесления VectorRelation(General, Parallel, Orthogonal) - отношение между двумя векторами("общий случай", параллельны, перпендикулярны). Перечисление задавать тоже тебе) */ + + /// + /// Расширяющий класс Vector. + /// + internal static class VectorExtensions + { + /// + /// Эпсилон. + /// + private const double eps = 1e-6; + /// + /// Перечисления - отношение между двумя векторами("общий случай", параллельны, перпендикулярны). + /// + internal enum VectorRelation + { + General, Parallel, Orthogonal + } + /// + /// Проверяет, является ли вектор нулевым. + /// + /// Исходный вектор. + /// True, если вектор нулевой, иначе False + public static bool IsZero(this Vector v) + { + return Math.Abs(v.X) < eps && Math.Abs(v.Y) < eps; + } + /// + /// Нормализует вектор (если он не нулевой). + /// + /// Исходный вектор. + /// Нормализованный вектор. + public static Vector Normalize(this Vector v) + { + if (IsZero(v)) + return v; + return v / Math.Sqrt(v.SquareLength()); + } + /// + /// Вычисление угла между векторами. + /// + /// Первый вектор. + /// Второй. + /// Угол между векторами в радианах от 0 до PI. + public static double GetAngleBetween(this Vector v, Vector u) + { + if (IsZero(v) || IsZero(u)) + { + return 0; + } + + return Math.Acos(Normalize(v).DotProduct(Normalize(u))); + } + /// + /// Вычисление отношения между двумя заданными векторами. + /// + /// Первый вектор. + /// Второй вектор. + /// Отношение между двумя векторами("общий случай", параллельны, перпендикулярны). + public static VectorRelation GetRelation(this Vector v, Vector u) + { + var ang = GetAngleBetween(v, u); + + if (ang < eps || Math.PI - ang < eps) + { + return VectorRelation.Parallel; + } + if (Math.Abs(Math.PI / 2 - ang) < eps) + { + return VectorRelation.Orthogonal; + } + return VectorRelation.General; + } + } }