Skip to content
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

Trie #3

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions Trie/Trie/Trie.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
namespace TrieClass
{
/// <summary>
/// Trie class.
/// </summary>
public class Trie
{
private readonly Dictionary<char, Trie> children;

/// <summary>
/// Initializes a new instance of the <see cref="Trie"/> class.
/// </summary>
public Trie()
{
this.children = [];
this.IsTerminal = false;
this.CountOfTerminalsFarther = 0;
}

/// <summary>
/// Gets a value indicating whether the edge is terminal.
/// </summary>
public bool IsTerminal { get; private set; }

/// <summary>
/// Gets the trie size.
/// </summary>
public int Size => this.CountOfTerminalsFarther;

private int CountOfTerminalsFarther { get; set; }
Comment on lines +28 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не уверен, почему бы не объединить их в одно поле, но если уж делаем private ..., то геттеры и сеттеры писать не надо.
Без геттеров/сеттеров - это будет честное поле класса. С геттерами/сеттерами это будет поле класса, спрятанное под функциями гет и сет.
image
image


/// <summary>
/// Adds given string to trie.
/// </summary>
/// <param name="element">String to add to the trie.</param>
/// <returns>True if successful, otherwise false.</returns>
public bool Add(string element)
{
if (element.Length == 0)
{
if (this.IsTerminal)
{
return false;
}

this.IsTerminal = true;
this.CountOfTerminalsFarther++;

return true;
}

if (!this.children.TryGetValue(element[0], out Trie? child))
{
child = new Trie();
this.children.Add(element[0], child);
}

if (child.Add(element[1..]))
{
this.CountOfTerminalsFarther++;

return true;
}

return false;
}

/// <summary>
/// Checks whether the element is contained in the trie.
/// </summary>
/// <param name="element">The element that needs to be checked if it is in the trie.</param>
/// <returns>True if successful, otherwise false.</returns>
public bool Contains(string element)
{
Trie? result = this.FindEdgeWithKey(element);

return result != null && result.IsTerminal;
}

/// <summary>
/// Removes an element from the trie.
/// </summary>
/// <param name="element">The element to be removed from the trie.</param>
/// <returns>True if successful, otherwise false.</returns>
public bool Remove(string element)
{
if (element.Length == 0)
{
if (!this.IsTerminal)
{
return false;
}

this.CountOfTerminalsFarther--;
this.IsTerminal = false;

return true;
}

if (!this.children.TryGetValue(element[0], out Trie? value))
{
return false;
}

if (value.Remove(element[1..]))
{
this.CountOfTerminalsFarther--;
if (value.CountOfTerminalsFarther == 0)
{
this.children.Remove(element[0]);
}

return true;
}

return false;
}

/// <summary>
/// Searches for how many trie elements start with a given prefix.
/// </summary>
/// <param name="prefix">The prefix for the search.</param>
/// <returns>The number of elements starting with this prefix.</returns>
public int HowManyStartsWithPrefix(string prefix)
{
if (prefix.Length == 0)
{
return this.CountOfTerminalsFarther;
}

if (!this.children.TryGetValue(prefix[0], out Trie? edge))
{
return 0;
}

return edge.HowManyStartsWithPrefix(prefix[1..]);
}

private Trie? FindEdgeWithKey(string key)
{
if (key.Length == 0)
{
return this;
}

if (!this.children.TryGetValue(key[0], out Trie? child))
{
return null;
}

return child.FindEdgeWithKey(key[1..]);
}
}
}
9 changes: 9 additions & 0 deletions Trie/Trie/Trie.csproj

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вообще, я имел ввиду не убирать целиком анализатор, а отключать конкретные варнинги, которые себя криво ведут 🤔

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
31 changes: 31 additions & 0 deletions Trie/Trie/Trie.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34607.119
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Trie", "Trie.csproj", "{B7F7A03C-3413-46A2-B23F-23680C6067B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TrieTests", "..\TrieTests\TrieTests.csproj", "{1C42C607-28FA-4520-A656-ABA4702B9BBA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B7F7A03C-3413-46A2-B23F-23680C6067B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7F7A03C-3413-46A2-B23F-23680C6067B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7F7A03C-3413-46A2-B23F-23680C6067B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7F7A03C-3413-46A2-B23F-23680C6067B2}.Release|Any CPU.Build.0 = Release|Any CPU
{1C42C607-28FA-4520-A656-ABA4702B9BBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1C42C607-28FA-4520-A656-ABA4702B9BBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C42C607-28FA-4520-A656-ABA4702B9BBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C42C607-28FA-4520-A656-ABA4702B9BBA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FE822E7C-39B7-4707-B1DA-DB3584687258}
EndGlobalSection
EndGlobal
61 changes: 61 additions & 0 deletions Trie/TrieTests/TrieTest.cs

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Стоило бы добавить хоть один тест на Size, раз уж это часть публичного API, в остальном норм

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using TrieClass;

[TestFixture]
public class TrieTests
{
private Trie trie;

[SetUp]
public void Setup()
{
trie = new Trie();
}

[Test]
public void AddElement_ReturnsTrue()
{
Assert.IsTrue(trie.Add("hello"));
}

[Test]
public void AddExistingElement_ReturnsFalse()
{
trie.Add("hello");
Assert.IsFalse(trie.Add("hello"));
}

[Test]
public void ContainsElement_ReturnsTrue()
{
trie.Add("world");
Assert.IsTrue(trie.Contains("world"));
}

[Test]
public void DoesNotContainElement_ReturnsFalse()
{
Assert.IsFalse(trie.Contains("world"));
}

[Test]
public void RemoveElement_ReturnsTrue()
{
trie.Add("apple");
Assert.IsTrue(trie.Remove("apple"));
}

[Test]
public void RemoveNotExistingElement_ReturnsFalse()
{
Assert.IsFalse(trie.Remove("hello"));
}

[Test]
public void HowManyStartsWithPrefix_ReturnsCorrectCount()
{
trie.Add("cat");
trie.Add("car");
trie.Add("dog");
Assert.That(trie.HowManyStartsWithPrefix("c"), Is.EqualTo(2));
}
}
36 changes: 36 additions & 0 deletions Trie/TrieTests/TrieTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<None Include="..\Trie\.editorconfig" Link=".editorconfig" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Microsoft.Playwright.NUnit" Version="1.27.1" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Trie\Trie.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="Microsoft.Playwright.NUnit" />
<Using Include="NUnit.Framework" />
<Using Include="System.Text.RegularExpressions" />
<Using Include="System.Threading.Tasks" />
</ItemGroup>

</Project>