-
Notifications
You must be signed in to change notification settings - Fork 0
Lzw.homework3 #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
MinyazevR
wants to merge
7
commits into
main
Choose a base branch
from
LZW.Homework3
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
3e33fb1
Writing basic stack functions, writing tests
MinyazevR 3ec3df7
Creating the Bor class, writing the required functions and tests for …
MinyazevR 4ad95c3
formatted
MinyazevR 81ee53d
Added tests for binary and empty file
MinyazevR d1c015a
add yml file
MinyazevR 2b48a0b
rename yml
MinyazevR fd7416e
formatted
MinyazevR File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,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 |
This file contains hidden or 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,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 |
This file contains hidden or 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,162 @@ | ||
| namespace LZW; | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using Trie; | ||
|
|
||
| /// <summary> | ||
| /// A class representing the LZW algorithm | ||
| /// </summary> | ||
| public class LZW | ||
| { | ||
| /// <summary> | ||
| /// A function for determining the number of bytes needed to store a number | ||
| /// </summary> | ||
| private static int NumberOfBytes(int number) | ||
| { | ||
| if (number < 256) | ||
| { | ||
| return 1; | ||
| } | ||
| if (number < 65536) | ||
| { | ||
| return 2; | ||
| } | ||
| if (number < 16777216) | ||
| { | ||
| return 3; | ||
| } | ||
| return 4; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Function for file compression | ||
| /// </summary> | ||
| /// <param name="pathToFileToCompress">The path to the file to compress</param> | ||
| public static void CompressFile(string pathToFileToCompress) | ||
| { | ||
| // 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 | ||
| Trie bor = new(); | ||
|
|
||
| if (stringToConvert.Length == 0) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| 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); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Function for file decompression | ||
| /// </summary> | ||
| /// <param name="pathToFile">The path to the file to decompress</param> | ||
| public static void DecompressFile(string pathToFile) | ||
| { | ||
| var currentDirectoryName = Path.GetDirectoryName(pathToFile); | ||
| var fileName = Path.GetFileName(pathToFile); | ||
|
|
||
| // 7 = .zipped.length | ||
| fileName = $"{currentDirectoryName}//Decompressed{fileName[0..(fileName.Length - 7)]}"; | ||
|
|
||
| // 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<int, byte[]>(); | ||
|
|
||
| for (int i = 0; i < 256; i++) | ||
| { | ||
| var byteArray = BitConverter.GetBytes(i); | ||
| dictionary.Add(i, byteArray[0..1]); | ||
| } | ||
|
|
||
| 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]); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or 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>net6.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| </Project> |
This file contains hidden or 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 @@ | ||
| 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]; | ||
|
|
||
| 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"); | ||
| } |
This file contains hidden or 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,93 @@ | ||
| namespace Trie; | ||
|
|
||
| /// <summary> | ||
| /// A class representing the Trie | ||
| /// </summary> | ||
| public class Trie | ||
| { | ||
| /// <summary> | ||
| /// A class representing the Trie node | ||
| /// </summary> | ||
| private class Node | ||
| { | ||
| /// <summary> | ||
| /// Dictionary for storing characters for each node | ||
| /// </summary> | ||
| public Dictionary<byte, Node> Nodes = new(); | ||
|
|
||
| /// <summary> | ||
| /// Code for each node | ||
| /// </summary> | ||
| public int Code { get; set;} | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Trie root | ||
| /// </summary> | ||
| private readonly Node root = new(); | ||
|
|
||
| /// <summary> | ||
| /// Trie size | ||
| /// </summary> | ||
| public int Size { get; private set; } | ||
|
|
||
| private Node currentNode; | ||
|
|
||
| /// <summary> | ||
| /// Function for getting the code of the current element | ||
| /// </summary> | ||
| /// <returns>Code</returns> | ||
| public int GetCode() => currentNode.Code; | ||
|
|
||
| /// <summary> | ||
| /// Trie constructor | ||
| /// </summary> | ||
| public Trie() | ||
| { | ||
| 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; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Function to add a byte | ||
| /// </summary> | ||
| /// <param name="byteToAdd"> Byte to add </param> | ||
| public void Add(byte byteToAdd) | ||
| { | ||
| Node node = new(); | ||
| currentNode?.Nodes.Add(byteToAdd, node); | ||
| currentNode = root; | ||
| node.Code = Size; | ||
| Size++; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Is the byte contained in Current node | ||
| /// </summary> | ||
| /// <param name="element"> Element to search </param> | ||
| /// <returns> True if there is such a byte. False if there is no such byte </returns> | ||
| public bool Contains(byte byteToSearch) => currentNode.Nodes.ContainsKey(byteToSearch); | ||
|
|
||
| /// <summary> | ||
| /// Function for moving to another node | ||
| /// </summary> | ||
| /// <param name="byteT">the byte to be moved to</param> | ||
| public void MoveIntoDesiredNode(byte byteToBeMovedTo) => currentNode = currentNode.Nodes[byteToBeMovedTo]; | ||
|
|
||
| /// <summary> | ||
| /// Function for moving to root | ||
| /// </summary> | ||
| public void MovedToRoot() => currentNode = root; | ||
| } | ||
|
|
Binary file not shown.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Вообще, может быть плохой идеей читать файл в память целиком. Файлы бывают большие. Тем более что LZW может работать побайтово. Но это можно не править, для учебных целей вполне ок.