-
Notifications
You must be signed in to change notification settings - Fork 0
Intermediate Test - [Priority Queue]
#1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| namespace PriorityQueue.Tests; | ||
|
|
||
| public abstract class GenericPriorityQueueTests<TElement, TPriority> | ||
| { | ||
| private PriorityQueue<TElement, TPriority> queue; | ||
|
|
||
| public virtual IComparer<TPriority>? Comparer { get; } | ||
|
|
||
| public abstract ItemPair SingleTestPair { get; } | ||
|
|
||
| public abstract IEnumerable<ItemPair> SamePriorityTestPairs { get; } | ||
|
|
||
| public abstract IEnumerable<ItemPair> IncreasingPriorityTestPairs { get; } | ||
|
|
||
| [SetUp] | ||
| public void Setup() | ||
| { | ||
| queue = Comparer == null ? new() : new(Comparer); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Активнее используйте expression-bodied-методы |
||
|
|
||
| [Test] | ||
| public void Empty_ShouldBeTrue_ForEmptyQueue() | ||
| { | ||
| Assert.That(queue.Empty, Is.True); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Empty_ShouldBeFalse_ForNonEmptyQueue() | ||
| { | ||
| queue.Enqueue(SingleTestPair.Element, SingleTestPair.Priority); | ||
| Assert.That(queue.Empty, Is.False); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Dequeue_ShouldThrow_IfQueueIsEmpty() | ||
| { | ||
| Assert.Throws<InvalidOperationException>(() => queue.Dequeue()); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Dequeue_ShouldReturn_EnqueuedItem() | ||
| { | ||
| queue.Enqueue(SingleTestPair.Element, SingleTestPair.Priority); | ||
| Assert.That(queue.Dequeue(), Is.EqualTo(SingleTestPair.Element)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void Dequeue_ShouldReturn_EnqueuedItems_InSameOrder_IfPriorityIsSame() | ||
| { | ||
| foreach (var (element, priority) in SamePriorityTestPairs) | ||
| { | ||
| queue.Enqueue(element, priority); | ||
| } | ||
|
|
||
| foreach (var (element, priority) in SamePriorityTestPairs) | ||
| { | ||
| Assert.That(queue.Dequeue(), Is.EqualTo(element)); | ||
| } | ||
| } | ||
|
|
||
| [Test] | ||
| public void Dequeue_ShouldReturn_EnqueuedItems_InReverseOrder_IfPriorityIsDecreasing() | ||
| { | ||
| foreach (var (element, priority) in IncreasingPriorityTestPairs.Reverse()) | ||
| { | ||
| queue.Enqueue(element, priority); | ||
| } | ||
|
|
||
| foreach (var (element, priority) in IncreasingPriorityTestPairs) | ||
| { | ||
| Assert.That(queue.Dequeue(), Is.EqualTo(element)); | ||
| } | ||
| } | ||
|
|
||
| public readonly record struct ItemPair(TElement Element, TPriority Priority); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| // 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 project with tests")] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <LangVersion>latest</LangVersion> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| <IsPackable>false</IsPackable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="coverlet.collector" Version="6.0.2" /> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" /> | ||
| <PackageReference Include="NUnit" Version="4.2.2" /> | ||
| <PackageReference Include="NUnit.Analyzers" Version="4.4.0" /> | ||
| <PackageReference Include="NUnit3TestAdapter" Version="4.6.0" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Using Include="NUnit.Framework" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="../PriorityQueue/PriorityQueue.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| namespace PriorityQueue.Tests; | ||
|
|
||
| public static class TypedPriorityQueueTests | ||
| { | ||
| public class IntPriorityQueue : GenericPriorityQueueTests<int, int> | ||
| { | ||
| public override ItemPair SingleTestPair => new(123, 456); | ||
|
|
||
| public override IEnumerable<ItemPair> SamePriorityTestPairs => Enumerable.Range(1, 64).Select(x => new ItemPair(x, 123)); | ||
|
|
||
| public override IEnumerable<ItemPair> IncreasingPriorityTestPairs => Enumerable.Range(1, 64).Select(x => new ItemPair(x, x)); | ||
| } | ||
|
|
||
| public class StringPriorityQueue : GenericPriorityQueueTests<string, string> | ||
| { | ||
| public override IComparer<string>? Comparer { get; } = new NumberStringComparer(); | ||
|
|
||
| public override ItemPair SingleTestPair => new("1234", "4444"); | ||
|
|
||
| public override IEnumerable<ItemPair> SamePriorityTestPairs => Enumerable.Range(1, 64) | ||
| .Select(x => x.ToString().PadLeft(3, '0')).Select(x => new ItemPair(x, x)); | ||
|
|
||
| public override IEnumerable<ItemPair> IncreasingPriorityTestPairs => Enumerable.Range(1, 8) | ||
| .Select(x => new string('1', x)).Select(x => new ItemPair(x, x)); | ||
|
|
||
| private class NumberStringComparer : IComparer<string> | ||
| { | ||
| public int Compare(string? x, string? y) | ||
| => int.Parse(x ?? "0") - int.Parse(y ?? "0"); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| | ||
| 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}") = "PriorityQueue", "PriorityQueue\PriorityQueue.csproj", "{DACEF6B2-BF52-446A-B201-C0D652F8A1FC}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PriorityQueue.Tests", "PriorityQueue.Tests\PriorityQueue.Tests.csproj", "{072C7A26-3045-4432-B398-4AC1353DF895}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {072C7A26-3045-4432-B398-4AC1353DF895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {072C7A26-3045-4432-B398-4AC1353DF895}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {072C7A26-3045-4432-B398-4AC1353DF895}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {072C7A26-3045-4432-B398-4AC1353DF895}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| EndGlobal |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| namespace PriorityQueue; | ||
|
|
||
| /// <summary> | ||
| /// Prioirty queue data structure. | ||
| /// </summary> | ||
| /// <typeparam name="TElement">Type of elements.</typeparam> | ||
| /// <typeparam name="TPriority">Type of priority associated with each element.</typeparam> | ||
| public class PriorityQueue<TElement, TPriority> | ||
| { | ||
| private IComparer<TPriority> comparer; | ||
| private Item? head; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="PriorityQueue{TValue, TPriority}"/> class. | ||
| /// </summary> | ||
| /// <param name="comparer">Comparer to use; if <see langword="null"/>, defaults to <see cref="Comparer{TPriority}.Default"/>.</param> | ||
| public PriorityQueue(IComparer<TPriority>? comparer = null) | ||
| { | ||
| head = null; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Да оно и так null, явной инициализации в конструкторе не требуется (это же не C++) |
||
| this.comparer = comparer ?? Comparer<TPriority>.Default; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="PriorityQueue{TValue, TPriority}"/> class. | ||
| /// </summary> | ||
| public PriorityQueue() | ||
| : this(null) | ||
| { | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets a value indicating whether queue is empty. | ||
| /// </summary> | ||
| public bool Empty => head == null; | ||
|
|
||
| /// <summary> | ||
| /// Enqueues element into the queue. | ||
| /// </summary> | ||
| /// <param name="element">Element to enqueue.</param> | ||
| /// <param name="priority">Priority of the <paramref name="element"/>.</param> | ||
| public void Enqueue(TElement element, TPriority priority) | ||
| { | ||
| var item = head; | ||
| if (item == null) | ||
| { | ||
| item = new(element, priority, null); | ||
| head = item; | ||
| return; | ||
| } | ||
|
|
||
| if (comparer.Compare(priority, item.Priority) < 0) | ||
| { | ||
| var newHead = new Item(element, priority, item); | ||
| head = newHead; | ||
| return; | ||
| } | ||
|
|
||
| while (item.Next != null && comparer.Compare(priority, item.Next.Priority) >= 0) | ||
| { | ||
| item = item.Next; | ||
| } | ||
|
|
||
| var newItem = new Item(element, priority, item.Next); | ||
| item.Next = newItem; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Dequeues element with the least priority from the queue. | ||
| /// </summary> | ||
| /// <returns>Element with the least priority .</returns> | ||
| public TElement Dequeue() | ||
| { | ||
| if (head == null) | ||
| { | ||
| throw new InvalidOperationException("Queue is empty"); | ||
| } | ||
|
|
||
| var item = head; | ||
| head = item.Next; | ||
| return item.Element; | ||
| } | ||
|
|
||
| private class Item(TElement element, TPriority priority, Item? next) | ||
| { | ||
| public TElement Element => element; | ||
|
|
||
| public TPriority Priority => priority; | ||
|
|
||
| public Item? Next { get; set; } = next; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Что-то StyleCop не подключен, ни тут, ни в тестах. А GlobalSuppressions для него есть
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Он в Directory.Build.props в корне |
||
|
|
||
| </Project> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Надо ещё шапку с информацией о лицензии