diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 0000000..94ac0b1 --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,38 @@ +name: Build + +on: [push] + +jobs: + build-Windows: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Build + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.x' + - name: Restore + run: $slnList = Get-ChildItem $foo.FullName -Recurse -Filter '*.sln'; foreach ($file in $slnList) {nuget restore $file.FullName} + - name: Build + run: $slnList = Get-ChildItem $foo.FullName -Recurse -Filter '*.sln'; foreach ($file in $slnList) {dotnet build $file.FullName} + - name: Test + run: $slnList = Get-ChildItem $foo.FullName -Recurse -Filter '*.sln'; foreach ($file in $slnList) {dotnet test $file.FullName} + + build-Ubuntu: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Build + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '6.x' + - name: Restore + run: for f in $(find . -name "*.sln"); do dotnet restore $f; done + - name: Build + run: for f in $(find . -name "*.sln"); do dotnet build $f; done + - name: Test + run: for f in $(find . -name "*.sln"); do dotnet test $f; done \ No newline at end of file diff --git a/Homework2/Bor/Bor.sln b/Homework2/Bor/Bor.sln new file mode 100644 index 0000000..66a4364 --- /dev/null +++ b/Homework2/Bor/Bor.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32210.238 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bor", "Bor\Bor.csproj", "{A5948E4C-54A6-49B2-AD93-A2C768CF3B7B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BorTest", "BorTest\BorTest.csproj", "{82DAD3CF-7041-4300-B987-4CF0FD1C3E52}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A5948E4C-54A6-49B2-AD93-A2C768CF3B7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5948E4C-54A6-49B2-AD93-A2C768CF3B7B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5948E4C-54A6-49B2-AD93-A2C768CF3B7B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5948E4C-54A6-49B2-AD93-A2C768CF3B7B}.Release|Any CPU.Build.0 = Release|Any CPU + {82DAD3CF-7041-4300-B987-4CF0FD1C3E52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82DAD3CF-7041-4300-B987-4CF0FD1C3E52}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82DAD3CF-7041-4300-B987-4CF0FD1C3E52}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82DAD3CF-7041-4300-B987-4CF0FD1C3E52}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EEBE94E6-045F-4E20-8C45-A352B7E2EEA7} + EndGlobalSection +EndGlobal diff --git a/Homework2/Bor/Bor/Bor.csproj b/Homework2/Bor/Bor/Bor.csproj new file mode 100644 index 0000000..644c780 --- /dev/null +++ b/Homework2/Bor/Bor/Bor.csproj @@ -0,0 +1,10 @@ + + + + Library + net6.0 + enable + enable + + + diff --git a/Homework2/Bor/Bor/Trie.cs b/Homework2/Bor/Bor/Trie.cs new file mode 100644 index 0000000..5bf2180 --- /dev/null +++ b/Homework2/Bor/Bor/Trie.cs @@ -0,0 +1,180 @@ +namespace Trie; + +/// +/// A class representing the Trie +/// +public class Trie +{ + /// + /// A class representing the Trie node + /// + private class Node + { + /// + /// Dictionary for storing characters for each node + /// + public Dictionary Nodes = new(); + + /// + /// Node property - whether it is the end of a string + /// + public bool IsTerminal { get; set; } + } + + /// + /// Bor root + /// + private readonly Node root = new(); + + /// + /// Bor size + /// + public int Size { get; private set; } + + /// + /// Function for adding a string + /// + /// Element to add + /// Was there an element string before calling Add + public bool Add(string element) + { + if (Contains(element)) + { + return false; + } + + Node node = root; + for (int i = 0; i < element.Length; i++) + { + if (node != null && !node.Nodes.ContainsKey(element[i])) + { + node.Nodes.Add(element[i], new Node()); + Size++; + } + + if (node != null && node.Nodes.ContainsKey(element[i])) + { + node = node.Nodes[element[i]]; + } + } + + if (node != null) + { + node.IsTerminal = true; + } + + return true; + } + + /// + /// Is the string contained in the Trie + /// + /// Element to search + /// True if there is such a string. False if there is no such string + public bool Contains(string element) + { + Node? node = root; + for (int i = 0; i < element.Length; i++) + { + if (node.Nodes.TryGetValue(element[i], out node)) + { + continue; + } + + return false; + } + + return node.IsTerminal; + } + + /// + /// Function for finding the number of strings starting with a prefix + /// + /// The number of strings starting with the prefix + public int HowManyStartWithPrefix(string prefix) + { + Node? node = root; + for (int i = 0; i < prefix.Length; i++) + { + if (node != null) + { + if (node.Nodes.TryGetValue(prefix[i], out node)) + { + continue; + } + } + + return 0; + } + + if (node == null) + { + return 0; + } + + return node.IsTerminal ? 1 + node.Nodes.Count : node.Nodes.Count; + } + + /// + /// Function for clearing dictionaries + /// + /// + static private void ClearDictionaryAndNode(Node node) + { + node.Nodes.Clear(); + } + + /// + /// Function for deleting string from Trie + /// + /// Element to delete + /// as there an element string before calling Remove + public bool Remove(string element) + { + if (!Contains(element)) + { + return false; + } + + int index = 0; + Node node = root; + Node? parent = null; + for (int i = 0; i < element.Length; i++) + { + if (node != null) + { + node = node.Nodes[element[i]]; + + if (node.Nodes.Count == 0 && i == element.Length - 1) + { + if (parent != null) + { + ClearDictionaryAndNode(parent); + Size -= i - index; + return true; + } + else + { + ClearDictionaryAndNode(root); + Size = 0; + return true; + } + } + + if (node.Nodes.Count != 0 && i == element.Length - 1) + { + node.IsTerminal = false; + return true; + } + } + + if (node != null && node.IsTerminal) + { + index = i; + parent = node; + } + } + + return true; + } +} diff --git a/Homework2/Bor/Bor/Trie.csproj b/Homework2/Bor/Bor/Trie.csproj new file mode 100644 index 0000000..644c780 --- /dev/null +++ b/Homework2/Bor/Bor/Trie.csproj @@ -0,0 +1,10 @@ + + + + Library + net6.0 + enable + enable + + + diff --git a/Homework2/Bor/BorTest/BorTest.csproj b/Homework2/Bor/BorTest/BorTest.csproj new file mode 100644 index 0000000..534cb0f --- /dev/null +++ b/Homework2/Bor/BorTest/BorTest.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + + diff --git a/Homework2/Bor/BorTest/TrieTest.cs b/Homework2/Bor/BorTest/TrieTest.cs new file mode 100644 index 0000000..c27b471 --- /dev/null +++ b/Homework2/Bor/BorTest/TrieTest.cs @@ -0,0 +1,97 @@ +namespace TrieTest; + +using NUnit.Framework; +using Trie; + +public class TrieTest +{ + private Trie trie = new(); + + [SetUp] + public void Setup() + { + trie = new(); + } + + [Test] + public void ShouldExpectedFalseWhenRemoveFromEmptyBor() + { + Assert.IsFalse(trie.Remove("hello")); + } + + [Test] + public void ShouldExpectedFalseWhenAddExistingString() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsFalse(trie.Add("hello")); + } + + [Test] + public void ShouldExpectedFalseWhenContainsForNonExistingString() + { + Assert.IsFalse(trie.Contains("hello")); + } + + [Test] + public void ShouldExpectedTrueWhenContainsForExistingString() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsTrue(trie.Contains("hello")); + } + + [Test] + public void ShouldExpectedFalseWhenRemoveForRemovedString() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsTrue(trie.Remove("hello")); + Assert.IsFalse(trie.Remove("hello")); + } + + [Test] + public void ShouldExpectedFalseWhenContainsForRemovedString() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsTrue(trie.Remove("hello")); + Assert.IsFalse(trie.Contains("hello")); + } + + [Test] + public void ShouldExpected5WhenSizeForBorContains5Node() + { + Assert.IsTrue(trie.Add("hello")); + Assert.AreEqual(5, trie.Size); + } + + [Test] + public void ShouldBorSizeNotChangeWhenAddExistingSubstring() + { + Assert.IsTrue(trie.Add("hello")); + int size = trie.Size; + Assert.IsTrue(trie.Add("hell")); + Assert.AreEqual(size, trie.Size); + } + + [Test] + public void ShouldBorSizeEqual8WhenAddStringLength3WithNonExistingFirstSymbolForBorContains5Node() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsTrue(trie.Add("bye")); + Assert.AreEqual(8, trie.Size); + } + + [Test] + public void ShouldExpected2WhenHowManyStartWithPrefixForBorContains2StringWhichStartWithSamePrefix() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsTrue(trie.Add("hel")); + Assert.AreEqual(2, trie.HowManyStartWithPrefix("hel")); + } + + [Test] + public void ShouldExpected0WhenHowManyStartWithPrefixForNonExistingPrefix() + { + Assert.IsTrue(trie.Add("hello")); + Assert.IsTrue(trie.Add("bye")); + Assert.AreEqual(0, trie.HowManyStartWithPrefix("leee")); + } +} \ No newline at end of file