From 0d9831606c662de5bac5b36723302283564ac433 Mon Sep 17 00:00:00 2001 From: drgere Date: Wed, 19 May 2021 21:47:01 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B0=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BA=D1=83=D0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Numbers.Tests/Numbers.Tests.csproj | 2 +- .../Numbers/FloatNumbers.cs | 25 +++++++++++++++---- .../01-primitive-types/Numbers/Integers.cs | 3 ++- .../01-primitive-types/Numbers/Numbers.csproj | 2 +- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/course-2021-1/exercises/01-primitive-types/Numbers.Tests/Numbers.Tests.csproj b/course-2021-1/exercises/01-primitive-types/Numbers.Tests/Numbers.Tests.csproj index 8a03330f..46553a6a 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers.Tests/Numbers.Tests.csproj +++ b/course-2021-1/exercises/01-primitive-types/Numbers.Tests/Numbers.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + netcoreapp3.1 false diff --git a/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs b/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs index 9cb1d053..a7e86f68 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs +++ b/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs @@ -3,6 +3,7 @@ Здесь все то же самое. */ using System; +using System.Reflection.Metadata.Ecma335; namespace Numbers { @@ -17,7 +18,8 @@ internal static double GetNaN() Необходимо вернуть значение, не используя непосредственно саму константу. Для этого подумай, какой смысл в себе несет эта константа и где бы она могла стать результатом операции или вычисления функции. */ - throw new NotImplementedException(); + //throw new NotImplementedException(); + return 0.0 / 0; } /// @@ -28,20 +30,33 @@ internal static double GetNaN() internal static bool IsNaN(double d) { // Подсказка: по аналогии с константами типа int, у типа double тоже есть свой набор констант. - throw new NotImplementedException(); + //throw new NotImplementedException(); + return !((d <= double.PositiveInfinity) && (d >= double.NegativeInfinity)); } /// /// Возвращает результат сравнения двух вещественнозначных чисел. /// /// -1 - первое меньше второго, 0 - значения равны, 1 - первое больше второго. - internal static int Compare(/* дополни сигнатуру метода как считаешь правильным */) + internal static int Compare(double a, double b, double eps) { /* Подумай, почему это задание дано в части про вещественнозначные числа. И почему не дана полная сигнатура метода. Если сходу идей нет, перестань искать подвох и просто реализуй дословно. Теперь еще раз посмотри на код и подумай в чем может быть проблема, сколько должно быть аргументов. */ - throw new NotImplementedException(); + //throw new NotImplementedException(); + if (b - a < eps) + { + if (a - b < eps) + { + return 0; + } + else + { + return 1; + } + } + return -1; } // и все?!! О_о @@ -49,4 +64,4 @@ internal static int Compare(/* дополни сигнатуру метода к // и все... -_- } -} +} \ No newline at end of file diff --git a/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs b/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs index b1d90398..16409da2 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs +++ b/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs @@ -55,7 +55,8 @@ internal static int HalfIntMaxValue() internal static int Cube(int x) { // не сомневайся, пиши. Тут без подвохов. - throw new NotImplementedException(); + //throw new NotImplementedException(); + return x * x * x; } /// diff --git a/course-2021-1/exercises/01-primitive-types/Numbers/Numbers.csproj b/course-2021-1/exercises/01-primitive-types/Numbers/Numbers.csproj index ce1697ae..c73e0d16 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers/Numbers.csproj +++ b/course-2021-1/exercises/01-primitive-types/Numbers/Numbers.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp2.0 + netcoreapp3.1 From 32b1f5fee877dd43f3a3bb839aeeb6412d9f9c97 Mon Sep 17 00:00:00 2001 From: drgere Date: Thu, 20 May 2021 10:57:52 +0300 Subject: [PATCH 2/4] 2021 --- .../Numbers.Tests/FloatNumbersTests.cs | 2 +- .../Numbers/FloatNumbers.cs | 5 +- .../01-primitive-types/Numbers/Integers.cs | 51 +++---------------- .../01-primitive-types/Numbers/Program.cs | 2 +- 4 files changed, 13 insertions(+), 47 deletions(-) diff --git a/course-2021-1/exercises/01-primitive-types/Numbers.Tests/FloatNumbersTests.cs b/course-2021-1/exercises/01-primitive-types/Numbers.Tests/FloatNumbersTests.cs index b0884a56..ade588ea 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers.Tests/FloatNumbersTests.cs +++ b/course-2021-1/exercises/01-primitive-types/Numbers.Tests/FloatNumbersTests.cs @@ -22,4 +22,4 @@ public void Test_GetNaN_IsNaNOfGetNaNReturnsTrue() Assert.True(FloatNumbers.IsNaN(FloatNumbers.GetNaN())); } } -} +} \ No newline at end of file diff --git a/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs b/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs index a7e86f68..24bfbb28 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs +++ b/course-2021-1/exercises/01-primitive-types/Numbers/FloatNumbers.cs @@ -31,9 +31,9 @@ internal static bool IsNaN(double d) { // Подсказка: по аналогии с константами типа int, у типа double тоже есть свой набор констант. //throw new NotImplementedException(); - return !((d <= double.PositiveInfinity) && (d >= double.NegativeInfinity)); + return double.IsNaN(d); } - + /// /// Возвращает результат сравнения двух вещественнозначных чисел. /// @@ -56,6 +56,7 @@ internal static int Compare(double a, double b, double eps) return 1; } } + return -1; } diff --git a/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs b/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs index 16409da2..7af18ee2 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs +++ b/course-2021-1/exercises/01-primitive-types/Numbers/Integers.cs @@ -41,12 +41,7 @@ public static class Integers /// internal static int HalfIntMaxValue() { - /* - После C++ вы будете приятно удивлены какое умное в .Net автодополнение (IntelliSense). - Особенно это касается связки Visual Studio + Resharper, используя которую, если просто набрать return и нажать пробел, - то в появившемся списке автодополнения одной из первых будет нужная тебе константа :) - */ - throw new NotImplementedException(); + return Int32.MaxValue / 2; } /// @@ -54,8 +49,6 @@ internal static int HalfIntMaxValue() /// internal static int Cube(int x) { - // не сомневайся, пиши. Тут без подвохов. - //throw new NotImplementedException(); return x * x * x; } @@ -64,11 +57,7 @@ internal static int Cube(int x) /// internal static int CubeWithOverflowCheck(int x) { - /* - Если спал на лекции, то тут придется погуглить, сорри. - И заодно подумай какой режим выставлен по умолчанию. Почему. И почему категорически нельзя надеяться на режим по умолчанию. - */ - throw new NotImplementedException(); + return checked(x * x * x); } /// @@ -76,8 +65,7 @@ И заодно подумай какой режим выставлен по у /// internal static int CubeWithoutOverflowCheck(int x) { - // если сделал предыдущие, то с этим уже должно быть понятно. - throw new NotImplementedException(); + return unchecked(x * x * x); } /// @@ -87,14 +75,7 @@ internal static int CubeWithoutOverflowCheck(int x) /// Эквивалентное строковое представление числа. internal static string ToString(int x) { - /* - Возможно ты уже в курсе, что "эквивалентное ему строковое представление" - понятие очень расплывчатое, и существует - огромная куча различных форматов вывода чисел: "123456789", "123 456 789", "0123456789" и т.п. - Сейчас представим, что такой проблемы не существует, и выберем самый простой вариант, который использует какие-то дефолтные настройки. - - Подсказка: нужно воспользоваться методом, который есть у абсолютно всех объектов. - */ - throw new NotImplementedException(); + return x.ToString(); } /// @@ -104,11 +85,7 @@ internal static string ToString(int x) /// 32-битное знаковое целочисленное представление числа. internal static int Parse(string s) { - /* - Продолжай идти простым путем -нужен метод, обратный методу ToString выше, который распарсит дефолтное строковое представление числа. - Подсказка: у каждого примитивного типа есть набор статических методов, среди которых есть нужный. - */ - throw new NotImplementedException(); + return Int32.Parse(s); } /// @@ -116,11 +93,7 @@ internal static int Parse(string s) /// internal static int TenTimes(int x) { - /* - Реализуй умножение числа на 10 без использования арифметических операций над числами. - Воспользуйся реализованными выше методами ToString и Parse. И не думай ни о каких переполнениях - задача не на это :) - */ - throw new NotImplementedException(); + return Int32.Parse(x.ToString() + "0"); } /// @@ -130,15 +103,7 @@ Реализуй умножение числа на 10 без использов /// Эквивалентное строковое представление в шестнадцатиричной системе счисления. internal static string ToHexString(int x) { - /* - У метода ToString числовых типов есть перегрузка, которая принимает строку с одним из заданного набора форматов. - В студии дается хорошая и понятная подсказка с этим набором форматов, в других же IDE скорее всего такого не будет, и придется погуглить форматы. - */ - throw new NotImplementedException(); + return x.ToString("X"); } - - /* - Закончил? Переходи в FloatNumbers.cs - */ } -} +} \ No newline at end of file diff --git a/course-2021-1/exercises/01-primitive-types/Numbers/Program.cs b/course-2021-1/exercises/01-primitive-types/Numbers/Program.cs index 78460c01..6a42c948 100644 --- a/course-2021-1/exercises/01-primitive-types/Numbers/Program.cs +++ b/course-2021-1/exercises/01-primitive-types/Numbers/Program.cs @@ -21,4 +21,4 @@ private static void Main() Console.WriteLine("Hello World!"); } } -} +} \ No newline at end of file From 15d820f1b69783bf33ad95c819a4d1e9a94f286b Mon Sep 17 00:00:00 2001 From: drgere Date: Thu, 20 May 2021 11:51:58 +0300 Subject: [PATCH 3/4] 2021 --- .../AdventureTime/AdventureTime/Time.cs | 116 ++++++------------ 1 file changed, 37 insertions(+), 79 deletions(-) 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..9bbe44ef 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; } /// @@ -33,10 +34,7 @@ public static DateTime WhatTimeIsItInUtc() /// Объект с заданными временем и значением . public static DateTime SpecifyKind(DateTime dt, DateTimeKind kind) { - /* - Подсказка: поищи в статических методах DateTime. - */ - throw new NotImplementedException(); + return DateTime.SpecifyKind(dt, kind); } /// @@ -46,12 +44,7 @@ public static DateTime SpecifyKind(DateTime dt, DateTimeKind kind) /// Строковое представление времени в формате ISO 8601. public static string ToRoundTripFormatString(DateTime dt) { - /* - Обязательно поиграйся и посмотри на изменение результата в зависимости от dt.Kind (для этого тебе поможет метод выше). - Ну и на будущее запомни этот прекрасный строковый формат представления времени - он твой бро! - Название запоминать не нужно, просто помни, что для передачи значения в виде строки, выбирать лучше инвариантные относительно сериализации/десериализации форматы. - */ - throw new NotImplementedException(); + return dt.ToString("O"); } /// @@ -61,11 +54,7 @@ Ну и на будущее запомни этот прекрасный стр /// Объект . public static DateTime ParseFromRoundTripFormat(string dtStr) { - /* - Поиграйся и проверь, что round-trip действительно round-trip, т.е. туда-обратно равно оригиналу (для туда воспользуйся предыдущим методом). - Проверь для всех значений DateTime.Kind. - */ - throw new NotImplementedException(); + return DateTime.Parse(dtStr, null, DateTimeStyles.RoundtripKind); } /// @@ -73,11 +62,7 @@ Проверь для всех значений DateTime.Kind. /// public static DateTime ToUtc(DateTime dt) { - /* - Eсли воспользуешься нужным методом, то напоминаю, что результат его работы зависит от dt.Kind. - В случае dt.Kind == Unspecified предполагается, что время локальное, т.е. результат работы в случае Local и Unspecified совпадают. Такие дела - */ - throw new NotImplementedException(); + return dt.ToUniversalTime(); } /// @@ -87,8 +72,7 @@ public static DateTime ToUtc(DateTime dt) /// Время, передвинутое вперед на 10 секунд от заданного public static DateTime AddTenSeconds(DateTime dt) { - // здесь воспользуйся методами самого объекта и заодно посмотри какие еще похожие есть - throw new NotImplementedException(); + return dt.AddSeconds(10); } /// @@ -98,11 +82,7 @@ public static DateTime AddTenSeconds(DateTime dt) /// Время, передвинутое вперед на 10 секунд от заданного public static DateTime AddTenSecondsV2(DateTime dt) { - /* - Ну а здесь воспользуйся сложением с TimeSpan. Обрати внимание, что помимо конструктора, у класса есть набор полезных статических методов-фабрик. - Обрати внимание, что у TimeSpan нет статических методов FromMonth, FromYear. Как думаешь, почему? - */ - throw new NotImplementedException(); + return dt + TimeSpan.FromSeconds(10); } /// @@ -113,12 +93,7 @@ public static DateTime AddTenSecondsV2(DateTime dt) /// Полное количество часов заданного временного отрезка. public static int GetHoursBetween(DateTime dt1, DateTime dt2) { - /* - 1) Подумай, в чем разница между Hours и TotalHours - 2) Проверь, учитывается ли Kind объектов при арифметических операциях. - 3) Подумай, почему возвращаемое значение может отличаться от действительности. - */ - throw new NotImplementedException(); + return (int) (dt2 - dt1).TotalHours; } /// @@ -126,8 +101,7 @@ public static int GetHoursBetween(DateTime dt1, DateTime dt2) /// public static int GetTotalMinutesInThreeMonths() { - // ну тут все просто и очевидно, если сделал остальные и подумал над вопросами в комментах. - throw new NotImplementedException(); + return (int) TimeSpan.FromDays(91).TotalMinutes; } #region Adventure time saga @@ -141,13 +115,9 @@ public static int GetTotalMinutesInThreeMonths() /// public static int GetAdventureTimeDurationInMinutes_ver0_Dumb() { - /* - Как ты понимаешь, время выбрано не просто так, но для начала давай прикинемся совсем наивными. - Лондон находится в часовом поясе +0 (GMT), а Москва в +3 (MSK). Воспользуйся DateTimeOffset, чтобы задать правильное время, и посчитай разницу в минутах. Посмотри на результат. - Держи, заготовочку для копипасты: - - 2010, 3, 28, 2, 15, 0 - */ - throw new NotImplementedException(); + var mskDate = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(3)); + var gmtDate = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.Zero); + return (int) (gmtDate - mskDate).TotalMinutes; } /// @@ -160,12 +130,9 @@ public static int GetAdventureTimeDurationInMinutes_ver0_Dumb() /// public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb() { - /* - Здесь то же самое. Сорри, немного бездумного кодинга. Вот заготовочка для копипасты времени: - - 2010, 3, 28, 3, 15, 0 - - 2010, 3, 28, 1, 15, 0 - */ - throw new NotImplementedException(); + var mskDate = new DateTimeOffset(2010, 3, 28, 3, 15, 0, TimeSpan.FromHours(3)); + var gmtDate = new DateTimeOffset(2010, 3, 28, 1, 15, 0, TimeSpan.Zero); + return (int) (gmtDate - mskDate).TotalMinutes; } /// @@ -173,39 +140,26 @@ public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver0_Dumb() /// public static int GetAdventureTimeDurationInMinutes_ver1_FeelsSmarter() { - /* - Глава вторая, в которой оказывается, что в некоторых странах принята такая штука как летнее время (не совсем то, про которое поет Лана Дель Рей). - - Внимательный читатель мог усомниться в данных мной часовых поясах и их смещении относительно UTC и был бы прав. - На самом деле смещения таковы: Лондон +1 (BST - British Summer Time), Москва +4 (MSD - Moscow Daylight Time). - Давай теперь учтем правильное смещение. Я понимаю, что это очевидно, что результат не изменится, но тебе же не сложно скопипастить и просто поменять смещения? - */ - throw new NotImplementedException(); + var msdDate = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(4)); + var bstDate = new DateTimeOffset(2010, 3, 28, 2, 15, 0, TimeSpan.FromHours(1)); + return (int) (bstDate - msdDate).TotalMinutes; } - // GetGenderSwappedAdventureTimeDurationInMinutes_ver1_FeelsSmarter опустим, там то же самое - /// /// Возвращает количество минут, проведенных в пути из Москвы в Лондон. /// public static int GetAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience() { - /* - Глава третья и последняя, в которой внезапно оказывается, что Финн и Фионна находятся в суперпозиции и существуют в виде гендерно нейтрального сверхчеловека, который и путешествовал из Москвы в Лондон. - - Дело в том, что перевод на летнее время в 2010м году в Москве произошел в 02:00 (стрелки часов перевели на час вперед), а в Лондоне - в 01:00. - Таким образом в Москве не было 02:15 - однако можно, например, считать, что этому времени соответствует 03:15. Ну а в Лондоне 01:15 это на самом деле 02:15. - Только как это обработать в рамках класса DateTimeOffset? Да, для конкретного примера мы могли бы сами ручками "перевести стрелки" и поставить правильное время, но что делать в общем случае? - Тут придется воспользоваться знанием о часовых поясах. Их есть у .Net. - - Дабы ты не мучился[-ась], роя в недрах msdn и stackoverflow в поисках ответа (в конце концов, когда тебе это в жизни действительно понадобится), - ниже ты найдешь готовый метод GetZonedTime. Просто посмотри на него (можешь даже посмотреть методы и свойства типа TimeZoneInfo, если интересно) и воспользуйся им для вычисления правильного времени - "отбытия" и "прибытия" наших героев. Затем посчитай длительность путешествия. Также даны правильные идентификаторы зон. - */ const string moscowZoneId = "Russian Standard Time"; const string londonZoneId = "GMT Standard Time"; - throw new NotImplementedException(); + // на Mac OS зоны обозначаются по-другому + const string moscowZoneIdLinux = "Europe/Moscow"; + const string londonZoneIdLinux = "Europe/London"; + + var mskDate = GetZonedTime(new DateTime(2010, 3, 28, 2, 15, 0), moscowZoneIdLinux); + var gmtDate = GetZonedTime(new DateTime(2010, 3, 28, 2, 15, 0), londonZoneIdLinux); + return (int) (gmtDate - mskDate).TotalMinutes; } /// @@ -213,12 +167,16 @@ ниже ты найдешь готовый метод GetZonedTime. Прост /// public static int GetGenderSwappedAdventureTimeDurationInMinutes_ver2_FeelsLikeRocketScience() { - /* - Реши по аналогии с предыдущим методом и проверь, что оба метода действительно возвращают одно и то же время (и что оно правильное). - */ const string moscowZoneId = "Russian Standard Time"; const string londonZoneId = "GMT Standard Time"; - throw new NotImplementedException(); + + // на Mac OS зоны обозначаются по-другому + const string moscowZoneIdLinux = "Europe/Moscow"; + const string londonZoneIdLinux = "Europe/London"; + + var msdDate = GetZonedTime(new DateTime(2010, 3, 28, 3, 15, 0), moscowZoneIdLinux); + var bstDate = GetZonedTime(new DateTime(2010, 3, 28, 1, 15, 0), londonZoneIdLinux); + return (int) (bstDate - msdDate).TotalMinutes; } private static DateTimeOffset GetZonedTime(DateTime localTime, string timeZoneId) @@ -277,7 +235,7 @@ private static ZonedDateTime GetZonedTime(LocalDateTime localTime, string timeZo /// True - если родились в один день, иначе - false. internal static bool AreEqualBirthdays(DateTime person1Birthday, DateTime person2Birthday) { - throw new NotImplementedException(); + return person1Birthday.Month == person2Birthday.Month && person1Birthday.Day == person2Birthday.Day; } } -} +} \ No newline at end of file From 1e495d9738b8d264d084ceec79c2752d95cc4f41 Mon Sep 17 00:00:00 2001 From: drgere Date: Thu, 27 May 2021 09:27:29 +0300 Subject: [PATCH 4/4] add 4-ex --- .../BoringVector/BoringVector/Vector.cs | 297 ++++++++---------- .../BoringVector/VectorExtensions.cs | 99 +++++- .../RicksMercilessEncryptorTests.cs | 86 ++++- .../RicksMercilessEncryptor.cs | 76 +++-- .../DrunkFibonacci/DrunkFibonacci.cs | 141 +++++---- 5 files changed, 419 insertions(+), 280 deletions(-) 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..32e62a1b 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 @@ -1,193 +1,160 @@ using System; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("BoringVector.Tests")] namespace BoringVector { - #region 1. Структура Vector - - /* - Реализуй структуру Vector - см. комментарии внутри нее. - */ - - internal struct Vector + /// + /// Класс для работы с векторами на плоскости + /// + internal readonly struct Vector { - /* - Vector задается парой вещественных координат X и Y. - */ - - - /* - На месте заглушек добавь реализацию базовых методов вектора: - - квадрат длины - - сумма векторов - - умножение на коэффициент - - скалярное произведение - - векторное произведение (= площадь параллелограмма) - */ + public readonly double X; + public readonly double Y; + /// + /// Конструирует вектор из двух координат + /// + /// Координата по оси x + /// Координата по оси y + 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); } + + /// + /// Возвращает , умноженный на число + /// + /// , коэффициент умножения + /// , умноженный на число 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 Math.Abs(X * v.Y - Y * v.X); } - - /* - Переопредели ниже метод ToString - пусть выводит (X; Y) - */ - - #region operators - - /* - Реализуй также следущие операторы (Vector v, u и double k): - - v + u, v - u - - k * v, v * k, v / k - - +v, -v - */ - - #endregion - } - - #endregion - - /* - Время отправиться в VectorExtensions.cs за новой порцией квестов, герой! - Как закончишь, возвращайся за щедрым вознаграждением! - */ - - - #region 3. Комментарии - - /* - Прости, я соврал. К сожалению, пока ты делал(-а) вторую часть, человек, который понимал, о чем идет речь в первой части, - успел съездить в путешествие под названием "во все тяжкие" и теперь проходит курс реабилитации. А те, кто был хотя бы примерно в теме, - внезапно лишились рассудка. - Тут еще из будущего сообщили, что тебе дали задачу поинтереснее, и ты наотрез отказался(-ась) сотрудничать в передаче знаний. - Ну а вместо тебя на эту задачу взяли пушистого котика, который отказывается разбираться в коде и уж тем более его писать - говорит у него лапки. - - В такой ситуации единственно возможное решение задачи - оставить после себя комментарии. Такие, чтобы даже котику было понятно! - В общем, впереди неприятная для многих часть - необходимо добавить комментарии ко всем введенным типам, методам и свойствам :) - - - _Хозяйке на заметку_ - - Для многих это действительно довольно неприятная и скучнейшая часть - писать комментарии к коду. Проблема в том, - что это еще и не так просто как кажется на первый взгляд. Очень желательно выдерживать единый стиль, писать по существу, - писать не "для текущего разобравшегося в проблеме и предметной области себя", а для "того парня", "себя через год". Ну или пушистого котика. - - Есть и хорошее в этом деле. Комментирование кода очень похоже на написание автотестов - оно позволяет взглянуть - на задачу и ее решение немного с другой стороны. Например, если слова не вяжутся, и не получается написать простое и короткое - описание к методу или типу - это хороший сигнал, что он "с душком", и его стоит переделать/отрефакторить. - Я лично чаще пишу комментарии ближе к концу работы над задачей. Это позволяет мне еще раз просмотреть весь написанный код под - слегка иным углом обзора и самому сделать первичный code review. - - - Ты мог(-ла) заметить, что в предыдущих заданиях для комментариев я использовал немного необычный синтаксис: - - /// - /// Возвращает объект с заданными временем и значением . - /// - /// Объект , задающий время. - /// Значение , задающий соответствующее свойство возвращаемого объекта. - /// Объект с заданными временем и значением . - - Такой блок является комментарием, т.к. каждая строка начинается с //, но имеет свою внутреннюю структуру и синтаксис. - Это так называемые Xml documentation comments. Их поддерживает сам компилятор. Они позволяют писать чуть более умные и продвинутые комментарии к сущностям, - а потом, например, автоматически генерировать по ним красивую документацию. - Правилом хорошего тона считается писать комментарии к методам, классам и другим сущностям, используя данный синтаксис - так ты и комментируешь их, и документируешь. - Внутри методов он не поддерживается, поэтому там только обычные (// или /*). - - Ниже приведены примеры простейших комментариев. Если наведете мышкой на название метода DoNothing, увидишь, - что студия отображает комментарий в подписи (в других IDE из коробки без плагинов это вряд ли будет работать). - Если навести на аргумент метода DoNothing - something, увидишь комментарий к нему. - Наведи теперь на NotImplementedException() - комментарий во всплывашке сделан с помощью такого же синтаксиса. - Код .Net Framework задокументирован именно таким синтаксисом. - - Чтобы создать такой комментарий, не нужно писать разметку целиком самому. Если ввести ///, студия сама создаст нужные блоки. - - Плюсы Xml documentation comments: - - блок комментариев имеет четкую предзаданную структуру, что дает возможность воспользоваться различными инструментариями - автогенерации документации (и создавать, например, документацию вроде MSDN). - В последней лабе мы, надеюсь, научимся генерировать для web api страничку с документацией к нашему апи и увидим, что генератор в том числе - может для каждого метода апи создавать формочку для его проверки и ручного тестирования. - - IDE может показывать ее в чуть более удобном виде, нежели если бы ты писал(-а) их обычным способом. - Например, показывать во всплывающей подсказке только самое необходимое короткое описание, а длинное с пояснениями и примерами кода не показывать. - - все названия типов, методов и свойств можно задавать в виде ссылки, например, , и это - будет строгая, проверяемая компилятором, ссылка. Ты, думаю, помнишь, что компилятор как сервис в частности предоставляет разные возможности рефакторинга, - например, переименование. Так вот, если воспользоваться им и переименовать метод DotProduct у структуры Vector, то - переименуется и текст в ссылке. Если же ссылка указывает на невалидную сущность, то студия явно даст понять: "Cannot resolve symbol 'blah-blah-blah'". - Я лично не проверял, но по идее можно даже сделать так, чтобы в таком случае была ошибка компиляции. В генерируемой же документации эти ссылки будут - заменены на реальные ссылки на страницы описания соответствующей сущности, что довольно удобно для навигации по ней. - - */ - - /// - /// Класс, не делающий ничего. - /// - internal class Foo - { + /// - /// Не делает ничего, как и подобает методам данного класса. + /// Возвращает , строковое представление /// - /// Экземпляр чего бы то ни было. - public static void DoNothing(object something) + /// Строковое представление + public override string ToString() { - // nothing to do here + return string.Concat("(", X.ToString(), "; )", Y.ToString(), ")"); } - - public static void ThrowNotImplementedException() + + /// + /// Складывает два объекта и возвращает новый + /// + /// , левое слагаемое + /// , правое слагаемое + /// , сумма векторов + public static Vector operator +(Vector v, Vector u) + { + return v.Add(u); + } + + /// + /// Вычитает один из другого и возвращает новый + /// + /// , левое слагаемое + /// , правое слагаемое + /// , результат вычитания + public static Vector operator -(Vector v, Vector u) { - throw new NotImplementedException(); + return new Vector(v.X - u.X, v.Y - u.Y); + } + + /// + /// Возвращает , умноженный на число + /// + /// , коэффициент умножения + /// Исходный + /// , умноженный на число + public static Vector operator *(double k, Vector v) + { + return v.Scale(k); + } + + /// + /// Возвращает , умноженный на число + /// + /// Исходный + /// , коэффициент умножения + /// , умноженный на число + public static Vector operator *(Vector v, double k) + { + return v.Scale(k); + } + + /// + /// Возвращает , нормированный на число + /// + /// Исходный + /// , коэффициент нормировки + /// , нормированный на число + public static Vector operator /(Vector v, double k) + { + return v.Scale(1 / k); + } + + /// + /// Возвращает неизмененный + /// + /// Исходный + /// Неизмененный + public static Vector operator +(Vector v) + { + return v; + } + + /// + /// Возвращает , направленный противоположно данному + /// + /// Исходный + /// , направленный противоположно данному + public static Vector operator -(Vector v) + { + return new Vector(-v.X, -v.Y); } } - - #endregion - - - #region 4. Тесты - - /* - Прости еще раз, но на этом твои мучения еще не кончаются. Проблема в том, что у котика все еще лапки, поэтому очень важно - покрыть тестами хотя бы базовые методы структуры Vector: - SquareLength - Add - Scale - DotProduct - CrossProduct - - Для этого создай в этом же солюшене (если ты не в студии, то можешь и не в солюшене) проект BoringVector.Tests, - который будет содержать класс с набором тестов. Используй Xunit (в принципе можешь воспользоваться и другим фреймворком для тестирования). - - Особо не заморачивайся с тем, чтобы оттестировать все возможные специальные случаи - в данном задании важно, чтобы - ты просто разобрался(-ась), как писать автотесты и как их запускать. Это задание НЕ на то, как писать хорошие тесты. - - Примечание: структура Vector описана как internal структура, поэтому по умолчанию сборке BoringVector.Tests она не видна. - Чтобы она была видна, существует специальная директива компилятору: - [assembly: InternalsVisibleTo("XXX")] - , где XXX - название проекта, которому ты хочешь сделать видимыми свои internal'ы. - - Можешь посмотреть, в задании [01-primitive-types] эта директива есть в файле Program.cs проекта Numbers. - - Итак, создай проект с тестами и добейся того, чтобы базовые методы структуры Vector их проходили. - */ - - #endregion - - - /* - На этом все. Время делать пулл реквест и наслаждаться заслуженным отдыхом :) - */ -} +} \ No newline at end of file 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..f5b11f3d 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,10 +1,91 @@ -namespace BoringVector +using System; + +namespace BoringVector { - /* - Здесь тебе нужно написать класс с методами-расширениями структуры Vector: - - IsZero: проверяет, является ли вектор нулевым, т.е. его координаты близки к нулю (в эпсилон окрестности). За эпсилон здесь и далее берем 1e-6. - - Normalize: нормализует вектор - - GetAngleBetween: возвращает угол между двумя векторами в радианах. Примечание: нулевой вектор сонаправлен любому другому. - - GetRelation: возвращает значение перечесления VectorRelation(General, Parallel, Orthogonal) - отношение между двумя векторами("общий случай", параллельны, перпендикулярны). Перечисление задавать тоже тебе) - */ -} + /// + /// Отношение между двумя векторами (общий случай, параллельны, перпендикулярны) + /// + enum VectorRelation { General, Parallel, Orthogonal }; + + /// + /// Методы-расширения структуры Vector + /// + static class VectorExtensions + { + /// + /// Проверяет, является ли вектор нулевым c погрешностью по длине в 1e-6. + /// + /// Объект + /// , является ли вектор нулевым + public static bool IsZero(this Vector v) + { + const double eps = 1e-6; + return Math.Sqrt(v.SquareLength()) < eps; + } + + /// + /// Возвращает , отнормированный на его длину + /// + /// + /// , отнормированный на его длину + public static Vector Normalize(this Vector v) + { + if (v.IsZero()) + { + return v; + } + + return v / Math.Sqrt(v.SquareLength()); + } + + /// + /// Возвращает , угол между двумя векторами в радианах + /// + /// Первый + /// Второй + /// , угол между двумя векторами в радианах + public static double GetAngleBetween(this Vector v, Vector u) + { + if (v.IsZero() || u.IsZero()) + { + return 0; + } + + var cos = v.DotProduct(u) / Math.Sqrt(v.SquareLength() * u.SquareLength()); + if (cos < -1) + { + return Math.PI; + } + + if (cos > 1) + { + return 0; + } + + return Math.Acos(cos); + } + + /// + /// Возвращает отношение (VectorRelation) между двумя векторами + /// + /// Первый + /// Второй + /// Отношение (VectorRelation) между двумя векторами + public static VectorRelation GetRelation(this Vector v, Vector u) + { + const double eps = 1e-6; + var angle = v.GetAngleBetween(u); + if (angle < eps || Math.PI - angle < eps) + { + return VectorRelation.Parallel; + } + + if (Math.Abs(angle - Math.PI / 2) < eps) + { + return VectorRelation.Orthogonal; + } + + return VectorRelation.General; + } + } +} \ No newline at end of file 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..b6083b34 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,94 @@ using System; +using System.Collections.Immutable; using Xunit; namespace WubbaLubbaDubDub.Tests { public class RicksMercilessEncryptorTests { + [Theory] + [InlineData("Простой текст", new []{"Простой текст"})] + [InlineData("Текст, разделенный\nпереводами\nстроки.", new[]{"Текст, разделенный", "переводами", "строки."})] + public void Test_SplitToLines_ReturnsCorrectValue(string text, string[] expectedLines) + { + Assert.Equal(expectedLines, text.SplitToLines()); + } + [Theory] + [InlineData("Простой текст", new []{"Простой", "текст"})] + [InlineData(" , .\r\nТекст,\t с 15: ..разными\n\n\t\t:;' символами!?\t\t \r\n", new[]{"Текст", "с", "15", "разными", "символами"})] + public void Test_SplitToWords_ReturnsCorrectValue(string line, string[] expectedWords) + { + Assert.Equal(expectedWords, line.SplitToWords()); + } + + [Theory] + [InlineData("", "")] + [InlineData("а", "")] + [InlineData("аб", "а")] + [InlineData("строка", "стр")] + [InlineData("строчка", "стр")] + public void Test_GetLeftHalf_ReturnsCorrectValue(string s, string expectedLeftHalf) + { + Assert.Equal(expectedLeftHalf, s.GetLeftHalf()); + } + + [Theory] + [InlineData("", "")] + [InlineData("строка", "ока")] + [InlineData("строчка", "очка")] + public void Test_GetRightHalf_ReturnsCorrectValue(string s, string expectedRightHalf) + { + Assert.Equal(expectedRightHalf, s.GetRightHalf()); + } + + [Theory] + [InlineData("один одиннадцать", "один", "три", "три тринадцать")] + [InlineData("строка как строка", "строка", "текст", "текст как текст")] + public void Test_Replace_ReturnsCorrectValue(string s, string old, string @new, string expected) + { + Assert.Equal(expected, RicksMercilessEncryptor.Replace(s, old, @new)); + } + + [Theory] + [InlineData("Слово", @"\u0421\u043B\u043E\u0432\u043E")] + [InlineData("français", @"\u0066\u0072\u0061\u006E\u00E7\u0061\u0069\u0073")] + public void Test_CharsToCodes_ReturnsCorrectValue(string chars, string expectedCodes) + { + Assert.Equal(expectedCodes, chars.CharsToCodes()); + } + + [Theory] + [InlineData("Слово", "оволС")] + [InlineData("français", "siaçnarf")] + public void Test_GetReversed_ReturnsCorrectValue(string value, string expectedReversed) + { + Assert.Equal(expectedReversed, value.GetReversed()); + } + + [Theory] + [InlineData("СлОвЕчКо", "сЛоВеЧкО")] + [InlineData("français", "FRANÇAIS")] + [InlineData("2021 год", "2021 ГОД")] + public void Test_InverseCase_ReturnsCorrectValue(string value, string expectedInversed) + { + Assert.Equal(expectedInversed, value.InverseCase()); + } + + [Theory] + [InlineData("абвгддд", "бвгдеее")] + [InlineData("français", "gsboèbjt")] + public void Test_ShiftInc_ReturnsCorrectValue(string value, string expectedShifted) + { + Assert.Equal(expectedShifted, value.ShiftInc()); + } + + [Theory] + [InlineData("траляля 0001:0000 /*12 1234:56AF*/", new []{65536L})] + [InlineData("//1234:56AF\n 0000:0012 //AAAA:AAAA\n /* 2314:ABCD*/", new []{18L})] + public void Test_GetUsedObjects_ReturnsCorrectValue(string value, long[] expectedObjects) + { + Assert.Equal(ImmutableArray.Create(expectedObjects), value.GetUsedObjects()); + } } -} +} \ No newline at end of file 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..b742e22c 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,7 @@ using System; -using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; +using System.Text.RegularExpressions; namespace WubbaLubbaDubDub { @@ -11,8 +12,7 @@ public static class RicksMercilessEncryptor /// public static string[] SplitToLines(this string text) { - // У строки есть специальный метод. Давай здесь без регулярок - throw new NotImplementedException(); + return text.Split('\n'); } /// @@ -20,8 +20,8 @@ public static string[] SplitToLines(this string text) /// public static string[] SplitToWords(this string line) { - // А вот здесь поиграйся с регулярками. - throw new NotImplementedException(); + var words = Regex.Split(line, "\\W+"); + return Array.FindAll(words, word => word.Length > 0); } /// @@ -30,8 +30,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 +39,7 @@ public static string GetLeftHalf(this string s) /// public static string GetRightHalf(this string s) { - throw new NotImplementedException(); + return s.Substring(s.Length / 2); } /// @@ -48,8 +47,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); } /// @@ -58,14 +56,12 @@ public static string Replace(this string s, string old, string @new) /// public static string CharsToCodes(this string s) { - /* - Может быть удобным здесь же сначала написать локальную функцию - которая содержит логику для преобразования одного символа, - а затем использовать её для посимвольного преобразования всей строки. - FYI: локальную функцию можно объявлять даже после строки с return. - То же самое можно сделать и для всех оставшихся методов. - */ - throw new NotImplementedException(); + return string.Concat(s.Select(CharToCode)); + + string CharToCode(char c) + { + return string.Concat("\\u", Convert.ToInt32(c).ToString("X4")); + } } /// @@ -73,11 +69,7 @@ То же самое можно сделать и для всех оставши /// public static string GetReversed(this string s) { - /* - Собрать строку из последовательности строк можно несколькими способами. - Один из низ - статический метод Concat. Но ты можешь выбрать любой. - */ - throw new NotImplementedException(); + return string.Concat(s.ToCharArray().Reverse()); } /// @@ -85,12 +77,12 @@ Один из низ - статический метод Concat. Но ты мо /// public static string InverseCase(this string s) { - /* - Здесь тебе помогут статические методы типа char. - На минуту задержись здесь и посмотри, какие еще есть статические методы у char. - Например, он содержит методы-предикаты для определения категории Юникода символа, что очень удобно. - */ - throw new NotImplementedException(); + return string.Concat(s.Select(InverseCase)); + + char InverseCase(char c) + { + return char.IsLower(c) ? char.ToUpper(c) : char.ToLower(c); + } } /// @@ -99,12 +91,13 @@ Здесь тебе помогут статические методы типа /// public static string ShiftInc(this string s) { - throw new NotImplementedException(); + return string.Concat(s.Select(ShiftInc)); + char ShiftInc(char c) + { + return Convert.ToChar(Convert.ToInt32(c) + 1); + } } - - #region Чуть посложнее - /// /// Возвращает список уникальных идентификаторов объектов, используемых в тексте . /// Идентификаторы объектов имеют длину 8байт и представлены в тексте в виде ¶X:Y¶, где X - старшие 4 байта, а Y - младшие 4 байта. @@ -113,13 +106,14 @@ public static string ShiftInc(this string s) /// public static IImmutableList GetUsedObjects(this string text) { - /* - Задача на поиграться с регулярками - вся сложность в том, чтобы аккуратно игнорировать комментарии. - Экспериментировать онлайн можно, например, здесь: http://regexstorm.net/tester и https://regexr.com/ - */ - throw new NotImplementedException(); - } + var commentRegex = new Regex(@"((\/\*)((?!\*\/)(.|\n))*(\*\/))|(\/\/.*\n)", RegexOptions.Multiline); + var cleanText = commentRegex.Replace(text, ""); + var idRegex = new Regex(@"[0-9A-F]{4}:[0-9A-F]{4}", RegexOptions.Multiline); - #endregion + return idRegex + .Matches(cleanText) + .Select(id => Convert.ToInt64(id.Value.Substring(5), 16) + (Convert.ToInt64(id.Value.Substring(0, 4), 16) << 16)) + .ToImmutableList(); + } } -} +} \ No newline at end of file diff --git a/course-2021-1/exercises/05-drunk-fibonacci/DrunkFibonacci/DrunkFibonacci/DrunkFibonacci.cs b/course-2021-1/exercises/05-drunk-fibonacci/DrunkFibonacci/DrunkFibonacci/DrunkFibonacci.cs index ac217f0d..405104e4 100644 --- a/course-2021-1/exercises/05-drunk-fibonacci/DrunkFibonacci/DrunkFibonacci/DrunkFibonacci.cs +++ b/course-2021-1/exercises/05-drunk-fibonacci/DrunkFibonacci/DrunkFibonacci/DrunkFibonacci.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; namespace DrunkFibonacci { @@ -11,8 +12,7 @@ internal static class DrunkFibonacci /// Длина массива public static int[] CreateIntArray(int len) { - // на создание массивов заданной длины - throw new NotImplementedException(); + return new int[len]; } /// @@ -23,8 +23,10 @@ public static int[] CreateIntArray(int len) /// Шаг прогрессии. public static void FillIntArray(int[] arr, int seed, int step) { - // на задание значений массива - throw new NotImplementedException(); + for (var i = 0; i < arr.Length; ++i, seed += step) + { + arr[i] = seed; + } } /// @@ -33,8 +35,7 @@ public static void FillIntArray(int[] arr, int seed, int step) /// public static int[] GetFirstFiveFibonacci() { - // на создание массива с инициализацией - throw new NotImplementedException(); + return new[] {0, 1, 1, 2, 3}; } /// @@ -42,14 +43,12 @@ public static int[] GetFirstFiveFibonacci() /// public static IEnumerable GetDeterministicRandomSequence() { - /* - Воспользуйся классом Random. - Для того, чтобы данный объект генерировал одну и ту же последовательность, - его следует инициализировать одной и той же константой (параметр конструктора seed). - - Задача на ленивую генерацию последовательностей. - */ - throw new NotImplementedException(); + const int seed = 42; + var rnd = new Random(seed); + while (true) + { + yield return rnd.Next(); + } } /// @@ -57,17 +56,42 @@ Задача на ленивую генерацию последовательн /// public static IEnumerable GetDrunkFibonacci() { - /* - Первые два значения: 1 и 1. - Каждое 6е число забывает озвучить (но учитывает при подсчете следующего). - Каждое 6е, начиная с 4го, вставляет очередную "шутку за 300": число 300. - У получившегося числа с некоторой вероятностью зануляет биты, - соответствующие числу 42 (т.е. те биты, которые в бинарном представлении числа 42 равны единице). - Вероятность считается так. На каждом i-ом этапе вычисления нового значения X последовательности берешь так же число Y - из последовательности GetDeterministicRandomSequence и проверяешь, есть ли у числа Y единичные биты числа 42. - При вычислении сложения переполнение типа разрешено и всячески поощряется. - */ - throw new NotImplementedException(); + bool IsSilent(int position) => position % 6 == 0; + bool AddThreeHundred(int position) => IsSilent(position) && position > 6 * 4; + + var prevValue = 1; + var currValue = 1; + var currPos = 2; + + var randomEnumerator = GetDeterministicRandomSequence().GetEnumerator(); + randomEnumerator.MoveNext(); + randomEnumerator.MoveNext(); + + while (true) + { + ++currPos; + randomEnumerator.MoveNext(); + prevValue += currValue; + (prevValue, currValue) = (currValue, prevValue); + + if (AddThreeHundred(currPos)) + { + ++currPos; + randomEnumerator.MoveNext(); + prevValue = currValue; + currValue = 300; + } + + if ((randomEnumerator.Current & 42) != 0) + { + currValue &= ~42; + } + + if (!IsSilent(currPos)) + { + yield return currValue; + } + } } /// @@ -77,8 +101,7 @@ При вычислении сложения переполнение типа /// Длина отрезка. public static int GetMaxOnRange(int from, int cnt) { - // научишься пропускать и брать фиксированную часть последовательности, агрегировать. Максимум есть среди готовых функций агрегации. - throw new NotImplementedException(); + return GetDrunkFibonacci().Skip(from - 1).Take(cnt).Max(); } /// @@ -87,8 +110,7 @@ public static int GetMaxOnRange(int from, int cnt) /// Индекс начала поиска отрезка. Нумерация с единицы. public static List GetNextNegativeRange(int from = 1) { - // научишься пропускать и брать по условию, превращать в список (см. ToList). - throw new NotImplementedException(); + return GetDrunkFibonacci().Skip(from - 1).SkipWhile(val => val >= 0).TakeWhile(val => val < 0).ToList(); } /// @@ -96,8 +118,7 @@ public static List GetNextNegativeRange(int from = 1) /// public static IEnumerable GetXoredWithLaggedItself() { - // узнаешь о существовании функции Zip. - throw new NotImplementedException(); + return GetDrunkFibonacci().Zip(GetDrunkFibonacci().Skip(42), (left, right) => left ^ right); } /// @@ -105,8 +126,19 @@ public static IEnumerable GetXoredWithLaggedItself() /// public static IEnumerable GetInChunks() { - // ни чему особо не научишься, просто интересная задачка :) - throw new NotImplementedException(); + var fibEnumerator = GetDeterministicRandomSequence().GetEnumerator(); + while (true) + { + const int len = 16; + var chunk = new int[len]; + for (var i = 0; i < len; ++i) + { + chunk[i] = fibEnumerator.Current; + fibEnumerator.MoveNext(); + } + + yield return chunk; + } } /// @@ -115,14 +147,7 @@ public static IEnumerable GetInChunks() /// public static IEnumerable FlattenChunkedSequence() { - /* - Узнаешь о встроенных функциях сортировки и функции SelectMany, - которая сглаживает (flatten) последовательность последовательностей в просто последовательность. - - Вообще говоря, SelectMany умеет много чего и мегаполезна. - Она в какой-то степени эквивалентна оператору `bind` над монадами (в данном случае над монадами последовательностей). - */ - throw new NotImplementedException(); + return GetInChunks().SelectMany(chunk => chunk.OrderBy(Math.Abs).Take(3)); } /// @@ -135,28 +160,16 @@ которая сглаживает (flatten) последовательност /// public static Dictionary GetGroupSizes() { - /* - Хочется увидеть решение через группировку и агрегацию. Для группировки существуют два метода-расширения GroupBy и ToLookup. - Они внешне немного похожи, но на самом деле очень сильно различаются семантически. - - Первый - ленивый (как Take, Where, Select и куча других) и лишь декларирует группировку, т.е. конструирует - новый объект с информацией о том, как производить группировку (сама итерация по исходной последовательности - при вызове метода GroupBy не производится). Это бывает удобно, например, при описании запросов к БД, используя ORM'ки - - GroupBy будет правильно истолковано конструктором запросов и группировка будет произведена на стороне БД, а не на стороне кода, - что и быстрее, и требует передачи меньшего кол-ва данных. - Если у объекта, полученного вызовом .GroupBy дважды вызвать методы, инициирующие итерацию, то она будет произведена дважды. - - Второй - не ленивый и производит непосредственно саму группировку. Можно трактовать это как "промежуточное кэширование" группировки для быстрого - [и возможно повторного] доступа к группам. Т.е. ты один раз произвел группировку, дальше пользуешься уже ей отдельно от оригинальной последовательности - - это не потребует повторных итераций по ней. - По сути ILookup аналогичен IDictionary> - разница лишь в том, что - обращение к несуществующему ключу лукапа будет выдавать пустую последовательность, в то время как словарь сгенерирует исключение. - - Конкретно в этом задании более к месту будет выглядеть использование GroupBy. Но можешь ради интереса воспользоваться и ToLookup. - - Итого научишься группировать и создавать на их основе словарь (см. ToDictionary). - */ - throw new NotImplementedException(); + return GetDrunkFibonacci() + .Take(10000) + .GroupBy( + val => val % 8, + (mod, vals) => new + { + mod, + count = vals.Count() + }) + .ToDictionary(item => item.mod, item => item.count); } } -} +} \ No newline at end of file