diff --git a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs index af4efcae..aded548a 100644 --- a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs +++ b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Program.cs @@ -1,9 +1,71 @@ -namespace AdventureTime +using System; + +namespace AdventureTime { internal class Program { private static void Main() { + DateTime dt = Time.WhatTimeIsIt(); + DateTimeKind kind = DateTimeKind.Utc; + // 1 + // Console.WriteLine(Time.WhatTimeIsItInUtc()); + + // 2 + // Console.WriteLine(dt); + // Console.WriteLine(Time.SpecifyKind(dt, kind)); + + // 3 + //Console.WriteLine(Time.ToRoundTripFormatString(dt)); + + // 4 + /* + Console.WriteLine(Time.SpecifyKind(dt, DateTimeKind.Local).ToString("o")); + Console.WriteLine(Time.SpecifyKind(dt, DateTimeKind.Unspecified).ToString("o")); + Console.WriteLine(Time.SpecifyKind(dt, DateTimeKind.Utc).ToString("o")); + */ + + // 5 + //Console.WriteLine(dt); + //Console.WriteLine(Time.ParseFromRoundTripFormat(Time.ToRoundTripFormatString(dt))); + + // 6 + //Console.WriteLine(Time.ToUtc(dt)); + + // 7 + //Console.WriteLine(dt); + //Console.WriteLine(Time.AddTenSeconds(dt)); + + // 8 + //Console.WriteLine(dt); + //Console.WriteLine(Time.AddTenSecondsV2(dt)); + + // 9 + DateTime test_dt = new DateTime(2021, 5, 24, 2, 15, 0); + //Console.WriteLine(Time.GetHoursBetween(dt, Time.SpecifyKind(test_dt, DateTimeKind.Utc))); + + // 10 + //Console.WriteLine(Time.GetTotalMinutesInThreeMonths()); + + // 11 + //Console.WriteLine(Time.GetAdventureTimeDurationInMinutes_ver0_Dumb()); + + // 12 + //Console.WriteLine(Time.GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb()); + + // 13 + //Console.WriteLine(Time.GetAdventureTimeDurationInMinutes_ver1_FeelsSmarter()); + + // 14 + //Console.WriteLine(Time.GetAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience()); + + // 15 + //Console.WriteLine(Time.GetGenderSwappedAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience()); + + // ... + + // 16 + //Console.WriteLine(Time.AreEqualBirthdays(dt, test_dt)); } } } diff --git a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs index 45de70d1..2a657e94 100644 --- a/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs +++ b/course-2021-1/exercises/02-adventure-time/AdventureTime/AdventureTime/Time.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using NodaTime; using NodaTime.TimeZones; @@ -14,7 +15,7 @@ internal static class Time /// public static DateTime WhatTimeIsIt() { - throw new NotImplementedException(); + return DateTime.Now; } /// @@ -22,7 +23,7 @@ public static DateTime WhatTimeIsIt() /// public static DateTime WhatTimeIsItInUtc() { - throw new NotImplementedException(); + return DateTime.UtcNow; } /// @@ -36,7 +37,7 @@ public static DateTime SpecifyKind(DateTime dt, DateTimeKind kind) /* Подсказка: поищи в статических методах DateTime. */ - throw new NotImplementedException(); + return DateTime.SpecifyKind(dt, kind); } /// @@ -51,7 +52,7 @@ public static string ToRoundTripFormatString(DateTime dt) Ну и на будущее запомни этот прекрасный строковый формат представления времени - он твой бро! Название запоминать не нужно, просто помни, что для передачи значения в виде строки, выбирать лучше инвариантные относительно сериализации/десериализации форматы. */ - throw new NotImplementedException(); + return dt.ToString("O"); } /// @@ -65,7 +66,7 @@ public static DateTime ParseFromRoundTripFormat(string dtStr) Поиграйся и проверь, что round-trip действительно round-trip, т.е. туда-обратно равно оригиналу (для туда воспользуйся предыдущим методом). Проверь для всех значений DateTime.Kind. */ - throw new NotImplementedException(); + return DateTime.Parse(dtStr); } /// @@ -77,7 +78,7 @@ public static DateTime ToUtc(DateTime dt) Eсли воспользуешься нужным методом, то напоминаю, что результат его работы зависит от dt.Kind. В случае dt.Kind == Unspecified предполагается, что время локальное, т.е. результат работы в случае Local и Unspecified совпадают. Такие дела */ - throw new NotImplementedException(); + return dt.ToUniversalTime(); } /// @@ -88,7 +89,7 @@ public static DateTime ToUtc(DateTime dt) public static DateTime AddTenSeconds(DateTime dt) { // здесь воспользуйся методами самого объекта и заодно посмотри какие еще похожие есть - throw new NotImplementedException(); + return dt.AddSeconds(10); } /// @@ -102,7 +103,8 @@ public static DateTime AddTenSecondsV2(DateTime dt) Ну а здесь воспользуйся сложением с TimeSpan. Обрати внимание, что помимо конструктора, у класса есть набор полезных статических методов-фабрик. Обрати внимание, что у TimeSpan нет статических методов FromMonth, FromYear. Как думаешь, почему? */ - throw new NotImplementedException(); + // в месяцах и годах переменное количество дней + return dt + TimeSpan.FromSeconds(10); } /// @@ -118,7 +120,10 @@ public static int GetHoursBetween(DateTime dt1, DateTime dt2) 2) Проверь, учитывается ли Kind объектов при арифметических операциях. 3) Подумай, почему возвращаемое значение может отличаться от действительности. */ - throw new NotImplementedException(); + // `Hours` возвращает число часов в записи времени, а `TotalHours` возвращает полное время в часах + // При попытке найти разницу между датой с local и датой, которая переведена в utc, разница не обнаружилась + // если даты в разных часовых поясах, то разница будет ещё включать разницу поясов + return (int)dt1.Subtract(dt2).TotalHours; } /// @@ -127,7 +132,9 @@ public static int GetHoursBetween(DateTime dt1, DateTime dt2) public static int GetTotalMinutesInThreeMonths() { // ну тут все просто и очевидно, если сделал остальные и подумал над вопросами в комментах. - throw new NotImplementedException(); + DateTime curr_dt = DateTime.UtcNow; + DateTime three_month_from_curr_dt = curr_dt.AddMonths(3); + return (int) three_month_from_curr_dt.Subtract(curr_dt).TotalMinutes; } #region Adventure time saga @@ -147,7 +154,10 @@ public static int GetAdventureTimeDurationInMinutes_ver0_Dumb() Держи, заготовочку для копипасты: - 2010, 3, 28, 2, 15, 0 */ - throw new NotImplementedException(); + var from = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(3)); + var to = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(0)); + + return (int)to.Subtract(from).TotalMinutes; } /// @@ -165,7 +175,9 @@ public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb() - 2010, 3, 28, 3, 15, 0 - 2010, 3, 28, 1, 15, 0 */ - throw new NotImplementedException(); + var from = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(3)); + var to = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.FromHours(0)); + return (int)to.Subtract(from).TotalMinutes; } /// @@ -180,7 +192,9 @@ public static int GetAdventureTimeDurationInMinutes_ver1_FeelsSmarter() На самом деле смещения таковы: Лондон +1 (BST - British Summer Time), Москва +4 (MSD - Moscow Daylight Time). Давай теперь учтем правильное смещение. Я понимаю, что это очевидно, что результат не изменится, но тебе же не сложно скопипастить и просто поменять смещения? */ - throw new NotImplementedException(); + var from = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(4)); + var to = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.FromHours(1)); + return (int)to.Subtract(from).TotalMinutes; } // GetGenderSwappedAdventureTimeDurationInMinutes_ver1_FeelsSmarter опустим, там то же самое @@ -202,10 +216,18 @@ public static int GetAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience( ниже ты найдешь готовый метод GetZonedTime. Просто посмотри на него (можешь даже посмотреть методы и свойства типа TimeZoneInfo, если интересно) и воспользуйся им для вычисления правильного времени "отбытия" и "прибытия" наших героев. Затем посчитай длительность путешествия. Также даны правильные идентификаторы зон. */ + // таких зон не существует + /* const string moscowZoneId = "Russian Standard Time"; const string londonZoneId = "GMT Standard Time"; - - throw new NotImplementedException(); + */ + const string moscowZoneId = "Europe/Moscow"; + const string londonZoneId = "Europe/London"; + + var from = GetZonedTime(new DateTime(2010, 3, 28, 2, 15, 0), moscowZoneId); + var to = GetZonedTime(new DateTime(2010, 3, 28, 2, 15, 0), londonZoneId); + + return (int)to.Subtract(from).TotalMinutes; } /// @@ -216,9 +238,13 @@ public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver2_FeelsLikeR /* Реши по аналогии с предыдущим методом и проверь, что оба метода действительно возвращают одно и то же время (и что оно правильное). */ - const string moscowZoneId = "Russian Standard Time"; - const string londonZoneId = "GMT Standard Time"; - throw new NotImplementedException(); + const string moscowZoneId = "Europe/Moscow"; + const string londonZoneId = "Europe/London"; + + var from = Time.GetZonedTime(new DateTime(2010, 3, 28, 3, 15, 0), moscowZoneId); + var to = Time.GetZonedTime(new DateTime(2010, 3, 28, 1, 15, 0), londonZoneId); + + return (int)to.Subtract(from).TotalMinutes; } private static DateTimeOffset GetZonedTime(DateTime localTime, string timeZoneId) @@ -277,7 +303,7 @@ private static ZonedDateTime GetZonedTime(LocalDateTime localTime, string timeZo /// True - если родились в один день, иначе - false. internal static bool AreEqualBirthdays(DateTime person1Birthday, DateTime person2Birthday) { - throw new NotImplementedException(); + return person1Birthday.Date.ToUniversalTime() == person2Birthday.Date.ToUniversalTime(); } } } diff --git a/course-2021-1/exercises/02-adventure-time/readme.md b/course-2021-1/exercises/02-adventure-time/readme.md index 67401923..d382c58a 100644 --- a/course-2021-1/exercises/02-adventure-time/readme.md +++ b/course-2021-1/exercises/02-adventure-time/readme.md @@ -1,4 +1,4 @@ -# 02. Primitive types +ow to# 02. Primitive types ## Entry point 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..ec53f732 --- /dev/null +++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/BoringVector.Tests.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp2.1 + + 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..4fec4a5a --- /dev/null +++ b/course-2021-1/exercises/03-boring-vector/BoringVector/BoringVector.Tests/UnitTest1.cs @@ -0,0 +1,67 @@ +using System; +using System.Runtime.InteropServices; +using Xunit; + +namespace BoringVector.Tests +{ + /* + SquareLength + Add + Scale + DotProduct + CrossProduct + */ + public class BoringVectorTest + { + [Theory] + [InlineData(1, 1, 2)] + [InlineData(2, -2, 8)] + public void SquareLengthTest(double X, double Y, double l) + { + Vector test = new Vector(X, Y); + Assert.Equal(l, test.SquareLength()); + } + + [Theory] + [InlineData(1, 1, 0, 0, 1, 1)] + [InlineData(1, 1, -1, -1, 0, 0)] + public void AddTest(double X1, double Y1, double X2, double Y2, double X3, double Y3) + { + Vector test1 = new Vector(X1, Y1); + Vector test2 = new Vector(X2, Y2); + Vector test3 = test1.Add(test2); + Assert.Equal(X3, test3.X); + Assert.Equal(Y3, test3.Y); + } + + [Theory] + [InlineData(1, 1, 2, 2, 2)] + public void ScaleTest(double X1, double Y1, double k, double X2, double Y2) + { + Vector test1 = new Vector(X1, Y1); + Vector test2 = test1.Scale(k); + Assert.Equal(X2, test2.X); + Assert.Equal(Y2, test2.Y); + } + + [Theory] + [InlineData(1, 2, 1, -1, -1)] + public void DotProductTest(double X1, double Y1, double X2, double Y2, double dp) + { + Vector test1 = new Vector(X1, Y1); + Vector test2 = new Vector(X2, Y2); + double test = test1.DotProduct(test2); + Assert.Equal(dp, test); + } + + [Theory] + [InlineData(2, 2, 1, -1, -4)] + public void CrossProductTest(double X1, double Y1, double X2, double Y2, double cp) + { + Vector test1 = new Vector(X1, Y1); + Vector test2 = new Vector(X2, Y2); + double test = test1.CrossProduct(test2); + Assert.Equal(cp, test); + } + } +} \ 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..4fc8d040 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", "{583A57E0-A7B1-486A-81FD-5746100C2C06}" +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 + {583A57E0-A7B1-486A-81FD-5746100C2C06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {583A57E0-A7B1-486A-81FD-5746100C2C06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {583A57E0-A7B1-486A-81FD-5746100C2C06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {583A57E0-A7B1-486A-81FD-5746100C2C06}.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..1a532317 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 @@ -6,7 +6,9 @@ internal class Program { private static void Main() { - Console.WriteLine("Hello World!"); + double a = 1.2; + double b = 0.32; + Console.WriteLine("(" + a.ToString() + "; " + b.ToString() + ")"); } } } 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..bd079444 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,29 @@ namespace BoringVector /* Реализуй структуру Vector - см. комментарии внутри нее. */ - - internal struct Vector + + /// + /// Класс, реализующий логику двумерного вещественного вектора (X, Y) + /// + public struct Vector { /* Vector задается парой вещественных координат X и Y. */ + public readonly double X; + public readonly double Y; + + /// + /// Создает вектор (x, y) + /// + /// Первая координата + /// Вторая координата + public Vector(double X, double Y) + { + this.X = X; + this.Y = Y; + } /* На месте заглушек добавь реализацию базовых методов вектора: @@ -23,32 +39,69 @@ internal struct Vector - скалярное произведение - векторное произведение (= площадь параллелограмма) */ - + + /// + /// Вычисляет длину вектора X^2 + Y^2 + /// + /// this.X ** 2 + this.Y ** 2 public double SquareLength() { - throw new NotImplementedException(); + return Math.Pow(this.X, 2) + Math.Pow(this.Y, 2); } + + /// + /// Вычисляет сумму векторов + /// + /// Правый вектор суммы + /// (this.X + v.X, this.Y + v.Y) public Vector Add(Vector v) { - throw new NotImplementedException(); + return new Vector(this.X + v.X, this.Y + v.Y); } + + /// + /// Умножает вектор на скаляр + /// + /// Скаляр + /// (k * this.X, k * this.Y) public Vector Scale(double k) { - throw new NotImplementedException(); + return new Vector(this.X * k, this.Y * k); } + + /// + /// Вычисляет скалярное произведение + /// + /// Правый вектор произведения + /// X * v.X + Y * v.Y public double DotProduct(Vector v) { - throw new NotImplementedException(); + return this.X * v.X + this.Y * v.Y; } + + /// + /// Вычисляет векторное произведение векторов (ориентированную площадь параллелограмма) + /// + /// Правый вектор произведения + /// [this, v] public double CrossProduct(Vector v) { - throw new NotImplementedException(); + return this.X * v.Y - this.Y * v.X; } /* Переопредели ниже метод ToString - пусть выводит (X; Y) */ + /// + /// Возвращает строку, представляющую вектор + /// + /// (this.X; this.Y) + public override string ToString() + { + return $"({this.X.ToString()}; {this.Y.ToString()})"; + } + #region operators /* @@ -57,6 +110,80 @@ public double CrossProduct(Vector v) - k * v, v * k, v / k - +v, -v */ + + /// + /// Вычисляет сумму векторов + /// + /// Левый вектор суммы + /// Правый вектор суммы + /// (a.X + b.X, a.Y + b.Y) + public static Vector operator +(Vector a, Vector b) + { + return a.Add(b); + } + + /// + /// Вычисляет Разность векторов + /// + /// Уменьшаемое + /// Вычитаемое + /// (a.X - b.X, a.Y - b.Y) + public static Vector operator -(Vector a, Vector b) + { + return a.Add(b.Scale(-1)); + } + + /// + /// Умножает вектор на скаляр + /// + /// Скаляр + /// Вектор + /// (k * a.X, k * a.Y) + public static Vector operator *(Vector a, double k) + { + return a.Scale(k); + } + + /// + /// Умножает вектор на скаляр + /// + /// Скаляр + /// Вектор + /// (k * a.X, k * a.Y) + public static Vector operator *(double k, Vector a) + { + return a.Scale(k); + } + + /// + /// Делит вектор на скаляр + /// + /// Вектор + /// Скаляр + /// (a.X / k, a.Y / k) + public static Vector operator /(double k, Vector a) + { + return a.Scale(1.0 / k); + } + + /// + /// Возвращает полученный вектор, ничего не делая с ним + /// + /// Вектор + public static Vector operator +(Vector a) + { + return a; + } + + /// + /// Возвращает вектор, умноженный на -1 + /// + /// Вектор + /// -v + public static Vector operator -(Vector a) + { + return a.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..d4e09db6 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,79 @@ - GetAngleBetween: возвращает угол между двумя векторами в радианах. Примечание: нулевой вектор сонаправлен любому другому. - GetRelation: возвращает значение перечесления VectorRelation(General, Parallel, Orthogonal) - отношение между двумя векторами("общий случай", параллельны, перпендикулярны). Перечисление задавать тоже тебе) */ + + /// + /// Класс, расширяющий функциональность двумерного вектора + /// + public static class VectorExtention + { + /// + /// Проверяет, является ли вектор нулевым (с точностью до eps) + /// + /// Вектор + /// Равен ли вектор нулевому + internal static bool IsZero(Vector v) + { + return Math.Abs(v.X) < 1e-6 && Math.Abs(v.Y) < 1e-6; + } + + /// + /// Нормализует вектор (приводит к длине 1, если он ненулевой) + /// + /// Вектор + /// v / |v| + internal static Vector Normalize(Vector v) + { + return v.Scale(1/Math.Sqrt(v.SquareLength())); + } + + /// + /// Считает угол между v и u в радианах + /// + /// Первый вектор + /// Второй вектор + /// Угол между v и u + internal static double GetAngleBetween(Vector v, Vector u) + { + if (IsZero(v) || IsZero(u)) + { + return 0; + } + else + { + return Math.Acos(Normalize(v).DotProduct(Normalize(u))); + } + } + + /// + /// Перечисление, определяющая взаимное расположение векторов в пространстве + /// + internal enum VectorRelation + { + General, + Parallel, + Orthogonal + } + + /// + /// Определяет взаимное расположение между векторами + /// + /// Первый вектор + /// Второй вектор + /// Взаимное расположение между v и u + internal static VectorRelation GetRelation(Vector v, Vector u) + { + if (GetAngleBetween(u, v) == 0) + { + return VectorRelation.Parallel; + } + + if (u.DotProduct(v) == 0) + { + return VectorRelation.Orthogonal; + } + + return VectorRelation.General; + } + } } diff --git a/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/RicksMercilessEncryptorTests.cs b/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/RicksMercilessEncryptorTests.cs index 434f02aa..f4292f92 100644 --- a/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/RicksMercilessEncryptorTests.cs +++ b/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/RicksMercilessEncryptorTests.cs @@ -1,10 +1,83 @@ using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; using Xunit; +using WubbaLubbaDubDub; namespace WubbaLubbaDubDub.Tests { public class RicksMercilessEncryptorTests { + + [Theory] + [InlineData("a\nb\nc", new string[] {"a", "b", "c"})] + public void Test_SplitToLine(string s, string[] res) + { + Assert.Equal(s.SplitToLines(), res); + } + [Theory] + [InlineData("aba caba\nabca", new string[] { "aba", "caba", "abca"})] + public void Test_SplitToWords(string s, string[] res) + { + Assert.Equal(s.SplitToWords(), res); + } + + [Theory] + [InlineData("abacaba", "aba")] + public void Test_GetLeftHalf(string s, string res) + { + Assert.Equal(s.GetLeftHalf(), res); + } + + [Theory] + [InlineData("abacaba", "caba")] + public void Test_GetRightHalf(string s, string res) + { + Assert.Equal(s.GetRightHalf(), res); + } + + [Theory] + [InlineData("chucha", "ch", "zh", "zhuzha")] + public void Test_Replace(string s, string r, string to, string res) + { + Assert.Equal(s.Replace(r, to), res); + } + + [Theory] + [InlineData("z", "\\u007A")] + public void Test_CharsToCodes(string s, string res) + { + Assert.Equal(s.CharsToCodes(), res); + } + + [Theory] + [InlineData("abcd", "dcba")] + public void Test_GetReversed(string s, string res) + { + Assert.Equal(s.GetReversed(), res); + } + + [Theory] + [InlineData("aBcD", "AbCd")] + public void Test_InverseCase(string s, string res) + { + Assert.Equal(s.InverseCase(), res); + } + + [Theory] + [InlineData("abc", "bcd")] + public void Test_ShiftInc(string s, string res) + { + Assert.Equal(s.ShiftInc(), res); + } + [Theory] + [InlineData("¶1234:5678¶ ¶1234:5678¶", new long[] { 0x12345678 })] + [InlineData("¶1234:5678¶/*testesttest*/¶1234:5678¶", new long[] { 0x12345678 })] + public void Test_GetUsedObjects(string s, long[] list) + { + Assert.Equal(s.GetUsedObjects(), list); + } } -} +} \ No newline at end of file diff --git a/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/WubbaLubbaDubDub.Tests.csproj b/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/WubbaLubbaDubDub.Tests.csproj index aa2f23f5..d20f497e 100644 --- a/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/WubbaLubbaDubDub.Tests.csproj +++ b/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub.Tests/WubbaLubbaDubDub.Tests.csproj @@ -12,4 +12,8 @@ + + + + diff --git a/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub/RicksMercilessEncryptor.cs b/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub/RicksMercilessEncryptor.cs index 1063065b..dee6ae08 100644 --- a/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub/RicksMercilessEncryptor.cs +++ b/course-2021-1/exercises/04-wubba-lubba-dub-dub/WubbaLubbaDubDub/WubbaLubbaDubDub/RicksMercilessEncryptor.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Globalization; +using System.Linq; +using System.Text.RegularExpressions; namespace WubbaLubbaDubDub { @@ -12,7 +15,7 @@ public static class RicksMercilessEncryptor public static string[] SplitToLines(this string text) { // У строки есть специальный метод. Давай здесь без регулярок - throw new NotImplementedException(); + return text.Split('\n'); } /// @@ -21,7 +24,14 @@ public static string[] SplitToLines(this string text) public static string[] SplitToWords(this string line) { // А вот здесь поиграйся с регулярками. - throw new NotImplementedException(); + Regex regex = new Regex(@"\w+"); + MatchCollection matches = regex.Matches(line); + string[] words = new string[matches.Count]; + for (int i = 0; i < matches.Count; ++i) + { + words[i] = matches[i].Value; + } + return words; } /// @@ -31,7 +41,7 @@ public static string[] SplitToWords(this string line) public static string GetLeftHalf(this string s) { // у строки есть метод получения подстроки - throw new NotImplementedException(); + return s.Substring(0, s.Length / 2); } /// @@ -40,7 +50,7 @@ public static string GetLeftHalf(this string s) /// public static string GetRightHalf(this string s) { - throw new NotImplementedException(); + return s.Substring(s.Length / 2); } /// @@ -49,7 +59,7 @@ public static string GetRightHalf(this string s) public static string Replace(this string s, string old, string @new) { // и такой метод у строки, очевидно, тоже есть - throw new NotImplementedException(); + return s.Replace(old, @new); } /// @@ -65,7 +75,17 @@ public static string CharsToCodes(this string s) FYI: локальную функцию можно объявлять даже после строки с return. То же самое можно сделать и для всех оставшихся методов. */ - throw new NotImplementedException(); + string[] encode(char[] symbols) + { + string[] output = new String[symbols.Length]; + for (int i = 0; i < symbols.Length; ++i) + { + output[i] = "\\u" + ((int) symbols[i]).ToString("X4"); + } + return output; + } + + return String.Concat(encode(s.ToCharArray())); } /// @@ -77,7 +97,7 @@ public static string GetReversed(this string s) Собрать строку из последовательности строк можно несколькими способами. Один из низ - статический метод Concat. Но ты можешь выбрать любой. */ - throw new NotImplementedException(); + return String.Concat(s.ToCharArray().Reverse()); } /// @@ -90,7 +110,23 @@ public static string InverseCase(this string s) На минуту задержись здесь и посмотри, какие еще есть статические методы у char. Например, он содержит методы-предикаты для определения категории Юникода символа, что очень удобно. */ - throw new NotImplementedException(); + char[] ReverseCase(char[] symbols) + { + for (int i = 0; i < symbols.Length; ++i) + { + if (char.IsLower(symbols[i])) + { + symbols[i] = char.ToUpper(symbols[i]); + } + else + { + symbols[i] = char.ToLower(symbols[i]); + } + } + return symbols; + } + + return String.Concat(ReverseCase(s.ToCharArray())); } /// @@ -99,7 +135,16 @@ public static string InverseCase(this string s) /// public static string ShiftInc(this string s) { - throw new NotImplementedException(); + char[] nextChar(char[] symbols) + { + for (int i = 0; i < symbols.Length; ++i) + { + symbols[i] = (char)(symbols[i] + 1); + } + return symbols; + } + + return String.Concat(nextChar(s.ToCharArray())); } @@ -107,7 +152,7 @@ public static string ShiftInc(this string s) /// /// Возвращает список уникальных идентификаторов объектов, используемых в тексте . - /// Идентификаторы объектов имеют длину 8байт и представлены в тексте в виде ¶X:Y¶, где X - старшие 4 байта, а Y - младшие 4 байта. + /// Идентификаторы объектов имеют длину 8 байт и представлены в тексте в виде ¶X:Y¶, где X - старшие 4 байта, а Y - младшие 4 байта. /// Текст так же содержит строчные (//) и блоковые (/**/) комментарии, которые нужно игнорировать. /// Т.е. в комментариях идентификаторы объектов искать не нужно. И, кстати, блоковые комментарии могут быть многострочными. /// @@ -117,7 +162,20 @@ public static IImmutableList GetUsedObjects(this string text) Задача на поиграться с регулярками - вся сложность в том, чтобы аккуратно игнорировать комментарии. Экспериментировать онлайн можно, например, здесь: http://regexstorm.net/tester и https://regexr.com/ */ - throw new NotImplementedException(); + text = Regex.Replace(text, @"\/\/.*", ""); + text = Regex.Replace(text, @"\/\*(.|\n)*?\*\/", ""); + + Regex regex_for_pattern = new Regex(@"¶\w{4}:\w{4}¶"); + MatchCollection matches = regex_for_pattern.Matches(text); + List ids = new List(); + for (int i = 0; i < matches.Count; ++i) + { + String id_string = matches[i].ToString(); + id_string = id_string.Replace(":",""); + id_string = id_string.Replace("¶",""); + ids.Add(long.Parse(id_string, NumberStyles.HexNumber)); + } + return ids.Distinct().ToImmutableList(); } #endregion