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/StackCalculator/StackCalculator.sln b/Homework2/StackCalculator/StackCalculator.sln new file mode 100644 index 0000000..7317c0d --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator.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}") = "StackCalculator", "StackCalculator\StackCalculator.csproj", "{8DBDDAE0-E403-49E6-9223-5AC9BF60294F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "TestStackCalculator\Tests.csproj", "{46FAACC4-DAD8-4735-943E-22F9ADAA23C6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8DBDDAE0-E403-49E6-9223-5AC9BF60294F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DBDDAE0-E403-49E6-9223-5AC9BF60294F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DBDDAE0-E403-49E6-9223-5AC9BF60294F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DBDDAE0-E403-49E6-9223-5AC9BF60294F}.Release|Any CPU.Build.0 = Release|Any CPU + {46FAACC4-DAD8-4735-943E-22F9ADAA23C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46FAACC4-DAD8-4735-943E-22F9ADAA23C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46FAACC4-DAD8-4735-943E-22F9ADAA23C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46FAACC4-DAD8-4735-943E-22F9ADAA23C6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F3D2B963-4468-436F-A5AE-D78F83C046C7} + EndGlobalSection +EndGlobal diff --git a/Homework2/StackCalculator/StackCalculator/Calculator.cs b/Homework2/StackCalculator/StackCalculator/Calculator.cs new file mode 100644 index 0000000..8183b2a --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/Calculator.cs @@ -0,0 +1,90 @@ +namespace StackCalculator; + +using Stack; + +/// +/// A class representing a stack calculator +/// +public class Calculator +{ + /// + /// Function for counting expressions in postfix form + /// + /// Expression value + public float CountTheExpressionInPostfixForm(string[] inputString, IStack stack) + { + for (int i = 0; i < inputString.Length; i++) + { + if (inputString[i] == "") + { + continue; + } + + if (int.TryParse(inputString[i], out int number)) + { + stack.Push(number); + continue; + } + + if (stack.NumberOfElements() < 2) + { + throw new IncorrectExpressionException(); + } + + float secondNumber; + float firstNumber; + try + { + secondNumber = stack.Pop(); + firstNumber = stack.Pop(); + } + catch (StackIsEmptyException) + { + throw; + } + + switch (inputString[i]) + { + case "+" : + { + stack.Push(firstNumber + secondNumber); + break; + } + + case "-" : + { + stack.Push(firstNumber - secondNumber); + break; + } + + case "*" : + { + stack.Push(firstNumber * secondNumber); + break; + } + + case "/" : + { + if (Math.Abs(secondNumber - 0) < 0.0000000000000000000000000001) + { + throw new DivideByZeroException(); + } + stack.Push(firstNumber / secondNumber); + break; + } + + default : + { + throw new InvalidCharacterException(); + } + } + } + + if (stack.NumberOfElements() != 1) + { + throw new IncorrectExpressionException(); + } + + return stack.Pop(); + } +} diff --git a/Homework2/StackCalculator/StackCalculator/IStack.cs b/Homework2/StackCalculator/StackCalculator/IStack.cs new file mode 100644 index 0000000..7138d4d --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/IStack.cs @@ -0,0 +1,47 @@ +namespace Stack; + +/// +/// A class representing the stack interface +/// +public interface IStack +{ + /// + /// Function for checking the stack for emptiness + /// + /// True - if the stack is empty + public bool IsEmpty(); + + /// + /// Function for adding an element to the stack + /// + /// The value to add + public void Push(T value); + + /// + /// Function for removing an element from the stack + /// + /// Remote value + public T? Pop(); + + /// + /// Function that returns the number of elements in the stack + /// + /// Number of elements in stack + public int NumberOfElements(); + + /// + /// Function that returns the top of the stack + /// + /// Top of the stack + public T? TopOfTheStack(); + + /// + /// Function for stack printing + /// + public void PrintStack(); + + /// + /// Function for removing the stack + /// + public void ClearStack(); +} diff --git a/Homework2/StackCalculator/StackCalculator/IncorrectExpressionException.cs b/Homework2/StackCalculator/StackCalculator/IncorrectExpressionException.cs new file mode 100644 index 0000000..3a68f0e --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/IncorrectExpressionException.cs @@ -0,0 +1,9 @@ +namespace StackCalculator; + +/// +/// A class for creating custom exceptions +/// +public class IncorrectExpressionException : Exception +{ + public IncorrectExpressionException() : base() { } +} \ No newline at end of file diff --git a/Homework2/StackCalculator/StackCalculator/InvalidCharacterException.cs b/Homework2/StackCalculator/StackCalculator/InvalidCharacterException.cs new file mode 100644 index 0000000..6500cdd --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/InvalidCharacterException.cs @@ -0,0 +1,9 @@ +namespace StackCalculator; + +/// +/// A class for creating custom exceptions +/// +public class InvalidCharacterException : Exception +{ + public InvalidCharacterException() : base() { } +} \ No newline at end of file diff --git a/Homework2/StackCalculator/StackCalculator/StackCalculator.csproj b/Homework2/StackCalculator/StackCalculator/StackCalculator.csproj new file mode 100644 index 0000000..a531813 --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/StackCalculator.csproj @@ -0,0 +1,11 @@ + + + + Library + net6.0 + enable + enable + + + + diff --git a/Homework2/StackCalculator/StackCalculator/StackIsEmptyException.cs b/Homework2/StackCalculator/StackCalculator/StackIsEmptyException.cs new file mode 100644 index 0000000..9264793 --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/StackIsEmptyException.cs @@ -0,0 +1,9 @@ +namespace Stack; + +/// +/// A class for creating custom exceptions +/// +public class StackIsEmptyException : Exception +{ + public StackIsEmptyException() : base() { } +} diff --git a/Homework2/StackCalculator/StackCalculator/StackOnArray.cs b/Homework2/StackCalculator/StackCalculator/StackOnArray.cs new file mode 100644 index 0000000..a4676ee --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/StackOnArray.cs @@ -0,0 +1,99 @@ +namespace Stack; + +using System; + +/// +/// A class representing the stack on arrays +/// +public class StackOnArray : IStack +{ + private T[] values; + private int numberOfElements; + + public StackOnArray() + { + values = new T[20]; + } + + /// + /// Function for checking the stack for emptiness + /// + /// True - if the stack is empty + public bool IsEmpty() => numberOfElements == 0; + + /// + /// Function for adding an element to the stack + /// + /// The value to add + public void Push(T value) + { + if (values != null && numberOfElements == values.Length) + { + Array.Resize(ref values, values.Length + 20); + } + + numberOfElements++; + if (values == null) + { + return; + } + + values[numberOfElements - 1] = value; + } + + /// + /// Function for removing an element from the stack + /// + /// Remote value + public T Pop() + { + if (numberOfElements == 0 || values == null) + { + throw new StackIsEmptyException(); + } + + T topOfSTack = values[numberOfElements - 1]; + Array.Clear(values, numberOfElements - 1, 1); + numberOfElements--; + return topOfSTack; + } + + /// + /// Function that returns the top of the stack + /// + /// Top of the stack + public T TopOfTheStack() + { + if (numberOfElements == 0 || values == null) + { + throw new StackIsEmptyException(); + } + + return values[numberOfElements - 1]; + } + + /// + /// Function that returns the number of elements in the stack + /// + /// Number of elements in stack + public int NumberOfElements() => numberOfElements; + + /// + /// Function for stack printing + /// + public void PrintStack() + { + for (int i = numberOfElements - 1; i >= 0; i--) + { + if (values != null) + { + Console.Write($"{values[i]} "); + } + } + } + + /// + /// Function for removing the stack + /// + public void ClearStack() => values = new T[20]; +} diff --git a/Homework2/StackCalculator/StackCalculator/StackOnLists.cs b/Homework2/StackCalculator/StackCalculator/StackOnLists.cs new file mode 100644 index 0000000..07770ba --- /dev/null +++ b/Homework2/StackCalculator/StackCalculator/StackOnLists.cs @@ -0,0 +1,100 @@ +namespace Stack; + +using System; + +/// +/// A class representing the stack on lists +/// +public class StackOnLists : IStack +{ + private class StackElement + { + public StackElement? Next { get; set; } + public T? Value { get; set; } + } + + private StackElement? head; + private int numberOfElements; + + /// + /// Function for checking the stack for emptiness + /// + /// True - if the stack is empty + public bool IsEmpty() => numberOfElements == 0; + + /// + /// Function for adding an element to the stack + /// + /// The value to add + public void Push(T value) + { + numberOfElements++; + StackElement newHead = new(); + newHead.Value = value; + newHead.Next = head; + head = newHead; + } + + /// + /// Function for removing an element from the stack + /// + /// Remote value + public T? Pop() + { + if (head == null) + { + throw new StackIsEmptyException(); + } + + if (head != null) + { + T? value = head.Value; + head = head.Next; + numberOfElements--; + return value; + } + return default; + } + + /// + /// Function that returns the number of elements in the stack + /// + /// Number of elements in stack + public int NumberOfElements() => numberOfElements; + + /// + /// Function that returns the top of the stack + /// + /// Top of the stack + public T? TopOfTheStack() + { + if (head == null) + { + throw new StackIsEmptyException(); + } + return head == null ? default : head.Value; + } + + /// + /// Function for stack printing + /// + public void PrintStack() + { + if (head == null) + { + return; + } + + StackElement? copyHead = head; + while (copyHead != null) + { + Console.Write($"{copyHead.Value} "); + copyHead = copyHead.Next; + } + } + + /// + /// Function for removing the stack + /// + public void ClearStack() => head = null; +} diff --git a/Homework2/StackCalculator/TestStackCalculator/TestStack.cs b/Homework2/StackCalculator/TestStackCalculator/TestStack.cs new file mode 100644 index 0000000..c3a2c6f --- /dev/null +++ b/Homework2/StackCalculator/TestStackCalculator/TestStack.cs @@ -0,0 +1,76 @@ +namespace TestStack; + +using NUnit.Framework; +using Stack; +using System.Collections.Generic; + +/// +/// A class for testing the stack on arrays +/// +public class StackTest +{ + private static IEnumerable Stacks + => new TestCaseData[] + { + new TestCaseData(new StackOnArray()), + new TestCaseData(new StackOnLists()), + }; + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsStackExceptionWhenRemoveFromEmptyStack(IStack stack) + { + Assert.Throws(() => stack.Pop()); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldStackNotEmptyAfterPush(IStack stack) + { + stack.Push(1); + Assert.IsFalse(stack.IsEmpty()); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsStackExceptionWhenTopOfTheStackFromEmptyStack(IStack stack) + { + Assert.Throws(() => stack.TopOfTheStack()); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldTopOfTheStackEqual1WhenPush1(IStack stack) + { + stack.Push(1); + Assert.AreEqual(1, stack.TopOfTheStack()); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldNumberOFElementsEqualZeroWhenEmptyStack(IStack stack) + { + Assert.AreEqual(0, stack.NumberOfElements()); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldNumberOfElementsEqual1WhenPushInEmptyStack(IStack stack) + { + stack.Push(1); + Assert.AreEqual(1, stack.NumberOfElements()); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldNumberOfElementsNotChangesWhenRemoveAfterPush(IStack stack) + { + stack.Push(1); + Assert.AreEqual(1, stack.NumberOfElements()); + stack.Pop(); + Assert.AreEqual(0, stack.NumberOfElements()); + } + + + [TestCaseSource(nameof(Stacks))] + public void ShouldTopOfTheStackNotChangesWhenPrintStack(IStack stack) + { + stack.Push(1); + stack.Push(2); + stack.PrintStack(); + Assert.AreEqual(2, stack.TopOfTheStack()); + } +} diff --git a/Homework2/StackCalculator/TestStackCalculator/TestStackCalculator.cs b/Homework2/StackCalculator/TestStackCalculator/TestStackCalculator.cs new file mode 100644 index 0000000..03b471f --- /dev/null +++ b/Homework2/StackCalculator/TestStackCalculator/TestStackCalculator.cs @@ -0,0 +1,84 @@ +namespace TestStackCalculator; + +using NUnit.Framework; +using Stack; +using System.Collections.Generic; +using StackCalculator; + +/// +/// A class for testing a stack calculator +/// +public class TestsStackCalculator +{ + private Calculator stackCalculator = new(); + + [SetUp] + public void Setup() + { + stackCalculator = new Calculator(); + } + + private static IEnumerable Stacks + => new TestCaseData[] + { + new TestCaseData(new StackOnArray()), + new TestCaseData(new StackOnLists()), + }; + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsDivideByZeroExceptionWhenDivideByZero(IStack stack) + { + string[] firstArray = { "123", "0", "/" }; + Assert.Throws(() => stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsInvalidCharacterExceptionWhenExpressionContainsInvalidCharacter(IStack stack) + { + string[] firstArray = { "123", "0", "a" }; + Assert.Throws (() => stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsIncorrectExpressionExceptionWhenExpressionIncorrect(IStack stack) + { + string[] expression = { "123", "4", "*", "-" }; + Assert.Throws(() => stackCalculator?.CountTheExpressionInPostfixForm(expression, stack)); + } + + + [TestCaseSource(nameof(Stacks))] + public void ShouldExpected12WhenExpressionEqual12(IStack stack) + { + string[] firstArray = { "12"}; + Assert.AreEqual(12, stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldExpectedZeroWhenExpressionContainsOnlyZerosAndNotContainsDivisions(IStack stack) + { + string[] firstArray = { "0", "0", "+", "0", "-" }; + Assert.AreEqual(0, stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsIncorrectExpressionExceptionWhenExpressionContainsOnlyOperators(IStack stack) + { + string[] firstArray = {"+", "-"}; + Assert.Throws(() => stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldThrowsIncorrectExpressionExceptionWhenExpressionIsEmptyString(IStack stack) + { + string[] firstArray = {" "}; + Assert.Throws(() => stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } + + [TestCaseSource(nameof(Stacks))] + public void ShouldExpected15WhenIfIsKnownThatTheResultIs15(IStack stack) + { + string[] firstArray = { "0" , "120", "+", "45", "15", "/", "33", "+", "-5", "-13", "+", "9", "/", "/", "1", "123", "*", "+", "-" }; + Assert.AreEqual(15, stackCalculator?.CountTheExpressionInPostfixForm(firstArray, stack)); + } +} \ No newline at end of file diff --git a/Homework2/StackCalculator/TestStackCalculator/Tests.csproj b/Homework2/StackCalculator/TestStackCalculator/Tests.csproj new file mode 100644 index 0000000..b7fe0be --- /dev/null +++ b/Homework2/StackCalculator/TestStackCalculator/Tests.csproj @@ -0,0 +1,21 @@ + + + + net6.0 + enable + + false + + + + + + + + + + + + + +