From 3e33fb1b7353553b86288f85d13be81a724854ea Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Mon, 28 Feb 2022 19:03:08 +0300 Subject: [PATCH 1/7] Writing basic stack functions, writing tests --- Stack/Stack.sln | 31 ++++++++++ Stack/Stack/Solution.cs | 9 +++ Stack/Stack/Stack.csproj | 10 ++++ Stack/Stack/StackOnArray.cs | 59 ++++++++++++++++++ Stack/Stack/StackOnLists.cs | 70 ++++++++++++++++++++++ Stack/TestStackOnArray/TestStack.csproj | 21 +++++++ Stack/TestStackOnArray/TestStackOnArray.cs | 55 +++++++++++++++++ Stack/TestStackOnArray/TestStackOnLists.cs | 55 +++++++++++++++++ 8 files changed, 310 insertions(+) create mode 100644 Stack/Stack.sln create mode 100644 Stack/Stack/Solution.cs create mode 100644 Stack/Stack/Stack.csproj create mode 100644 Stack/Stack/StackOnArray.cs create mode 100644 Stack/Stack/StackOnLists.cs create mode 100644 Stack/TestStackOnArray/TestStack.csproj create mode 100644 Stack/TestStackOnArray/TestStackOnArray.cs create mode 100644 Stack/TestStackOnArray/TestStackOnLists.cs diff --git a/Stack/Stack.sln b/Stack/Stack.sln new file mode 100644 index 0000000..69b9eb5 --- /dev/null +++ b/Stack/Stack.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}") = "Stack", "Stack\Stack.csproj", "{70DCF9E2-593E-4AB9-A056-F0C172DA3419}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestStack", "TestStackOnArray\TestStack.csproj", "{60E6252B-6D54-47D9-B466-95927AFE6E5D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Release|Any CPU.Build.0 = Release|Any CPU + {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F2B1E14B-C1F7-471E-987B-DCCA99BA603E} + EndGlobalSection +EndGlobal diff --git a/Stack/Stack/Solution.cs b/Stack/Stack/Solution.cs new file mode 100644 index 0000000..01b00fc --- /dev/null +++ b/Stack/Stack/Solution.cs @@ -0,0 +1,9 @@ +namespace Stack; + +public class Solution +{ + static void Main() + { + return; + } +} diff --git a/Stack/Stack/Stack.csproj b/Stack/Stack/Stack.csproj new file mode 100644 index 0000000..74abf5c --- /dev/null +++ b/Stack/Stack/Stack.csproj @@ -0,0 +1,10 @@ + + + + Exe + net6.0 + enable + enable + + + diff --git a/Stack/Stack/StackOnArray.cs b/Stack/Stack/StackOnArray.cs new file mode 100644 index 0000000..7153ef2 --- /dev/null +++ b/Stack/Stack/StackOnArray.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; + +namespace Stack; + +public class StackOnArray +{ + private T[] values; + private int numberOfElements; + + public StackOnArray() + { + values = new T[20]; + } + + public bool IsEmpty() + { + return numberOfElements == 0; + } + + public void Push(T value) + { + if(numberOfElements == values.Length) + { + Array.Resize(ref values, values.Length + 20); + } + numberOfElements++; + values[numberOfElements - 1] = value; + } + + public T Pop() + { + if(numberOfElements == 0) + { + throw new InvalidOperationException("Stack is empty"); + } + T topOfSTack = values[numberOfElements - 1]; + numberOfElements--; + return topOfSTack; + } + + public T ReturnTopOfTheStack() + { + return values[numberOfElements - 1]; + } + + public int ReturnNumberOfElements() + { + return numberOfElements; + } + + public void PrintStack() + { + for (int i = 0; i < numberOfElements; i++) + { + Console.Write($"{values[i]} "); + } + } +} \ No newline at end of file diff --git a/Stack/Stack/StackOnLists.cs b/Stack/Stack/StackOnLists.cs new file mode 100644 index 0000000..5e505f5 --- /dev/null +++ b/Stack/Stack/StackOnLists.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; + +namespace Stack; + +public class StackOnLists +{ + private StackOnLists? head; + private StackOnLists? next; + private T? value; + private int numberOfElements; + + public bool IsEmpty() + { + return numberOfElements == 0; + } + + public void Push(T value) + { + numberOfElements++; + StackOnLists newHead = new StackOnLists(); + newHead.next = head; + head = newHead; + head.value = value; + } + + public T Pop() + { + if (head == null || head.value == null) + { + throw new InvalidOperationException("Stack is empty"); + } + var topOfSTack = head; + head = head.next; + numberOfElements--; + return topOfSTack.value; + } + + public int ReturnNumberOfElements() + { + return numberOfElements; + } + + public T ReturnTopOfTheStack() + { + if (head == null || head.value == null) + { + throw new InvalidOperationException("Stack is empty"); + } + return head.value; + } + + public void PrintStack() + { + if (head == null) + { + throw new InvalidOperationException("Stack is empty"); + } + StackOnLists copyHead = head; + while (copyHead != null && copyHead.next != null) + { + Console.Write($"{copyHead.value} "); + copyHead = copyHead.next; + } + if (copyHead != null && copyHead.value != null) + { + Console.Write($"{copyHead.value} "); + } + } +} diff --git a/Stack/TestStackOnArray/TestStack.csproj b/Stack/TestStackOnArray/TestStack.csproj new file mode 100644 index 0000000..48ef2ac --- /dev/null +++ b/Stack/TestStackOnArray/TestStack.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + + diff --git a/Stack/TestStackOnArray/TestStackOnArray.cs b/Stack/TestStackOnArray/TestStackOnArray.cs new file mode 100644 index 0000000..73e9391 --- /dev/null +++ b/Stack/TestStackOnArray/TestStackOnArray.cs @@ -0,0 +1,55 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Stack; + +namespace TestStack; + +[TestClass] +public class TestStackOnArray +{ + [TestMethod] + public void TestPush() + { + StackOnArray stackOnArray = new StackOnArray(); + stackOnArray.Push(1); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 1); + stackOnArray.Push(2); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 2); + stackOnArray.Push(4); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 4); + stackOnArray.Push(5); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 5); + } + + [TestMethod] + public void TestPop() + { + StackOnArray stackOnArray = new StackOnArray(); + stackOnArray.Push("first"); + stackOnArray.Push("second"); + stackOnArray.Push("hello"); + stackOnArray.Push("kek"); + stackOnArray.Pop(); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), "hello"); + stackOnArray.Pop(); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), "second"); + stackOnArray.Pop(); + Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), "first"); + } + + [TestMethod] + public void TestReturnNumberOfElements() + { + StackOnArray stackOnArray = new StackOnArray(); + stackOnArray.Push("first"); + stackOnArray.Push("second"); + stackOnArray.Push("hello"); + stackOnArray.Push("kek"); + Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 4); + stackOnArray.Pop(); + Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 3); + stackOnArray.Pop(); + Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 2); + stackOnArray.Pop(); + Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 1); + } +} diff --git a/Stack/TestStackOnArray/TestStackOnLists.cs b/Stack/TestStackOnArray/TestStackOnLists.cs new file mode 100644 index 0000000..86f1b9f --- /dev/null +++ b/Stack/TestStackOnArray/TestStackOnLists.cs @@ -0,0 +1,55 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Stack; + +namespace TestStack; + +[TestClass] +public class TestStackOnLists +{ + [TestMethod] + public void TestPush() + { + StackOnLists stackOnLists = new StackOnLists(); + stackOnLists.Push(1); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 1); + stackOnLists.Push(2); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 2); + stackOnLists.Push(4); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 4); + stackOnLists.Push(5); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 5); + } + + [TestMethod] + public void TestPop() + { + StackOnLists stackOnLists = new StackOnLists(); + stackOnLists.Push("first"); + stackOnLists.Push("second"); + stackOnLists.Push("hello"); + stackOnLists.Push("kek"); + stackOnLists.Pop(); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), "hello"); + stackOnLists.Pop(); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), "second"); + stackOnLists.Pop(); + Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), "first"); + } + + [TestMethod] + public void TestReturnNumberOfElements() + { + StackOnLists stackOnLists = new StackOnLists(); + stackOnLists.Push("first"); + stackOnLists.Push("second"); + stackOnLists.Push("hello"); + stackOnLists.Push("kek"); + Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 4); + stackOnLists.Pop(); + Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 3); + stackOnLists.Pop(); + Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 2); + stackOnLists.Pop(); + Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 1); + } +} From 3ec3df78d2ce0a7e1daa89f11169747f5ba39209 Mon Sep 17 00:00:00 2001 From: Roman Date: Sat, 14 May 2022 20:27:34 +0300 Subject: [PATCH 2/7] Creating the Bor class, writing the required functions and tests for them --- Homework3/LZW/LZW.sln | 31 ++++ Homework3/LZW/LZW/Bor.cs | 81 +++++++++ Homework3/LZW/LZW/LZW.cs | 158 ++++++++++++++++++ .../LZW/LZW/LZW.csproj | 0 Homework3/LZW/LZW/Solution.cs | 29 ++++ Homework3/LZW/LZWTest/BorTest.cs | 62 +++++++ Homework3/LZW/LZWTest/LZWTest.cs | 24 +++ Homework3/LZW/LZWTest/Test.txt | 1 + .../LZW/LZWTest/Tests.csproj | 6 +- Stack/Stack.sln | 31 ---- Stack/Stack/Solution.cs | 9 - Stack/Stack/StackOnArray.cs | 59 ------- Stack/Stack/StackOnLists.cs | 70 -------- Stack/TestStackOnArray/TestStackOnArray.cs | 55 ------ Stack/TestStackOnArray/TestStackOnLists.cs | 55 ------ 15 files changed, 389 insertions(+), 282 deletions(-) create mode 100644 Homework3/LZW/LZW.sln create mode 100644 Homework3/LZW/LZW/Bor.cs create mode 100644 Homework3/LZW/LZW/LZW.cs rename Stack/Stack/Stack.csproj => Homework3/LZW/LZW/LZW.csproj (100%) create mode 100644 Homework3/LZW/LZW/Solution.cs create mode 100644 Homework3/LZW/LZWTest/BorTest.cs create mode 100644 Homework3/LZW/LZWTest/LZWTest.cs create mode 100644 Homework3/LZW/LZWTest/Test.txt rename Stack/TestStackOnArray/TestStack.csproj => Homework3/LZW/LZWTest/Tests.csproj (66%) delete mode 100644 Stack/Stack.sln delete mode 100644 Stack/Stack/Solution.cs delete mode 100644 Stack/Stack/StackOnArray.cs delete mode 100644 Stack/Stack/StackOnLists.cs delete mode 100644 Stack/TestStackOnArray/TestStackOnArray.cs delete mode 100644 Stack/TestStackOnArray/TestStackOnLists.cs diff --git a/Homework3/LZW/LZW.sln b/Homework3/LZW/LZW.sln new file mode 100644 index 0000000..5162330 --- /dev/null +++ b/Homework3/LZW/LZW.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}") = "LZW", "LZW\LZW.csproj", "{5DAEADDF-7108-4028-90E1-5C05C2034360}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "LZWTest\Tests.csproj", "{455E760B-8592-4A15-BB37-A79DAE435B4C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5DAEADDF-7108-4028-90E1-5C05C2034360}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DAEADDF-7108-4028-90E1-5C05C2034360}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DAEADDF-7108-4028-90E1-5C05C2034360}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DAEADDF-7108-4028-90E1-5C05C2034360}.Release|Any CPU.Build.0 = Release|Any CPU + {455E760B-8592-4A15-BB37-A79DAE435B4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {455E760B-8592-4A15-BB37-A79DAE435B4C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {455E760B-8592-4A15-BB37-A79DAE435B4C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {455E760B-8592-4A15-BB37-A79DAE435B4C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7673691E-822C-4405-8F11-DE9C2BCBAE62} + EndGlobalSection +EndGlobal diff --git a/Homework3/LZW/LZW/Bor.cs b/Homework3/LZW/LZW/Bor.cs new file mode 100644 index 0000000..9ae1cef --- /dev/null +++ b/Homework3/LZW/LZW/Bor.cs @@ -0,0 +1,81 @@ +namespace Bor; + +/// +/// A class representing the bor data structure +/// +public class Bor +{ + /// + /// // A class representing the bor data structure + /// + private class Node + { + // Dictionary for storing characters for each node + public Dictionary Nodes = new(); + + // Code for each node + public int Code { get; set;} + } + + // Bor root + private readonly Node root = new(); + + // Bor size + public int Size { get; private set; } + + private Node currentNode; + + public int GetCode() + { + return currentNode.Code; + } + + public Bor() + { + root.Code = -1; + + // Initialize the bor with numbers from 0 to 256 + for (int i = 0; i < 256; i++) + { + Node node = new(); + root.Nodes.Add((byte)i, node); + node.Code = Size; + Size++; + } + + // The current node is the root + currentNode = root; + } + + /// + /// Function to add a byte + /// + /// byte to add + public void Add(byte byteToAdd) + { + Node node = new(); + currentNode?.Nodes.Add(byteToAdd, node); + currentNode = root; + node.Code = Size; + Size++; + } + + /// + /// Is the byte contained in Current Node + /// + /// Element to search + /// True if there is such a byte. False if there is no such byte + public bool Contains(byte byteToSearch) => currentNode.Nodes.ContainsKey(byteToSearch); + + /// + /// Function for moving to another node + /// + /// the byte to be moved to + public void MoveIntoDesiredNode(byte byteToBeMovedTo) => currentNode = currentNode.Nodes[byteToBeMovedTo]; + + /// + /// Function for moving to root + /// + public void MovedToRoot() => currentNode = root; +} + diff --git a/Homework3/LZW/LZW/LZW.cs b/Homework3/LZW/LZW/LZW.cs new file mode 100644 index 0000000..ae48b86 --- /dev/null +++ b/Homework3/LZW/LZW/LZW.cs @@ -0,0 +1,158 @@ +namespace LZW; + +using System; +using System.IO; +using Bor; + +/// +/// A class representing the LZW algorithm +/// +public class LZW +{ + //A function for determining the number of bytes needed to store a number + private static int NumberOfBytes(int number) + { + if (number < 256) + { + return 1; + } + if (number < 65536) + { + return 2; + } + if (number < 16777216) + { + return 3; + } + return 4; + } + + /// + /// Function for file compression + /// + /// The path to the file to compress + public static void CompressFile(string pathToFileToCompress) + { + + string fileName = Path.GetFileNameWithoutExtension(pathToFileToCompress); + fileName = $"{pathToFileToCompress}..//..//{fileName}.zipped"; + + // Name of the compressed file + using FileStream fs = new(fileName, FileMode.Create); + + // Reading all bytes from a file + var stringToConvert = File.ReadAllBytes(pathToFileToCompress); + + // Creating bor + Bor bor = new(); + + for (int i = 0; i < stringToConvert.Length; i++) + { + // If the byte is contained in the bor + if (bor.Contains(stringToConvert[i])) + { + // Moving on to the next byte + bor.MoveIntoDesiredNode(stringToConvert[i]); + } + // Otherwise, we add it to the bor + else + { + // Taking the idex from the parent vertex and encode it + var bytes = BitConverter.GetBytes(bor.GetCode()); + + // Cut off the extra bytes + // The required number of bytes is selected according to the size of the bor + // Since among the numbers that need to be encoded there may be a bor size (index of the maximum vertex), + // the number of bytes to store depends on the size of the bor. + // Even a number requires fewer bytes, + // it is written in a large number of bytes so that it can be decoded later. + Array.Resize(ref bytes, NumberOfBytes(bor.Size - 1)); + bor.Add(stringToConvert[i]); + fs.Write(bytes); + + // Going back to the last vertex + i--; + } + } + + // The last bytes that are already in the dictionary and that are not written in the loop + var newbytes = BitConverter.GetBytes(bor.GetCode()); + Array.Resize(ref newbytes, NumberOfBytes(bor.Size)); + fs.Write(newbytes); + } + + public static void DecompressFile(string pathToFile) + { + + string fileName = Path.GetFileNameWithoutExtension(pathToFile); + fileName = $"{pathToFile}..//..//{fileName}"; + + // Create file + using FileStream fs = new(fileName, FileMode.Create); + + // Reading all bytes from a file + byte[] stringToConvert = File.ReadAllBytes(pathToFile); + + // Dictionary for decoding + var dictionary = new Dictionary(); + + for (int i = 0; i < 256; i++) + { + int index = 0; + var byteArray = BitConverter.GetBytes(i); + for (int l = 0; l < byteArray.Length; l++) + { + if (l == 1) + { + index = l; + } + } + dictionary.Add(i, byteArray[0..index]); + } + + int rightBorder = 0; + int leftBorder = 0; + bool flag = false; + + while (leftBorder < stringToConvert.Length) + { + // The right border of the current subarray + rightBorder = leftBorder + NumberOfBytes(dictionary.Count - 1) - 1; + + // If the right border has gone beyond the edge, then we will make it the last byte + rightBorder = rightBorder > stringToConvert.Length - 1 ? stringToConvert.Length - 1 : rightBorder; + + + if (leftBorder > stringToConvert.Length - 1) + { + break; + } + + // Converting bytes to int + var bytes = new byte[4]; + Array.Copy(stringToConvert, leftBorder, bytes, 0, NumberOfBytes(dictionary.Count - 1)); + leftBorder = rightBorder + 1; + int answer = BitConverter.ToInt32(bytes); + + // If it is the first number + if (!flag) + { + flag = true; + } + + // Otherwise, we concatenate the last element with the first byte of the current one + else + { + var newArray = new byte[dictionary[dictionary.Count - 1].Length + 1]; + Array.Copy(dictionary[dictionary.Count - 1], newArray, dictionary[dictionary.Count - 1].Length); + newArray[newArray.Length - 1] = dictionary[answer][0]; + // Changing the value in the dictionary to the value we need + dictionary[dictionary.Count - 1] = newArray; + } + + // Adding a new element to the dictionary + dictionary.Add(dictionary.Count, dictionary[answer]); + fs.Write(dictionary[answer]); + } + } +} \ No newline at end of file diff --git a/Stack/Stack/Stack.csproj b/Homework3/LZW/LZW/LZW.csproj similarity index 100% rename from Stack/Stack/Stack.csproj rename to Homework3/LZW/LZW/LZW.csproj diff --git a/Homework3/LZW/LZW/Solution.cs b/Homework3/LZW/LZW/Solution.cs new file mode 100644 index 0000000..b82d2bb --- /dev/null +++ b/Homework3/LZW/LZW/Solution.cs @@ -0,0 +1,29 @@ +namespace LZW; + +public class Solution +{ + static void Main(string[] args) + { + if (args.Length != 2) + { + throw new FileNotFoundException(); + } + string pathToFile = args[0]; + if (args[1] == "-c") + { + var file = new FileInfo(pathToFile); + long uncompressedFileSize = file.Length; + string fileName = Path.GetFileNameWithoutExtension(pathToFile); + fileName = $"{pathToFile}..\\..\\{fileName}.zipped"; + LZW.CompressFile(pathToFile); + file = new FileInfo(fileName); + long compressedFileSize = file.Length; + Console.WriteLine((float)(uncompressedFileSize) / (float)compressedFileSize); + return; + } + if (args[1] == "-u") + { + LZW.DecompressFile(pathToFile); + } + } +} diff --git a/Homework3/LZW/LZWTest/BorTest.cs b/Homework3/LZW/LZWTest/BorTest.cs new file mode 100644 index 0000000..639e112 --- /dev/null +++ b/Homework3/LZW/LZWTest/BorTest.cs @@ -0,0 +1,62 @@ +namespace Test; + +using NUnit.Framework; +using Bor; +using System; + +public class BorTest +{ + Bor bor = new(); + + [SetUp] + public void Setup() + { + bor = new(); + } + + [Test] + public void ShouldExpectedTrueWhenContainsForBorWhereinCurrentNodeContainsThisNode() + { + bor.MoveIntoDesiredNode((byte)123); + bor.Add((byte)143); + bor.MoveIntoDesiredNode((byte)123); + Assert.IsTrue(bor.Contains((byte)143)); + } + + [Test] + public void ShouldExpectedFalseWhenContainsForBorWhereinCurrentNodeContainsThisNode() + { + bor.MoveIntoDesiredNode((byte)123); + Assert.IsFalse(bor.Contains((byte)143)); + } + + [Test] + public void ShouldBorSizeIncreaseByOneWhenAdd() + { + bor.MoveIntoDesiredNode((byte)123); + var size = bor.Size; + bor.Add((byte)12); + Assert.AreEqual(size + 1, bor.Size); + } + + [Test] + public void ShouldWhenAddExistingNode() + { + Assert.Throws(() => bor.Add((byte)12)); + } + + [Test] + public void ShouldExpectedCurrentRootEqualRootWhenMoveToRoot() + { + bor.MoveIntoDesiredNode((byte)123); + bor.MovedToRoot(); + Assert.AreEqual(-1, bor.GetCode()); + } + + [Test] + public void ShouldExpectedCurrentRootWhenMoveIntoDesiredNode() + { + bor.MoveIntoDesiredNode((byte)123); + Assert.AreEqual(123, bor.GetCode()); + } +} \ No newline at end of file diff --git a/Homework3/LZW/LZWTest/LZWTest.cs b/Homework3/LZW/LZWTest/LZWTest.cs new file mode 100644 index 0000000..a1353ba --- /dev/null +++ b/Homework3/LZW/LZWTest/LZWTest.cs @@ -0,0 +1,24 @@ +namespace Test; + +using NUnit.Framework; +using System.IO; + +public class LZWTests +{ + [SetUp] + public void Setup() + { + } + + [Test] + public void ShouldExpectedStringAreEqualWhenLZWForFile() + { + string filename = "..//..//..//Test.txt"; + LZW.LZW.CompressFile(filename); + string newFilename = "..//..//..//Test.zipped"; + LZW.LZW.DecompressFile(newFilename); + var firstString = File.ReadAllBytes(filename); + var secondString = File.ReadAllBytes("..//..//..//Test"); + Assert.AreEqual(firstString, secondString); + } +} \ No newline at end of file diff --git a/Homework3/LZW/LZWTest/Test.txt b/Homework3/LZW/LZWTest/Test.txt new file mode 100644 index 0000000..9374c1a --- /dev/null +++ b/Homework3/LZW/LZWTest/Test.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. Nunc egestas, augue at pellentesque laoreet, felis eros vehicula leo, at malesuada velit leo quis pede. Donec interdum, metus et hendrerit aliquet, dolor diam sagittis ligula, eget egestas libero turpis vel mi. Nunc nulla. Fusce risus nisl, viverra et, tempor et, pretium in, sapien. Donec venenatis vulputate lorem. Morbi nec metus. Phasellus blandit leo ut odio. Maecenas ullamcorper, dui et placerat feugiat, eros pede varius nisi, condimentum viverra felis nunc et lorem. Sed magna purus, fermentum eu, tincidunt eu, varius ut, felis. In auctor lobortis lacus. Quisque libero metus, condimentum nec, tempor a, commodo mollis, magna. Vestibulum ullamcorper mauris at ligula. Fusce fermentum. Nullam cursus lacinia erat. Praesent blandit laoreet nibh. Fusce convallis metus id felis luctus adipiscing. Pellentesque egestas, neque sit amet convallis pulvinar, justo nulla eleifend augue, ac auctor orci leo non est. Quisque id mi. Ut tincidunt tincidunt erat. Etiam feugiat lorem non metus. Vestibulum dapibus nunc ac augue. Curabitur vestibulum aliquam leo. Praesent egestas neque eu enim. In hac habitasse platea dictumst. Fusce a quam. Etiam ut purus mattis mauris sodales aliquam. Curabitur nisi. Quisque malesuada placerat nisl. Nam ipsum risus, rutrum vitae, vestibulum eu, molestie vel, lacus. Sed augue ipsum, egestas nec, vestibulum et, malesuada adipiscing, dui. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Mauris sollicitudin fermentum libero. Praesent nonummy mi in odio. Nunc interdum lacus sit amet orci. Vestibulum rutrum, mi nec elementum vehicula, eros quam gravida nisl, id fringilla neque ante vel mi. Morbi mollis tellus ac sapien. Phasellus volutpat, metus eget egestas mollis, lacus lacus blandit dui, id egestas quam mauris ut lacus. Fusce vel dui. Sed in libero ut nibh placerat accumsan. Proin faucibus arcu quis ante. In consectetuer turpis ut velit. Nulla sit amet est. Praesent metus tellus, elementum eu, semper a, adipiscing nec, purus. Cras risus ipsum, faucibus ut, ullamcorper id, varius ac, leo. Suspendisse feugiat. Suspendisse enim turpis, dictum sed, iaculis a, condimentum nec, nisi. Praesent nec nisl a purus blandit viverra. Praesent ac massa at ligula laoreet iaculis. Nulla neque dolor, sagittis eget, iaculis quis, molestie non, velit. Mauris turpis nunc, blandit et, volutpat molestie, porta ut, ligula. Fusce pharetra convallis urna. Quisque ut nisi. Donec mi odio, faucibus at, scelerisque quis, convallis in, nisi. Suspendisse non nisl sit amet velit hendrerit rutrum. Ut leo. Ut a nisl id ante tempus hendrerit. Proin pretium, leo ac pellentesque mollis, felis nunc ultrices eros, sed gravida augue augue mollis justo. Suspendisse eu ligula. Nulla facilisi. Donec id justo. Praesent porttitor, nulla vitae posuere iaculis, arcu nisl dignissim dolor, a pretium mi sem ut ipsum. Curabitur suscipit suscipit tellus. Praesent vestibulum dapibus nibh. Etiam iaculis nunc ac metus. Ut id nisl quis enim dignissim sagittis. Etiam sollicitudin, ipsum eu pulvinar rutrum, tellus ipsum laoreet sapien, quis venenatis ante odio sit amet eros. Proin magna. Duis vel nibh at velit scelerisque suscipit. Curabitur turpis. Vestibulum suscipit nulla quis orci. Fusce ac felis sit amet ligula pharetra condimentum. Maecenas egestas arcu quis ligula mattis placerat. Duis lobortis massa imperdiet quam. Suspendisse potenti. Pellentesque commodo eros a enim. Vestibulum turpis sem, aliquet eget, lobortis pellentesque, rutrum eu, nisl. Sed libero. Aliquam erat volutpat. Etiam vitae tortor. Morbi vestibulum volutpat enim. Aliquam eu nunc. Nunc sed turpis. Sed mollis, eros et ultrices tempus, mauris ipsum aliquam libero, non adipiscing dolor urna a orci. Nulla porta dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Pellentesque dapibus hendrerit tortor. Praesent egestas tristique nibh. Sed a libero. Cras varius. Donec vitae orci sed dolor rutrum auctor. Fusce egestas elit eget lorem. Suspendisse nisl elit, rhoncus eget, elementum ac, condimentum eget, diam. Nam at tortor in tellus interdum sagittis. Aliquam lobortis. Donec orci lectus, aliquam ut, faucibus non, euismod id, nulla. Curabitur blandit mollis lacus. Nam adipiscing. Vestibulum eu odio. Vivamus laoreet. Nullam tincidunt adipiscing enim. Phasellus tempus. Proin viverra, ligula sit amet ultrices semper, ligula arcu tristique sapien, a accumsan nisi mauris ac eros. Fusce neque. Suspendisse faucibus, nunc et pellentesque egestas, lacus ante convallis tellus, vitae iaculis lacus elit id tortor. Vivamus aliquet elit ac nisl. Fusce fermentum odio nec arcu. Vivamus euismod mauris. In ut quam vitae odio lacinia tincidunt. Praesent ut ligula non mi varius sagittis. Cras sagittis. Praesent ac sem eget est egestas volutpat. Vivamus consectetuer hendrerit lacus. Cras non dolor. Vivamus in erat ut urna cursus vestibulum. Fusce commodo aliquam arcu. Nam commodo suscipit quam. Quisque id odio. Praesent venenatis metus at tortor pulvinar varius.Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut eros et nisl sagittis vestibulum. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Sed lectus. Donec mollis hendrerit risus. Phasellus nec sem in justo pellentesque facilisis. Etiam imperdiet imperdiet orci. Nunc nec neque. Phasellus leo dolor, tempus non, auctor et, hendrerit quis, nisi. Curabitur ligula sapien, tincidunt non, euismod vitae, posuere imperdiet, leo. Maecenas malesuada. Praesent congue erat at massa. Sed cursus turpis vitae tortor. Donec posuere vulputate arcu. Phasellus accumsan cursus velit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed aliquam, nisi quis porttitor congue, elit erat euismod orci, ac placerat dolor lectus quis orci. Phasellus consectetuer vestibulum elit. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc. Vestibulum fringilla pede sit amet augue. In turpis. Pellentesque posuere. Praesent turpis. Aenean posuere, tortor sed cursus feugiat, nunc augue blandit nunc, eu sollicitudin urna dolor sagittis lacus. Donec elit libero, sodales nec, volutpat a, suscipit non, turpis. Nullam sagittis. Suspendisse pulvinar, augue ac venenatis condimentum, sem libero volutpat nibh, nec pellentesque velit pede quis nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Fusce id purus. Ut varius tincidunt libero. Phasellus dolor. Maecenas vestibulum mollis diam. Pellentesque ut neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In dui magna, posuere eget, vestibulum et, tempor auctor, justo. In ac felis quis tortor malesuada pretium. Pellentesque auctor neque nec urna. Proin sapien ipsum, porta a, auctor quis, euismod ut, mi. Aenean viverra rhoncus pede. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut non enim eleifend felis pretium feugiat. Vivamus quis mi. Phasellus a est. Phasellus magna. In hac habitasse platea dictumst. Curabitur at lacus ac velit ornare lobortis. Curabitur a felis in nunc fringilla tristique. Morbi mattis ullamcorper velit. Phasellus gravida semper nisi. Nullam vel sem. Pellentesque libero tortor, tincidunt et, tincidunt eget, semper nec, quam. Sed hendrerit. Morbi ac felis. \ No newline at end of file diff --git a/Stack/TestStackOnArray/TestStack.csproj b/Homework3/LZW/LZWTest/Tests.csproj similarity index 66% rename from Stack/TestStackOnArray/TestStack.csproj rename to Homework3/LZW/LZWTest/Tests.csproj index 48ef2ac..5cfb103 100644 --- a/Stack/TestStackOnArray/TestStack.csproj +++ b/Homework3/LZW/LZWTest/Tests.csproj @@ -9,13 +9,13 @@ - - + + - + diff --git a/Stack/Stack.sln b/Stack/Stack.sln deleted file mode 100644 index 69b9eb5..0000000 --- a/Stack/Stack.sln +++ /dev/null @@ -1,31 +0,0 @@ - -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}") = "Stack", "Stack\Stack.csproj", "{70DCF9E2-593E-4AB9-A056-F0C172DA3419}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestStack", "TestStackOnArray\TestStack.csproj", "{60E6252B-6D54-47D9-B466-95927AFE6E5D}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Debug|Any CPU.Build.0 = Debug|Any CPU - {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Release|Any CPU.ActiveCfg = Release|Any CPU - {70DCF9E2-593E-4AB9-A056-F0C172DA3419}.Release|Any CPU.Build.0 = Release|Any CPU - {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {60E6252B-6D54-47D9-B466-95927AFE6E5D}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F2B1E14B-C1F7-471E-987B-DCCA99BA603E} - EndGlobalSection -EndGlobal diff --git a/Stack/Stack/Solution.cs b/Stack/Stack/Solution.cs deleted file mode 100644 index 01b00fc..0000000 --- a/Stack/Stack/Solution.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Stack; - -public class Solution -{ - static void Main() - { - return; - } -} diff --git a/Stack/Stack/StackOnArray.cs b/Stack/Stack/StackOnArray.cs deleted file mode 100644 index 7153ef2..0000000 --- a/Stack/Stack/StackOnArray.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Stack; - -public class StackOnArray -{ - private T[] values; - private int numberOfElements; - - public StackOnArray() - { - values = new T[20]; - } - - public bool IsEmpty() - { - return numberOfElements == 0; - } - - public void Push(T value) - { - if(numberOfElements == values.Length) - { - Array.Resize(ref values, values.Length + 20); - } - numberOfElements++; - values[numberOfElements - 1] = value; - } - - public T Pop() - { - if(numberOfElements == 0) - { - throw new InvalidOperationException("Stack is empty"); - } - T topOfSTack = values[numberOfElements - 1]; - numberOfElements--; - return topOfSTack; - } - - public T ReturnTopOfTheStack() - { - return values[numberOfElements - 1]; - } - - public int ReturnNumberOfElements() - { - return numberOfElements; - } - - public void PrintStack() - { - for (int i = 0; i < numberOfElements; i++) - { - Console.Write($"{values[i]} "); - } - } -} \ No newline at end of file diff --git a/Stack/Stack/StackOnLists.cs b/Stack/Stack/StackOnLists.cs deleted file mode 100644 index 5e505f5..0000000 --- a/Stack/Stack/StackOnLists.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Stack; - -public class StackOnLists -{ - private StackOnLists? head; - private StackOnLists? next; - private T? value; - private int numberOfElements; - - public bool IsEmpty() - { - return numberOfElements == 0; - } - - public void Push(T value) - { - numberOfElements++; - StackOnLists newHead = new StackOnLists(); - newHead.next = head; - head = newHead; - head.value = value; - } - - public T Pop() - { - if (head == null || head.value == null) - { - throw new InvalidOperationException("Stack is empty"); - } - var topOfSTack = head; - head = head.next; - numberOfElements--; - return topOfSTack.value; - } - - public int ReturnNumberOfElements() - { - return numberOfElements; - } - - public T ReturnTopOfTheStack() - { - if (head == null || head.value == null) - { - throw new InvalidOperationException("Stack is empty"); - } - return head.value; - } - - public void PrintStack() - { - if (head == null) - { - throw new InvalidOperationException("Stack is empty"); - } - StackOnLists copyHead = head; - while (copyHead != null && copyHead.next != null) - { - Console.Write($"{copyHead.value} "); - copyHead = copyHead.next; - } - if (copyHead != null && copyHead.value != null) - { - Console.Write($"{copyHead.value} "); - } - } -} diff --git a/Stack/TestStackOnArray/TestStackOnArray.cs b/Stack/TestStackOnArray/TestStackOnArray.cs deleted file mode 100644 index 73e9391..0000000 --- a/Stack/TestStackOnArray/TestStackOnArray.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Stack; - -namespace TestStack; - -[TestClass] -public class TestStackOnArray -{ - [TestMethod] - public void TestPush() - { - StackOnArray stackOnArray = new StackOnArray(); - stackOnArray.Push(1); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 1); - stackOnArray.Push(2); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 2); - stackOnArray.Push(4); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 4); - stackOnArray.Push(5); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), 5); - } - - [TestMethod] - public void TestPop() - { - StackOnArray stackOnArray = new StackOnArray(); - stackOnArray.Push("first"); - stackOnArray.Push("second"); - stackOnArray.Push("hello"); - stackOnArray.Push("kek"); - stackOnArray.Pop(); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), "hello"); - stackOnArray.Pop(); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), "second"); - stackOnArray.Pop(); - Assert.AreEqual(stackOnArray.ReturnTopOfTheStack(), "first"); - } - - [TestMethod] - public void TestReturnNumberOfElements() - { - StackOnArray stackOnArray = new StackOnArray(); - stackOnArray.Push("first"); - stackOnArray.Push("second"); - stackOnArray.Push("hello"); - stackOnArray.Push("kek"); - Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 4); - stackOnArray.Pop(); - Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 3); - stackOnArray.Pop(); - Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 2); - stackOnArray.Pop(); - Assert.AreEqual(stackOnArray.ReturnNumberOfElements(), 1); - } -} diff --git a/Stack/TestStackOnArray/TestStackOnLists.cs b/Stack/TestStackOnArray/TestStackOnLists.cs deleted file mode 100644 index 86f1b9f..0000000 --- a/Stack/TestStackOnArray/TestStackOnLists.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Stack; - -namespace TestStack; - -[TestClass] -public class TestStackOnLists -{ - [TestMethod] - public void TestPush() - { - StackOnLists stackOnLists = new StackOnLists(); - stackOnLists.Push(1); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 1); - stackOnLists.Push(2); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 2); - stackOnLists.Push(4); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 4); - stackOnLists.Push(5); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), 5); - } - - [TestMethod] - public void TestPop() - { - StackOnLists stackOnLists = new StackOnLists(); - stackOnLists.Push("first"); - stackOnLists.Push("second"); - stackOnLists.Push("hello"); - stackOnLists.Push("kek"); - stackOnLists.Pop(); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), "hello"); - stackOnLists.Pop(); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), "second"); - stackOnLists.Pop(); - Assert.AreEqual(stackOnLists.ReturnTopOfTheStack(), "first"); - } - - [TestMethod] - public void TestReturnNumberOfElements() - { - StackOnLists stackOnLists = new StackOnLists(); - stackOnLists.Push("first"); - stackOnLists.Push("second"); - stackOnLists.Push("hello"); - stackOnLists.Push("kek"); - Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 4); - stackOnLists.Pop(); - Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 3); - stackOnLists.Pop(); - Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 2); - stackOnLists.Pop(); - Assert.AreEqual(stackOnLists.ReturnNumberOfElements(), 1); - } -} From 4ad95c37c9070e402ae98a9a99d51b9dfee5e68e Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 18 May 2022 15:14:15 +0300 Subject: [PATCH 3/7] formatted --- Homework3/LZW/LZW/LZW.cs | 10 +--------- Homework3/LZW/LZW/Solution.cs | 3 +++ Homework3/LZW/LZWTest/LZWTest.cs | 5 ----- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Homework3/LZW/LZW/LZW.cs b/Homework3/LZW/LZW/LZW.cs index ae48b86..98c80c4 100644 --- a/Homework3/LZW/LZW/LZW.cs +++ b/Homework3/LZW/LZW/LZW.cs @@ -98,16 +98,8 @@ public static void DecompressFile(string pathToFile) for (int i = 0; i < 256; i++) { - int index = 0; var byteArray = BitConverter.GetBytes(i); - for (int l = 0; l < byteArray.Length; l++) - { - if (l == 1) - { - index = l; - } - } - dictionary.Add(i, byteArray[0..index]); + dictionary.Add(i, byteArray[0..1]); } int rightBorder = 0; diff --git a/Homework3/LZW/LZW/Solution.cs b/Homework3/LZW/LZW/Solution.cs index b82d2bb..f7f6ff2 100644 --- a/Homework3/LZW/LZW/Solution.cs +++ b/Homework3/LZW/LZW/Solution.cs @@ -8,7 +8,9 @@ static void Main(string[] args) { throw new FileNotFoundException(); } + string pathToFile = args[0]; + if (args[1] == "-c") { var file = new FileInfo(pathToFile); @@ -21,6 +23,7 @@ static void Main(string[] args) Console.WriteLine((float)(uncompressedFileSize) / (float)compressedFileSize); return; } + if (args[1] == "-u") { LZW.DecompressFile(pathToFile); diff --git a/Homework3/LZW/LZWTest/LZWTest.cs b/Homework3/LZW/LZWTest/LZWTest.cs index a1353ba..2cade72 100644 --- a/Homework3/LZW/LZWTest/LZWTest.cs +++ b/Homework3/LZW/LZWTest/LZWTest.cs @@ -5,11 +5,6 @@ namespace Test; public class LZWTests { - [SetUp] - public void Setup() - { - } - [Test] public void ShouldExpectedStringAreEqualWhenLZWForFile() { From 81ee53d545632400565f67fbe336445691b7cca1 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 1 Jun 2022 03:02:16 +0300 Subject: [PATCH 4/7] Added tests for binary and empty file Added comments Fixed a problem with file extension loss --- Homework3/LZW/LZW/LZW.cs | 31 ++++++++---- Homework3/LZW/LZW/Solution.cs | 15 ++++-- Homework3/LZW/LZW/{Bor.cs => Trie.cs} | 36 +++++++++----- Homework3/LZW/LZWTest/LZW.exe | Bin 0 -> 148992 bytes Homework3/LZW/LZWTest/LZWTest.cs | 46 +++++++++++++----- Homework3/LZW/LZWTest/SecondTest.txt | 0 .../LZW/LZWTest/{BorTest.cs => TrieTest.cs} | 6 +-- 7 files changed, 93 insertions(+), 41 deletions(-) rename Homework3/LZW/LZW/{Bor.cs => Trie.cs} (73%) create mode 100644 Homework3/LZW/LZWTest/LZW.exe create mode 100644 Homework3/LZW/LZWTest/SecondTest.txt rename Homework3/LZW/LZWTest/{BorTest.cs => TrieTest.cs} (96%) diff --git a/Homework3/LZW/LZW/LZW.cs b/Homework3/LZW/LZW/LZW.cs index 98c80c4..7c9ff74 100644 --- a/Homework3/LZW/LZW/LZW.cs +++ b/Homework3/LZW/LZW/LZW.cs @@ -2,14 +2,16 @@ using System; using System.IO; -using Bor; +using Trie; /// /// A class representing the LZW algorithm /// public class LZW { - //A function for determining the number of bytes needed to store a number + /// + /// A function for determining the number of bytes needed to store a number + /// private static int NumberOfBytes(int number) { if (number < 256) @@ -33,18 +35,22 @@ private static int NumberOfBytes(int number) /// The path to the file to compress public static void CompressFile(string pathToFileToCompress) { - - string fileName = Path.GetFileNameWithoutExtension(pathToFileToCompress); - fileName = $"{pathToFileToCompress}..//..//{fileName}.zipped"; - // Name of the compressed file + string fileName = $"{pathToFileToCompress}.zipped"; + + // Create file using FileStream fs = new(fileName, FileMode.Create); // Reading all bytes from a file var stringToConvert = File.ReadAllBytes(pathToFileToCompress); // Creating bor - Bor bor = new(); + Trie bor = new(); + + if (stringToConvert.Length == 0) + { + return; + } for (int i = 0; i < stringToConvert.Length; i++) { @@ -81,11 +87,17 @@ public static void CompressFile(string pathToFileToCompress) fs.Write(newbytes); } + /// + /// Function for file decompression + /// + /// The path to the file to decompress public static void DecompressFile(string pathToFile) { + var currentDirectoryName = Path.GetDirectoryName(pathToFile); + var fileName = Path.GetFileName(pathToFile); - string fileName = Path.GetFileNameWithoutExtension(pathToFile); - fileName = $"{pathToFile}..//..//{fileName}"; + // 7 = .zipped.length + fileName = $"{currentDirectoryName}//Decompressed{fileName[0..(fileName.Length - 7)]}"; // Create file using FileStream fs = new(fileName, FileMode.Create); @@ -114,7 +126,6 @@ public static void DecompressFile(string pathToFile) // If the right border has gone beyond the edge, then we will make it the last byte rightBorder = rightBorder > stringToConvert.Length - 1 ? stringToConvert.Length - 1 : rightBorder; - if (leftBorder > stringToConvert.Length - 1) { break; diff --git a/Homework3/LZW/LZW/Solution.cs b/Homework3/LZW/LZW/Solution.cs index f7f6ff2..3076219 100644 --- a/Homework3/LZW/LZW/Solution.cs +++ b/Homework3/LZW/LZW/Solution.cs @@ -6,7 +6,9 @@ static void Main(string[] args) { if (args.Length != 2) { - throw new FileNotFoundException(); + Console.WriteLine("The first argument should be the path to the file, " + + "the second argument is the key -c if you need to compress the file, the key -u if you decompress"); + return; } string pathToFile = args[0]; @@ -15,18 +17,21 @@ static void Main(string[] args) { var file = new FileInfo(pathToFile); long uncompressedFileSize = file.Length; - string fileName = Path.GetFileNameWithoutExtension(pathToFile); - fileName = $"{pathToFile}..\\..\\{fileName}.zipped"; + string fileName = $"{pathToFile}.zipped"; LZW.CompressFile(pathToFile); file = new FileInfo(fileName); long compressedFileSize = file.Length; Console.WriteLine((float)(uncompressedFileSize) / (float)compressedFileSize); return; } - - if (args[1] == "-u") + else if (args[1] == "-u") { LZW.DecompressFile(pathToFile); } + else + { + Console.WriteLine("Invalid key entered"); + } + } } diff --git a/Homework3/LZW/LZW/Bor.cs b/Homework3/LZW/LZW/Trie.cs similarity index 73% rename from Homework3/LZW/LZW/Bor.cs rename to Homework3/LZW/LZW/Trie.cs index 9ae1cef..ada8e03 100644 --- a/Homework3/LZW/LZW/Bor.cs +++ b/Homework3/LZW/LZW/Trie.cs @@ -1,36 +1,48 @@ -namespace Bor; +namespace Trie; /// /// A class representing the bor data structure /// -public class Bor +public class Trie { /// /// // A class representing the bor data structure /// private class Node { - // Dictionary for storing characters for each node + /// + /// Dictionary for storing characters for each node + /// public Dictionary Nodes = new(); - // Code for each node + /// + /// Code for each node + /// public int Code { get; set;} } - // Bor root + /// + /// Bor root + /// private readonly Node root = new(); - // Bor size + /// + /// Bor size + /// public int Size { get; private set; } private Node currentNode; - public int GetCode() - { - return currentNode.Code; - } + /// + /// Function for getting the code of the current element + /// + /// + public int GetCode() => currentNode.Code; - public Bor() + /// + /// Trie constructor + /// + public Trie() { root.Code = -1; @@ -50,7 +62,7 @@ public Bor() /// /// Function to add a byte /// - /// byte to add + /// Byte to add public void Add(byte byteToAdd) { Node node = new(); diff --git a/Homework3/LZW/LZWTest/LZW.exe b/Homework3/LZW/LZWTest/LZW.exe new file mode 100644 index 0000000000000000000000000000000000000000..60c498d0f0066561362f7ddac0d4d1514fe0f983 GIT binary patch literal 148992 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 J9^-#WKLCV3vn~Jt literal 0 HcmV?d00001 diff --git a/Homework3/LZW/LZWTest/LZWTest.cs b/Homework3/LZW/LZWTest/LZWTest.cs index 2cade72..6ad5ba0 100644 --- a/Homework3/LZW/LZWTest/LZWTest.cs +++ b/Homework3/LZW/LZWTest/LZWTest.cs @@ -5,15 +5,39 @@ namespace Test; public class LZWTests { - [Test] - public void ShouldExpectedStringAreEqualWhenLZWForFile() - { - string filename = "..//..//..//Test.txt"; - LZW.LZW.CompressFile(filename); - string newFilename = "..//..//..//Test.zipped"; - LZW.LZW.DecompressFile(newFilename); - var firstString = File.ReadAllBytes(filename); - var secondString = File.ReadAllBytes("..//..//..//Test"); - Assert.AreEqual(firstString, secondString); - } + [Test] + public void ShouldExpectedDecompressedFileAreEqualInitialFileWhenCompressAndDecompressForTxtFile() + { + string filename = "..//..//..//Test.txt"; + LZW.LZW.CompressFile(filename); + string newFilename = "..//..//..//Test.txt.zipped"; + LZW.LZW.DecompressFile(newFilename); + var firstString = File.ReadAllBytes(filename); + var secondString = File.ReadAllBytes("..//..//..//DecompressedTest.txt"); + Assert.AreEqual(firstString, secondString); + } + + [Test] + public void ShouldExpectedDecompressedFileAreEqualInitialFileWhenCompressAndDecompressForExeFile() + { + string filename = "..//..//..//LZW.exe"; + LZW.LZW.CompressFile(filename); + string newFilename = "..//..//..//LZW.exe.zipped"; + LZW.LZW.DecompressFile(newFilename); + var firstString = File.ReadAllBytes(filename); + var secondString = File.ReadAllBytes("..//..//..//DecompressedLZW.exe"); + Assert.AreEqual(firstString, secondString); + } + + [Test] + public void ShouldExpectedDecompressedFileAreEqualInitialFileWhenCompressAndDecompressForEmptyFile() + { + string filename = "..//..//..//SecondTest.txt"; + LZW.LZW.CompressFile(filename); + string newFilename = "..//..//..//SecondTest.txt.zipped"; + LZW.LZW.DecompressFile(newFilename); + var firstString = File.ReadAllBytes(filename); + var secondString = File.ReadAllBytes("..//..//..//DecompressedSecondTest.txt"); + Assert.AreEqual(firstString, secondString); + } } \ No newline at end of file diff --git a/Homework3/LZW/LZWTest/SecondTest.txt b/Homework3/LZW/LZWTest/SecondTest.txt new file mode 100644 index 0000000..e69de29 diff --git a/Homework3/LZW/LZWTest/BorTest.cs b/Homework3/LZW/LZWTest/TrieTest.cs similarity index 96% rename from Homework3/LZW/LZWTest/BorTest.cs rename to Homework3/LZW/LZWTest/TrieTest.cs index 639e112..ce62004 100644 --- a/Homework3/LZW/LZWTest/BorTest.cs +++ b/Homework3/LZW/LZWTest/TrieTest.cs @@ -1,12 +1,12 @@ namespace Test; using NUnit.Framework; -using Bor; +using Trie; using System; -public class BorTest +public class TrieTest { - Bor bor = new(); + Trie bor = new(); [SetUp] public void Setup() From d1c015adb54e5d3ca067f330e8fdc2f6c88594f9 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 2 Jun 2022 00:11:01 +0300 Subject: [PATCH 5/7] add yml file --- .github/workflows/LZW.yml | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/LZW.yml diff --git a/.github/workflows/LZW.yml b/.github/workflows/LZW.yml new file mode 100644 index 0000000..94ac0b1 --- /dev/null +++ b/.github/workflows/LZW.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 From 2b48a0b9e2f376163df3f9ba1ac3b67a74cdfd73 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 2 Jun 2022 01:15:44 +0300 Subject: [PATCH 6/7] rename yml --- .github/workflows/{LZW.yml => dotnet.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{LZW.yml => dotnet.yml} (100%) diff --git a/.github/workflows/LZW.yml b/.github/workflows/dotnet.yml similarity index 100% rename from .github/workflows/LZW.yml rename to .github/workflows/dotnet.yml From fd7416e8d493ab13bc1382facda2a36da2df6299 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 2 Jun 2022 02:43:46 +0300 Subject: [PATCH 7/7] formatted --- Homework3/LZW/LZW/LZW.cs | 13 ++++---- Homework3/LZW/LZW/Solution.cs | 57 +++++++++++++++-------------------- Homework3/LZW/LZW/Trie.cs | 12 ++++---- 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/Homework3/LZW/LZW/LZW.cs b/Homework3/LZW/LZW/LZW.cs index 7c9ff74..8180a67 100644 --- a/Homework3/LZW/LZW/LZW.cs +++ b/Homework3/LZW/LZW/LZW.cs @@ -60,18 +60,19 @@ public static void CompressFile(string pathToFileToCompress) // Moving on to the next byte bor.MoveIntoDesiredNode(stringToConvert[i]); } + // Otherwise, we add it to the bor else { // Taking the idex from the parent vertex and encode it var bytes = BitConverter.GetBytes(bor.GetCode()); - // Cut off the extra bytes - // The required number of bytes is selected according to the size of the bor - // Since among the numbers that need to be encoded there may be a bor size (index of the maximum vertex), - // the number of bytes to store depends on the size of the bor. - // Even a number requires fewer bytes, - // it is written in a large number of bytes so that it can be decoded later. + /* Cut off the extra bytes + The required number of bytes is selected according to the size of the bor + Since among the numbers that need to be encoded there may be a bor size (index of the maximum vertex), + the number of bytes to store depends on the size of the bor. + Even a number requires fewer bytes, + it is written in a large number of bytes so that it can be decoded later. */ Array.Resize(ref bytes, NumberOfBytes(bor.Size - 1)); bor.Add(stringToConvert[i]); fs.Write(bytes); diff --git a/Homework3/LZW/LZW/Solution.cs b/Homework3/LZW/LZW/Solution.cs index 3076219..747afcf 100644 --- a/Homework3/LZW/LZW/Solution.cs +++ b/Homework3/LZW/LZW/Solution.cs @@ -1,37 +1,28 @@ -namespace LZW; - -public class Solution +if (args.Length != 2) { - static void Main(string[] args) - { - if (args.Length != 2) - { - Console.WriteLine("The first argument should be the path to the file, " + - "the second argument is the key -c if you need to compress the file, the key -u if you decompress"); - return; - } - - string pathToFile = args[0]; + Console.WriteLine("The first argument should be the path to the file, " + + "the second argument is the key -c if you need to compress the file, the key -u if you decompress"); + return; +} - if (args[1] == "-c") - { - var file = new FileInfo(pathToFile); - long uncompressedFileSize = file.Length; - string fileName = $"{pathToFile}.zipped"; - LZW.CompressFile(pathToFile); - file = new FileInfo(fileName); - long compressedFileSize = file.Length; - Console.WriteLine((float)(uncompressedFileSize) / (float)compressedFileSize); - return; - } - else if (args[1] == "-u") - { - LZW.DecompressFile(pathToFile); - } - else - { - Console.WriteLine("Invalid key entered"); - } +string pathToFile = args[0]; - } +if (args[1] == "-c") +{ + var file = new FileInfo(pathToFile); + long uncompressedFileSize = file.Length; + string fileName = $"{pathToFile}.zipped"; + LZW.LZW.CompressFile(pathToFile); + file = new FileInfo(fileName); + long compressedFileSize = file.Length; + Console.WriteLine((float)(uncompressedFileSize) / (float)compressedFileSize); + return; +} +else if (args[1] == "-u") +{ + LZW.LZW.DecompressFile(pathToFile); +} +else +{ + Console.WriteLine("Invalid key entered"); } diff --git a/Homework3/LZW/LZW/Trie.cs b/Homework3/LZW/LZW/Trie.cs index ada8e03..a1848c2 100644 --- a/Homework3/LZW/LZW/Trie.cs +++ b/Homework3/LZW/LZW/Trie.cs @@ -1,12 +1,12 @@ namespace Trie; /// -/// A class representing the bor data structure +/// A class representing the Trie /// public class Trie { /// - /// // A class representing the bor data structure + /// A class representing the Trie node /// private class Node { @@ -22,12 +22,12 @@ private class Node } /// - /// Bor root + /// Trie root /// private readonly Node root = new(); /// - /// Bor size + /// Trie size /// public int Size { get; private set; } @@ -36,7 +36,7 @@ private class Node /// /// Function for getting the code of the current element /// - /// + /// Code public int GetCode() => currentNode.Code; /// @@ -73,7 +73,7 @@ public void Add(byte byteToAdd) } /// - /// Is the byte contained in Current Node + /// Is the byte contained in Current node /// /// Element to search /// True if there is such a byte. False if there is no such byte