diff --git a/NewBorForCI/NewBorForCI.sln b/NewBorForCI/NewBorForCI.sln new file mode 100644 index 0000000..87768e0 --- /dev/null +++ b/NewBorForCI/NewBorForCI.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33403.182 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewBorForCI", "NewBorForCI\NewBorForCI.csproj", "{9A77CDBE-D0EE-4CED-B5B7-92B3567E6BAE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestsTrie", "TestsBor\TestsTrie.csproj", "{8ECB64A5-1B15-4C3F-85A6-34DDE66CE741}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9A77CDBE-D0EE-4CED-B5B7-92B3567E6BAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A77CDBE-D0EE-4CED-B5B7-92B3567E6BAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A77CDBE-D0EE-4CED-B5B7-92B3567E6BAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A77CDBE-D0EE-4CED-B5B7-92B3567E6BAE}.Release|Any CPU.Build.0 = Release|Any CPU + {8ECB64A5-1B15-4C3F-85A6-34DDE66CE741}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ECB64A5-1B15-4C3F-85A6-34DDE66CE741}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8ECB64A5-1B15-4C3F-85A6-34DDE66CE741}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8ECB64A5-1B15-4C3F-85A6-34DDE66CE741}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {22B84F78-A6D8-4810-95B6-A79AEF403E7F} + EndGlobalSection +EndGlobal diff --git a/NewBorForCI/NewBorForCI/NewBorForCI.csproj b/NewBorForCI/NewBorForCI/NewBorForCI.csproj new file mode 100644 index 0000000..dc2bb05 --- /dev/null +++ b/NewBorForCI/NewBorForCI/NewBorForCI.csproj @@ -0,0 +1,10 @@ + + + + Library + net7.0 + enable + enable + + + diff --git a/NewBorForCI/NewBorForCI/Trie.cs b/NewBorForCI/NewBorForCI/Trie.cs new file mode 100644 index 0000000..2fa0433 --- /dev/null +++ b/NewBorForCI/NewBorForCI/Trie.cs @@ -0,0 +1,149 @@ +using System.Xml.Linq; + +namespace Trie; + +// A container for storing strings, in the form of a suspended tree +public class Trie +{ + private TrieElement root = new(); + + // Adding an element + public bool Add(string element) + { + ArgumentNullException.ThrowIfNull(element); + root.NumberOfLinesInTheDictionary++; + var walker = root; + int i = 0; + while (i < element.Length) + { + char number = element[i]; + if (!walker.Next.ContainsKey(number)) + { + walker.Next.Add(number, new TrieElement()); + } + ++walker.Next[number].NumberOfLinesInTheDictionary; + walker = walker.Next[number]; + i++; + } + if (!walker.IsTerminal) + { + walker.IsTerminal = true; + return true; + } + return false; + } + + private bool RemoveHelp(TrieElement walker, string element, int position, ref bool isDeleted) + { + if (position == element.Length) + { + if (walker.IsTerminal) + { + walker.IsTerminal = false; + return true; + } + return false; + } + + if (walker.Next.ContainsKey(element[position])) + { + bool isCorrect = RemoveHelp(walker.Next[element[position]], element, position + 1, ref isDeleted); + if (!isCorrect) + { + return false; + } + if (walker.Next[element[position]].NumberOfLinesInTheDictionary == 1) + { + walker.Next.Remove(element[position]); + isDeleted = true; + return true; + } + if (isDeleted) + { + isDeleted = false; + } + --walker.Next[element[position]].NumberOfLinesInTheDictionary; + return true; + } + return false; + } + + // Deleting an element in the tree + public bool Remove(string element) + { + if (root == null) + { + throw new InvalidOperationException(); + } + if (element == null) + { + throw new ArgumentNullException(); + } + + if (element == "") + { + root.IsTerminal = false; + return true; + } + var walker = root; + bool isDeleted = false; + if (RemoveHelp(walker, element, 0, ref isDeleted)) + { + --root.NumberOfLinesInTheDictionary; + return true; + } + return false; + } + + // Counts the number of rows with the same prefix + public int HowManyStartsWithPrefix(string prefix) + { + ArgumentNullException.ThrowIfNull(root); + + var walker = root; + int i = 0; + while (i < prefix.Length) + { + if (!walker.Next.ContainsKey(prefix[i])) + { + return 0; + } + walker = walker.Next[prefix[i]]; + ++i; + } + return walker.NumberOfLinesInTheDictionary; + } + + // Checks for the presence of a string + public bool Contains(string element) + { + ArgumentNullException.ThrowIfNull(root); + + var walker = root; + int i = 0; + while (i < element.Length) + { + if (!walker.Next.ContainsKey(element[i])) + { + return false; + } + walker = walker.Next[element[i]]; + ++i; + } + return true; + } + + private class TrieElement + { + public Dictionary Next { get; set; } + public bool IsTerminal { get; set; } + + + public int NumberOfLinesInTheDictionary { get; set; } + + public TrieElement() + { + Next = new Dictionary(); + } + } +} \ No newline at end of file diff --git a/NewBorForCI/TestsBor/TestsTrie.cs b/NewBorForCI/TestsBor/TestsTrie.cs new file mode 100644 index 0000000..475f028 --- /dev/null +++ b/NewBorForCI/TestsBor/TestsTrie.cs @@ -0,0 +1,74 @@ +namespace Trie; + +public class Tests +{ + private Trie? trie; + + [SetUp] + public void TestInitialize() + { + trie = new(); + Assert.IsNotNull(trie); + } + + [Test] + public void TheAddedElementShouldbeFoundInBor() + { + TestInitialize(); + trie.Add("end"); + Assert.True(trie.Contains("end")); + } + + [Test] + public void ByAddingAndRemovingAnElementItShouldNotStayInBor() + { + TestInitialize(); + trie.Add("end"); + trie.Remove("end"); + Assert.False(trie.Contains("end")); + } + + [Test] + public void AddTwoStringsWithTheSamePrefixBorTheNumberOfStringsWithThisPrefixIsTwo() + { + TestInitialize(); + trie.Add("endProgram"); + trie.Add("endFunction"); + Assert.That(trie.HowManyStartsWithPrefix("end") == 2); + } + + [Test] + public void WhenEnteringDifferentStringsTheNumberOfStringsWithTheSamePrefixNotZeroMustBeOne() + { + TestInitialize(); + trie.Add("aaaaa"); + trie.Add("bbbbb"); + trie.Add("ccccc"); + Assert.That(trie.HowManyStartsWithPrefix("a") == 1); + } + + [Test] + public void TheAnswerToANoExistentPrefixInTheBorShouldBeOne() + { + TestInitialize(); + trie.Add("adadasd"); + Assert.That(trie.HowManyStartsWithPrefix("dsdsd") == 0); + } + + [Test] + public void AnEmptyPrefixShouldGiveOuAllTheLinesInTheBor() + { + TestInitialize(); + trie.Add("adads"); + trie.Add("ddsds"); + trie.Add("End"); + Assert.That(trie.HowManyStartsWithPrefix("") == 3); + } + + [Test] + public void EmptyBorShouldGiveZeroStringsInBor() + { + TestInitialize(); + Assert.That(trie.HowManyStartsWithPrefix("") == 0); + } +} \ No newline at end of file diff --git a/NewBorForCI/TestsBor/TestsTrie.csproj b/NewBorForCI/TestsBor/TestsTrie.csproj new file mode 100644 index 0000000..bd2f697 --- /dev/null +++ b/NewBorForCI/TestsBor/TestsTrie.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/NewBorForCI/TestsBor/Usings.cs b/NewBorForCI/TestsBor/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/NewBorForCI/TestsBor/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file