From 507ca674cdd4db00cdd4d54df76d0a2874146bcc Mon Sep 17 00:00:00 2001 From: ilya-krivtsov <180809461+ilya-krivtsov@users.noreply.github.com> Date: Sun, 4 May 2025 23:26:56 +0300 Subject: [PATCH] MyLinq (hw10 - mylinq) --- MyLinq/MyLinq.Tests/GlobalSuppressions.cs | 11 +++ MyLinq/MyLinq.Tests/MyLinq.Tests.csproj | 28 +++++++ MyLinq/MyLinq.Tests/MyLinqTests.cs | 94 +++++++++++++++++++++++ MyLinq/MyLinq.sln | 53 +++++++++++++ MyLinq/MyLinq/MyLinq.cs | 83 ++++++++++++++++++++ MyLinq/MyLinq/MyLinq.csproj | 10 +++ 6 files changed, 279 insertions(+) create mode 100644 MyLinq/MyLinq.Tests/GlobalSuppressions.cs create mode 100644 MyLinq/MyLinq.Tests/MyLinq.Tests.csproj create mode 100644 MyLinq/MyLinq.Tests/MyLinqTests.cs create mode 100644 MyLinq/MyLinq.sln create mode 100644 MyLinq/MyLinq/MyLinq.cs create mode 100644 MyLinq/MyLinq/MyLinq.csproj diff --git a/MyLinq/MyLinq.Tests/GlobalSuppressions.cs b/MyLinq/MyLinq.Tests/GlobalSuppressions.cs new file mode 100644 index 0000000..909e036 --- /dev/null +++ b/MyLinq/MyLinq.Tests/GlobalSuppressions.cs @@ -0,0 +1,11 @@ +// +// Copyright (c) Ilya Krivtsov. All rights reserved. +// + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "This is tests project")] diff --git a/MyLinq/MyLinq.Tests/MyLinq.Tests.csproj b/MyLinq/MyLinq.Tests/MyLinq.Tests.csproj new file mode 100644 index 0000000..8c176c4 --- /dev/null +++ b/MyLinq/MyLinq.Tests/MyLinq.Tests.csproj @@ -0,0 +1,28 @@ + + + + net9.0 + latest + enable + enable + + true + + + + + + + + + + + + + + + + + + + diff --git a/MyLinq/MyLinq.Tests/MyLinqTests.cs b/MyLinq/MyLinq.Tests/MyLinqTests.cs new file mode 100644 index 0000000..f970e0d --- /dev/null +++ b/MyLinq/MyLinq.Tests/MyLinqTests.cs @@ -0,0 +1,94 @@ +// +// Copyright (c) Ilya Krivtsov. All rights reserved. +// + +namespace MyLinq.Tests; + +public class MyLinqTests +{ + [Test] + public void GetPrimes_Yields_PrimeNumbers() + { + int iterations = 100; + + foreach (var (index, prime) in MyLinq.GetPrimes().Index()) + { + if (index >= iterations) + { + break; + } + + for (uint i = 2; i < prime; i++) + { + Assert.That(prime % i, Is.Not.EqualTo(0)); + } + } + } + + [Test] + public void Take_ReturnsSequence_With_First_N_Elements() + { + int takeCount = 47; + Assert.That( + MyLinq.Take(Enumerable.Range(0, 100), takeCount) + .SequenceEqual(Enumerable.Range(0, takeCount)), + Is.True); + } + + [Test] + public void Take_ReturnsSameSequence_If_CountIsGreaterThanOrEqualTo_SourceCount() + { + int count = 100; + var range = Enumerable.Range(0, count); + Assert.Multiple(() => + { + Assert.That(MyLinq.Take(range, count).SequenceEqual(range), Is.True); + Assert.That(MyLinq.Take(range, count + 1).SequenceEqual(range), Is.True); + }); + } + + [Test] + public void Take_ReturnsEmptySequence_If_CountIs_LessThanOrEqualTo_Zero() + { + var range = Enumerable.Range(0, 100); + Assert.Multiple(() => + { + Assert.That(MyLinq.Take(range, 0).Any(), Is.False); + Assert.That(MyLinq.Take(range, -1).Any(), Is.False); + }); + } + + [Test] + public void Skip_ReturnsSequence_Without_First_N_Elements() + { + int takeCount = 53; + Assert.That( + MyLinq.Skip(Enumerable.Range(0, 100), takeCount) + .SequenceEqual(Enumerable.Range(takeCount, 100 - takeCount)), + Is.True); + } + + [Test] + public void Skip_ReturnsSameSequence_If_CountIsLessThanOrEqualTo_Zero() + { + int count = 100; + var range = Enumerable.Range(0, count); + Assert.Multiple(() => + { + Assert.That(MyLinq.Skip(range, 0).SequenceEqual(range), Is.True); + Assert.That(MyLinq.Skip(range, -1).SequenceEqual(range), Is.True); + }); + } + + [Test] + public void Skip_ReturnsEmptySequence_If_CountIsGreaterThanOrEqualTo_SourceCount() + { + int count = 100; + var range = Enumerable.Range(0, count); + Assert.Multiple(() => + { + Assert.That(MyLinq.Skip(range, count).Any(), Is.False); + Assert.That(MyLinq.Skip(range, count + 1).Any(), Is.False); + }); + } +} diff --git a/MyLinq/MyLinq.sln b/MyLinq/MyLinq.sln new file mode 100644 index 0000000..4082121 --- /dev/null +++ b/MyLinq/MyLinq.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyLinq", "MyLinq\MyLinq.csproj", "{29852F1B-EA67-4A5F-921D-52E576AB1D21}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MyLinq.Tests", "MyLinq.Tests", "{57E4A64D-212E-B59A-67DA-DA99F8ED86A3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyLinq.Tests", "MyLinq.Tests\MyLinq.Tests.csproj", "{69B64B70-96AF-4C17-8F62-95FCA2604676}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Debug|x64.ActiveCfg = Debug|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Debug|x64.Build.0 = Debug|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Debug|x86.ActiveCfg = Debug|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Debug|x86.Build.0 = Debug|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Release|Any CPU.Build.0 = Release|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Release|x64.ActiveCfg = Release|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Release|x64.Build.0 = Release|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Release|x86.ActiveCfg = Release|Any CPU + {29852F1B-EA67-4A5F-921D-52E576AB1D21}.Release|x86.Build.0 = Release|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Debug|Any CPU.Build.0 = Debug|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Debug|x64.ActiveCfg = Debug|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Debug|x64.Build.0 = Debug|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Debug|x86.ActiveCfg = Debug|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Debug|x86.Build.0 = Debug|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Release|Any CPU.ActiveCfg = Release|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Release|Any CPU.Build.0 = Release|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Release|x64.ActiveCfg = Release|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Release|x64.Build.0 = Release|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Release|x86.ActiveCfg = Release|Any CPU + {69B64B70-96AF-4C17-8F62-95FCA2604676}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {69B64B70-96AF-4C17-8F62-95FCA2604676} = {57E4A64D-212E-B59A-67DA-DA99F8ED86A3} + EndGlobalSection +EndGlobal diff --git a/MyLinq/MyLinq/MyLinq.cs b/MyLinq/MyLinq/MyLinq.cs new file mode 100644 index 0000000..7dbea2d --- /dev/null +++ b/MyLinq/MyLinq/MyLinq.cs @@ -0,0 +1,83 @@ +// +// Copyright (c) Ilya Krivtsov. All rights reserved. +// + +namespace MyLinq; + +/// +/// Utility class with GetPrimes, Take and Skip functions. +/// +public static class MyLinq +{ + /// + /// Practically infinite sequence of prime numbers. + /// + /// Sequence of prime numbers. + public static IEnumerable GetPrimes() + { + yield return 2; + yield return 3; + ulong lastPrime = 3; + while (true) + { + lastPrime += 2; + bool isPrime = true; + for (ulong i = 2; i * i <= lastPrime; i++) + { + if (lastPrime % i == 0) + { + isPrime = false; + break; + } + } + + if (isPrime) + { + yield return lastPrime; + } + } + } + + /// + /// Sequence with first items from . + /// + /// Item type. + /// Sequence to take first items from. + /// How many items to take. + /// Subsequence of . + public static IEnumerable Take(this IEnumerable sequence, int count) + { + int index = 0; + foreach (var item in sequence) + { + if (index >= count) + { + yield break; + } + + yield return item; + index++; + } + } + + /// + /// Sequence without first items from . + /// + /// Item type. + /// Sequence to skip first items from. + /// How many items to skip. + /// Subsequence of . + public static IEnumerable Skip(this IEnumerable sequence, int count) + { + int index = 0; + foreach (var item in sequence) + { + if (index >= count) + { + yield return item; + } + + index++; + } + } +} diff --git a/MyLinq/MyLinq/MyLinq.csproj b/MyLinq/MyLinq/MyLinq.csproj new file mode 100644 index 0000000..bf05b58 --- /dev/null +++ b/MyLinq/MyLinq/MyLinq.csproj @@ -0,0 +1,10 @@ + + + + Library + net9.0 + enable + enable + + +