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