Skip to content

Commit 1da1c83

Browse files
committed
Creating the Bar class, writing the required functions and tests for them
1 parent 3e33fb1 commit 1da1c83

File tree

9 files changed

+417
-0
lines changed

9 files changed

+417
-0
lines changed

Homework3/LZW/LZW.sln

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.1.32210.238
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LZW", "LZW\LZW.csproj", "{5DAEADDF-7108-4028-90E1-5C05C2034360}"
7+
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "LZWTest\Tests.csproj", "{455E760B-8592-4A15-BB37-A79DAE435B4C}"
9+
EndProject
10+
Global
11+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|Any CPU = Debug|Any CPU
13+
Release|Any CPU = Release|Any CPU
14+
EndGlobalSection
15+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{5DAEADDF-7108-4028-90E1-5C05C2034360}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17+
{5DAEADDF-7108-4028-90E1-5C05C2034360}.Debug|Any CPU.Build.0 = Debug|Any CPU
18+
{5DAEADDF-7108-4028-90E1-5C05C2034360}.Release|Any CPU.ActiveCfg = Release|Any CPU
19+
{5DAEADDF-7108-4028-90E1-5C05C2034360}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{455E760B-8592-4A15-BB37-A79DAE435B4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{455E760B-8592-4A15-BB37-A79DAE435B4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{455E760B-8592-4A15-BB37-A79DAE435B4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{455E760B-8592-4A15-BB37-A79DAE435B4C}.Release|Any CPU.Build.0 = Release|Any CPU
24+
EndGlobalSection
25+
GlobalSection(SolutionProperties) = preSolution
26+
HideSolutionNode = FALSE
27+
EndGlobalSection
28+
GlobalSection(ExtensibilityGlobals) = postSolution
29+
SolutionGuid = {7673691E-822C-4405-8F11-DE9C2BCBAE62}
30+
EndGlobalSection
31+
EndGlobal

Homework3/LZW/LZW/Bor.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
namespace Bor;
2+
3+
/// <summary>
4+
/// A class representing the bor data structure
5+
/// </summary>
6+
public class Bor
7+
{
8+
/// <summary>
9+
/// // A class representing the bor data structure
10+
/// </summary>
11+
private class Node
12+
{
13+
// Dictionary for storing characters for each node
14+
public Dictionary<byte, Node> Nodes = new();
15+
16+
// Code for each node
17+
public int Code { get; set;}
18+
}
19+
20+
// Bor root
21+
private readonly Node root = new();
22+
23+
// Bor size
24+
public int Size { get; private set; }
25+
26+
private Node currentNode;
27+
28+
public int GetCode()
29+
{
30+
return currentNode.Code;
31+
}
32+
33+
public Bor()
34+
{
35+
root.Code = -1;
36+
37+
// Initialize the bor with numbers from 0 to 256
38+
for (int i = 0; i < 256; i++)
39+
{
40+
Node node = new();
41+
root.Nodes.Add((byte)i, node);
42+
node.Code = Size;
43+
Size++;
44+
}
45+
46+
// The current node is the root
47+
currentNode = root;
48+
}
49+
50+
/// <summary>
51+
/// Function to add a byte
52+
/// </summary>
53+
/// <param name="byteToAdd"> byte to add </param>
54+
public void Add(byte byteToAdd)
55+
{
56+
Node node = new();
57+
currentNode?.Nodes.Add(byteToAdd, node);
58+
currentNode = root;
59+
node.Code = Size;
60+
Size++;
61+
}
62+
63+
/// <summary>
64+
/// Is the byte contained in Current Node
65+
/// </summary>
66+
/// <param name="element"> Element to search </param>
67+
/// <returns> True if there is such a byte. False if there is no such byte </returns>
68+
public bool Contains(byte byteToSearch) => currentNode.Nodes.ContainsKey(byteToSearch);
69+
70+
/// <summary>
71+
/// Function for moving to another node
72+
/// </summary>
73+
/// <param name="byteT">the byte to be moved to</param>
74+
public void MoveIntoDesiredNode(byte byteToBeMovedTo) => currentNode = currentNode.Nodes[byteToBeMovedTo];
75+
76+
/// <summary>
77+
/// Function for moving to root
78+
/// </summary>
79+
public void MovedToRoot() => currentNode = root;
80+
}
81+

Homework3/LZW/LZW/LZW.cs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
namespace LZW;
2+
3+
using System;
4+
using System.IO;
5+
using Bor;
6+
7+
/// <summary>
8+
/// A class representing the LZW algorithm
9+
/// </summary>
10+
public class LZW
11+
{
12+
//A function for determining the number of bytes needed to store a number
13+
private static int NumberOfBytes(int number)
14+
{
15+
if (number < 256)
16+
{
17+
return 1;
18+
}
19+
if (number < 65536)
20+
{
21+
return 2;
22+
}
23+
if (number < 16777216)
24+
{
25+
return 3;
26+
}
27+
return 4;
28+
}
29+
30+
/// <summary>
31+
/// Function for file compression
32+
/// </summary>
33+
/// <param name="pathToFileToCompress">The path to the file to compress</param>
34+
public static void CompressFile(string pathToFileToCompress)
35+
{
36+
37+
string fileName = Path.GetFileNameWithoutExtension(pathToFileToCompress);
38+
fileName = $"{pathToFileToCompress}..//..//{fileName}.zipped";
39+
40+
// Name of the compressed file
41+
using FileStream fs = new(fileName, FileMode.Create);
42+
43+
// Reading all bytes from a file
44+
var stringToConvert = File.ReadAllBytes(pathToFileToCompress);
45+
46+
// Creating bor
47+
Bor bor = new();
48+
49+
for (int i = 0; i < stringToConvert.Length; i++)
50+
{
51+
// If the byte is contained in the bor
52+
if (bor.Contains(stringToConvert[i]))
53+
{
54+
// Moving on to the next byte
55+
bor.MoveIntoDesiredNode(stringToConvert[i]);
56+
}
57+
// Otherwise, we add it to the bor
58+
else
59+
{
60+
// Taking the idex from the parent vertex and encode it
61+
var bytes = BitConverter.GetBytes(bor.GetCode());
62+
63+
// Cut off the extra bytes
64+
// The required number of bytes is selected according to the size of the bor
65+
// Since among the numbers that need to be encoded there may be a bor size (index of the maximum vertex),
66+
// the number of bytes to store depends on the size of the bor.
67+
// Even a number requires fewer bytes,
68+
// it is written in a large number of bytes so that it can be decoded later.
69+
Array.Resize(ref bytes, NumberOfBytes(bor.Size - 1));
70+
bor.Add(stringToConvert[i]);
71+
fs.Write(bytes);
72+
73+
// Going back to the last vertex
74+
i--;
75+
}
76+
}
77+
78+
// The last bytes that are already in the dictionary and that are not written in the loop
79+
var newbytes = BitConverter.GetBytes(bor.GetCode());
80+
Array.Resize(ref newbytes, NumberOfBytes(bor.Size));
81+
fs.Write(newbytes);
82+
}
83+
84+
public static void DecompressFile(string pathToFile)
85+
{
86+
87+
string fileName = Path.GetFileNameWithoutExtension(pathToFile);
88+
fileName = $"{pathToFile}..//..//{fileName}";
89+
90+
// Create file
91+
using FileStream fs = new(fileName, FileMode.Create);
92+
93+
// Reading all bytes from a file
94+
byte[] stringToConvert = File.ReadAllBytes(pathToFile);
95+
96+
// Dictionary for decoding
97+
var dictionary = new Dictionary<int, byte[]>();
98+
99+
for (int i = 0; i < 256; i++)
100+
{
101+
int index = 0;
102+
var byteArray = BitConverter.GetBytes(i);
103+
for (int l = 0; l < byteArray.Length; l++)
104+
{
105+
if (l == 1)
106+
{
107+
index = l;
108+
}
109+
}
110+
dictionary.Add(i, byteArray[0..index]);
111+
}
112+
113+
int rightBorder = 0;
114+
int leftBorder = 0;
115+
bool flag = false;
116+
117+
while (leftBorder < stringToConvert.Length)
118+
{
119+
// The right border of the current subarray
120+
rightBorder = leftBorder + NumberOfBytes(dictionary.Count - 1) - 1;
121+
122+
// If the right border has gone beyond the edge, then we will make it the last byte
123+
rightBorder = rightBorder > stringToConvert.Length - 1 ? stringToConvert.Length - 1 : rightBorder;
124+
125+
126+
if (leftBorder > stringToConvert.Length - 1)
127+
{
128+
break;
129+
}
130+
131+
// Converting bytes to int
132+
var bytes = new byte[4];
133+
Array.Copy(stringToConvert, leftBorder, bytes, 0, NumberOfBytes(dictionary.Count - 1));
134+
leftBorder = rightBorder + 1;
135+
int answer = BitConverter.ToInt32(bytes);
136+
137+
// If it is the first number
138+
if (!flag)
139+
{
140+
flag = true;
141+
}
142+
143+
// Otherwise, we concatenate the last element with the first byte of the current one
144+
else
145+
{
146+
var newArray = new byte[dictionary[dictionary.Count - 1].Length + 1];
147+
Array.Copy(dictionary[dictionary.Count - 1], newArray, dictionary[dictionary.Count - 1].Length);
148+
newArray[newArray.Length - 1] = dictionary[answer][0];
149+
// Changing the value in the dictionary to the value we need
150+
dictionary[dictionary.Count - 1] = newArray;
151+
}
152+
153+
// Adding a new element to the dictionary
154+
dictionary.Add(dictionary.Count, dictionary[answer]);
155+
fs.Write(dictionary[answer]);
156+
}
157+
}
158+
}

Homework3/LZW/LZW/LZW.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
</Project>

Homework3/LZW/LZW/Solution.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace LZW;
2+
3+
public class Solution
4+
{
5+
static void Main(string[] args)
6+
{
7+
if (args.Length != 2)
8+
{
9+
throw new FileNotFoundException();
10+
}
11+
string pathToFile = args[0];
12+
if (args[1] == "-c")
13+
{
14+
var file = new FileInfo(pathToFile);
15+
long uncompressedFileSize = file.Length;
16+
string fileName = Path.GetFileNameWithoutExtension(pathToFile);
17+
fileName = $"{pathToFile}..\\..\\{fileName}.zipped";
18+
LZW.CompressFile(pathToFile);
19+
file = new FileInfo(fileName);
20+
long compressedFileSize = file.Length;
21+
Console.WriteLine((float)(uncompressedFileSize) / (float)compressedFileSize);
22+
return;
23+
}
24+
if (args[1] == "-u")
25+
{
26+
LZW.DecompressFile(pathToFile);
27+
}
28+
}
29+
}

Homework3/LZW/LZWTest/BorTest.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
namespace Test;
2+
3+
using NUnit.Framework;
4+
using Bor;
5+
using System;
6+
7+
public class BorTest
8+
{
9+
Bor bor = new();
10+
11+
[SetUp]
12+
public void Setup()
13+
{
14+
bor = new();
15+
}
16+
17+
[Test]
18+
public void ShouldExpectedTrueWhenContainsForBorWhereinCurrentNodeContainsThisNode()
19+
{
20+
bor.MoveIntoDesiredNode((byte)123);
21+
bor.Add((byte)143);
22+
bor.MoveIntoDesiredNode((byte)123);
23+
Assert.IsTrue(bor.Contains((byte)143));
24+
}
25+
26+
[Test]
27+
public void ShouldExpectedFalseWhenContainsForBorWhereinCurrentNodeContainsThisNode()
28+
{
29+
bor.MoveIntoDesiredNode((byte)123);
30+
Assert.IsFalse(bor.Contains((byte)143));
31+
}
32+
33+
[Test]
34+
public void ShouldBorSizeIncreaseByOneWhenAdd()
35+
{
36+
bor.MoveIntoDesiredNode((byte)123);
37+
var size = bor.Size;
38+
bor.Add((byte)12);
39+
Assert.AreEqual(size + 1, bor.Size);
40+
}
41+
42+
[Test]
43+
public void ShouldWhenAddExistingNode()
44+
{
45+
Assert.Throws<ArgumentException>(() => bor.Add((byte)12));
46+
}
47+
48+
[Test]
49+
public void ShouldExpectedCurrentRootEqualRootWhenMoveToRoot()
50+
{
51+
bor.MoveIntoDesiredNode((byte)123);
52+
bor.MovedToRoot();
53+
Assert.AreEqual(-1, bor.GetCode());
54+
}
55+
56+
[Test]
57+
public void ShouldExpectedCurrentRootWhenMoveIntoDesiredNode()
58+
{
59+
bor.MoveIntoDesiredNode((byte)123);
60+
Assert.AreEqual(123, bor.GetCode());
61+
}
62+
}

0 commit comments

Comments
 (0)