-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from kamendov-maxim/Bor
Бор
- Loading branch information
Showing
7 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
using System.Buffers.Binary; | ||
using System.ComponentModel; | ||
using System.Diagnostics.Contracts; | ||
using System.Globalization; | ||
using System.Linq.Expressions; | ||
using System.Net.Sockets; | ||
using System.Runtime.CompilerServices; | ||
using System.Xml; | ||
|
||
namespace Data_Structures; | ||
public class Bor : IDataStructure | ||
{ | ||
public Bor() | ||
{ | ||
this.Size = 0; | ||
this.root = new Node(); | ||
} | ||
|
||
private class Node | ||
{ | ||
public Node() | ||
{ | ||
this.Children = new Dictionary<char, Node>(); | ||
endOfWord = false; | ||
} | ||
|
||
public Dictionary<char, Node> Children; | ||
public bool endOfWord; | ||
} | ||
|
||
public bool Add(string element) | ||
{ | ||
Node tempRoot = root; | ||
int total = element.Length - 1; | ||
bool answer = false; | ||
for (int i = 0; i < element.Length; i++) | ||
{ | ||
if (tempRoot.Children.TryGetValue(element[i], out Node? value)) | ||
{ | ||
tempRoot = value; | ||
if (!tempRoot.endOfWord && i == element.Length - 1) | ||
{ | ||
tempRoot.endOfWord = true; | ||
return true; | ||
} | ||
} | ||
else | ||
{ | ||
answer = true; | ||
var newTrie = new Node(); | ||
|
||
if (total == i) | ||
{ | ||
newTrie.endOfWord = true; | ||
} | ||
|
||
tempRoot.Children.Add(element[i], newTrie); | ||
tempRoot = newTrie; | ||
} | ||
} | ||
return answer; | ||
} | ||
|
||
public bool Contains(string element) | ||
{ | ||
Node tempRoot = root; | ||
int total = element.Length - 1; | ||
for (int i = 0; i < element.Length; i++) | ||
{ | ||
if (tempRoot.Children.TryGetValue(element[i], out Node? value)) | ||
{ | ||
tempRoot = value; | ||
|
||
if (total == i) | ||
{ | ||
if (tempRoot.endOfWord == true) | ||
{ | ||
return true; | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
public bool Remove(string element) | ||
{ | ||
Node? nodeFromWhereToDelete = null; | ||
char startOfWordToDelete = default; | ||
var previousNode = root; | ||
int i = 0; | ||
for (i = 0; i < element.Length; ++i) | ||
{ | ||
if (previousNode.Children.TryGetValue(element[i], out Node? currentNode)) | ||
{ | ||
if (i + 1 == element.Length && currentNode.endOfWord == true && currentNode.Children.Count > 0) | ||
{ | ||
currentNode.endOfWord = false; | ||
return true; | ||
} | ||
if (nodeFromWhereToDelete is null || currentNode.Children.Count > 1) | ||
{ | ||
nodeFromWhereToDelete = currentNode; | ||
startOfWordToDelete = element[i + 1]; | ||
} | ||
|
||
previousNode = currentNode; | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
if (nodeFromWhereToDelete is null) | ||
{ | ||
throw new InvalidOperationException("Trie does not work correclty"); | ||
} | ||
|
||
nodeFromWhereToDelete.Children.Remove(startOfWordToDelete); | ||
|
||
return true; | ||
} | ||
|
||
public int HowManyStartsWithPrefix(string prefix) | ||
{ | ||
Node tempNode = root; | ||
int total = prefix.Length - 1; | ||
for (int i = 0; i < prefix.Length; i++) | ||
{ | ||
if (tempNode.Children.ContainsKey(prefix[i])) | ||
{ | ||
tempNode = tempNode.Children[prefix[i]]; | ||
} | ||
else | ||
{ | ||
return 0; | ||
} | ||
} | ||
return PrefixRecursion(tempNode); | ||
} | ||
|
||
private static int PrefixRecursion(Node root) | ||
{ | ||
int answer = 0; | ||
var nodes = root.Children.Select(x => x.Value); | ||
foreach (var node in nodes) | ||
{ | ||
if (node.endOfWord) | ||
{ | ||
++answer; | ||
} | ||
answer += PrefixRecursion(node); | ||
} | ||
return answer; | ||
} | ||
|
||
public int Size; | ||
private readonly Node root; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace Data_Structures; | ||
|
||
interface IDataStructure | ||
{ | ||
bool Add(string element); | ||
|
||
bool Contains(string element); | ||
|
||
bool Remove(string element); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using System.Runtime.InteropServices; | ||
using Data_Structures; | ||
|
||
class Program | ||
{ | ||
public enum UserInput | ||
{ | ||
addEntry, | ||
checkWord, | ||
removeEntry, | ||
wordsWithPrefix, | ||
printSize, | ||
exitProgram | ||
} | ||
|
||
public static void PrintOptions() | ||
{ | ||
Console.WriteLine("Введите команду:"); | ||
Console.WriteLine("0 - добавить слово"); | ||
Console.WriteLine("1 - проверить, есть ли такое слово"); | ||
Console.WriteLine("2 - удалить слово"); | ||
Console.WriteLine("3 - посчитать количество слов с префиксом"); | ||
Console.WriteLine("4 - посчитать размер бора"); | ||
Console.WriteLine("5 - выйти"); | ||
} | ||
|
||
public static UserInput GetUserInput() | ||
{ | ||
int userInput = Convert.ToInt32(Console.ReadLine()); | ||
while (!typeof(UserInput).IsEnumDefined(userInput)) | ||
{ | ||
Console.WriteLine("Введите цифру от 0 до 5"); | ||
userInput = Convert.ToInt32(Console.ReadLine()); | ||
} | ||
return (UserInput)userInput; | ||
} | ||
|
||
public static void Main() | ||
{ | ||
var myBor = new Bor(); | ||
var input = UserInput.checkWord; | ||
while (input != UserInput.exitProgram) | ||
{ | ||
PrintOptions(); | ||
input = GetUserInput(); | ||
switch (input) | ||
{ | ||
case UserInput.addEntry: | ||
{ | ||
Console.WriteLine("Введите строку"); | ||
string? str = Console.ReadLine(); | ||
myBor.Add(str!); | ||
Console.WriteLine("Строка добавлена"); | ||
break; | ||
} | ||
case | ||
UserInput.checkWord: | ||
{ | ||
Console.WriteLine("Введите строку"); | ||
string? str = Console.ReadLine(); | ||
if (myBor.Contains(str!)) | ||
{ | ||
Console.WriteLine("Такая строка есть"); | ||
} | ||
else | ||
{ | ||
Console.WriteLine("Такой строки нет"); | ||
} | ||
break; | ||
} | ||
case UserInput.printSize: | ||
{ | ||
Console.WriteLine($"Размер бора - {myBor.Size}"); | ||
break; | ||
} | ||
case UserInput.removeEntry: | ||
{ | ||
|
||
Console.WriteLine("Введите строку"); | ||
string? str = Console.ReadLine(); | ||
myBor.Remove(str!); | ||
Console.WriteLine("Строка удалена"); | ||
break; | ||
} | ||
case UserInput.wordsWithPrefix: | ||
{ | ||
Console.WriteLine("Введите префикс"); | ||
string? str = Console.ReadLine(); | ||
Console.WriteLine($"Слов с таким префиксом: {myBor.HowManyStartsWithPrefix(str!)}"); | ||
break; | ||
} | ||
case UserInput.exitProgram: | ||
{ | ||
Console.WriteLine("Заврешение работы программы"); | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
namespace Bor.Tests; | ||
using Data_Structures; | ||
|
||
public class Tests | ||
{ | ||
Bor trie; | ||
readonly string[] testStrings = ["abcdef", "abcdrfg", "abuq", "abcdeyunkhnrlnh", | ||
"slgbfb;gajga", "sldgaslgnlkg", "agdfjhahg"]; | ||
|
||
[SetUp] | ||
public void Setup() | ||
{ | ||
trie = new(); | ||
} | ||
|
||
[Test] | ||
public void Test1() | ||
{ | ||
foreach (string testString in testStrings) | ||
trie.Add(testString); | ||
|
||
foreach (var testString in testStrings) | ||
{ | ||
Assert.That(trie.Contains(testString)); | ||
} | ||
|
||
trie.Remove("abcdef"); | ||
|
||
foreach (var testString in testStrings) | ||
{ | ||
if (testString == "abcdef") | ||
{ | ||
Assert.That(!trie.Contains(testString)); | ||
} | ||
else | ||
{ | ||
Assert.That(trie.Contains(testString)); | ||
} | ||
} | ||
|
||
trie.Remove("abcdeyunkhnrlnh"); | ||
trie.Remove("slgbfb;gajga"); | ||
|
||
foreach (var testString in testStrings) | ||
{ | ||
if (testString == "abcdef" || testString == "abcdeyunkhnrlnh" || testString == "slgbfb;gajga") | ||
{ | ||
Assert.That(!trie.Contains(testString)); | ||
} | ||
else | ||
{ | ||
Assert.That(trie.Contains(testString)); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | ||
<PackageReference Include="NUnit" Version="3.14.0" /> | ||
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="NUnit.Framework" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Bor.Src\Bor.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Oops, something went wrong.