diff --git a/ListAndUniqueList/ListAndUniqueList.sln b/ListAndUniqueList/ListAndUniqueList.sln new file mode 100644 index 0000000..1976afc --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33403.182 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ListAndUniqueList", "ListAndUniqueList\ListAndUniqueList.csproj", "{7F7F9968-FB78-4353-AC51-E0D43F4A7557}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsList", "TestsList\TestsList.csproj", "{BB4EEB6F-6C72-4F81-A0BD-4AADA4AD9058}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsUniqueList", "TestsUniqueList\TestsUniqueList.csproj", "{6FA174A8-43FA-48FB-B3B7-E747E92E4A66}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7F7F9968-FB78-4353-AC51-E0D43F4A7557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F7F9968-FB78-4353-AC51-E0D43F4A7557}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F7F9968-FB78-4353-AC51-E0D43F4A7557}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F7F9968-FB78-4353-AC51-E0D43F4A7557}.Release|Any CPU.Build.0 = Release|Any CPU + {BB4EEB6F-6C72-4F81-A0BD-4AADA4AD9058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB4EEB6F-6C72-4F81-A0BD-4AADA4AD9058}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB4EEB6F-6C72-4F81-A0BD-4AADA4AD9058}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB4EEB6F-6C72-4F81-A0BD-4AADA4AD9058}.Release|Any CPU.Build.0 = Release|Any CPU + {6FA174A8-43FA-48FB-B3B7-E747E92E4A66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6FA174A8-43FA-48FB-B3B7-E747E92E4A66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6FA174A8-43FA-48FB-B3B7-E747E92E4A66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6FA174A8-43FA-48FB-B3B7-E747E92E4A66}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B598B7F0-1489-463C-B6BB-24CBDBDD7F83} + EndGlobalSection +EndGlobal diff --git a/ListAndUniqueList/ListAndUniqueList/InvalidItemException.cs b/ListAndUniqueList/ListAndUniqueList/InvalidItemException.cs new file mode 100644 index 0000000..db53bea --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList/InvalidItemException.cs @@ -0,0 +1,6 @@ +namespace ListAndUniqueList; + +/// +/// Throw exception when item is already in unique list +/// +public class InvalidItemException : Exception {} \ No newline at end of file diff --git a/ListAndUniqueList/ListAndUniqueList/InvalidPositionException.cs b/ListAndUniqueList/ListAndUniqueList/InvalidPositionException.cs new file mode 100644 index 0000000..29e3c68 --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList/InvalidPositionException.cs @@ -0,0 +1,6 @@ +namespace ListAndUniqueList; + +/// +/// Throw exception when the position is incorrect +/// +public class InvalidPositionException : Exception {} \ No newline at end of file diff --git a/ListAndUniqueList/ListAndUniqueList/List.cs b/ListAndUniqueList/ListAndUniqueList/List.cs new file mode 100644 index 0000000..d8ec533 --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList/List.cs @@ -0,0 +1,227 @@ +namespace ListAndUniqueList; + +/// +/// A list for storing and interacting with int type elements +/// +public class List +{ + private ListElement? Head; + private ListElement? Tail; + + /// + /// Adding an item to the list + /// + virtual public void AddElement(int position, int value) + { + if (Head == null) + { + var item = new ListElement(value); + Head = item; + Tail = item; + ++Head.SizeList; + } + else + { + ++Head.SizeList; + ListElement item = new ListElement(value); + if (Tail == null) + { + throw new NullReferenceException(); + } + if (position == 0) + { + var temp = Head.Next; + Head = item; + Head.Next = temp; + return; + } + if (position == Head.SizeList - 1) + { + Tail.Next = item; + Tail = item; + return; + } + var walker = Head; + int counter = 0; + + while (walker != null && walker.Next != null && counter != position) + { + walker = walker.Next; + counter++; + } + if (walker == null || walker.Next == null) + { + throw new NullReferenceException(); + } + else + { + var temp = walker.Next.Next; + walker.Next = item; + item.Next = temp; + } + } + } + + /// + /// Deletes an item at the end of the list + /// + /// Throws an exception when the list is empty + /// Element which was deleted + virtual public int RemoveElement(int position) + { + if (Head == null || Tail == null) + { + throw new NullListException(); + } + if (position > Head.SizeList) + { + throw new NullReferenceException(); + } + if (Tail == Head) + { + var itemFromTail = Tail.Value; + Tail = null; + Head = null; + return itemFromTail; + } + if (position == 0) + { + var itemFromHead = Head.Value; + Head = Head.Next; + return itemFromHead; + } + if (position == Head.SizeList) + { + var itemFromTail = Tail.Value; + var walkerForTail = Head; + while (walkerForTail != null && walkerForTail.Next != Tail) + { + walkerForTail = walkerForTail.Next; + } + if (walkerForTail == null) + { + throw new NullReferenceException(); + } + Tail = walkerForTail; + walkerForTail.Next = null; + } + + int counter = 0; + var walker = Head; + while (walker != null && walker.Next != null && walker.Next.Next != null && counter != position - 1) + { + walker = walker.Next; + counter++; + } + if (walker == null || walker.Next == null) + { + throw new NullReferenceException(); + } + var item = walker.Next.Value; + walker.Next = walker.Next.Next; + --Head.SizeList; + return item; + } + + /// + /// Prints list items + /// + virtual public void PrintTheElements() + { + ListElement? walker = Head; + int counter = 0; + while (walker != null) + { + Console.Write(counter); + Console.Write(' '); + Console.WriteLine(walker.Value); + walker = walker.Next; + ++counter; + } + } + + /// + /// Changes values by position + /// + /// Throws an exception when the list is empty + virtual public void ChangeValueByPosition(int position, int newValue) + { + if (Head == null || Tail == null) + { + throw new NullListException(); + } + ListElement? walker = Head; + int counter = 0; + while (walker != null && counter != position) + { + walker = walker.Next; + counter++; + } + if (walker == null) + { + throw new NullReferenceException(); + } + walker.Value = newValue; + } + + /// + /// Checks if the list is empty + /// + virtual public bool IsEmpty() => Head == null; + + /// + /// Returns the value by position + /// + /// Throws an exception when the list is empty + /// Throws an excwption when there is no such position in the list + virtual public int ReturnValueByPosition(int position) + { + if (Head == null || Tail == null) + { + throw new NullListException(); + } + var walker = Head; + int counter = 0; + while (walker != null && counter != position) + { + walker = walker.Next; + ++counter; + } + if (walker == null) + { + throw new InvalidPositionException(); + } + return walker.Value; + } + + /// + /// Checks if there is an item in the list + /// + /// Returns true if present and false if absent + public bool Contains(int value) + { + var walker = Head; + while (walker != null) + { + if (walker.Value == value) + { + return true; + } + walker = walker.Next; + } + return false; + } + + public class ListElement + { + public ListElement(int value) + { + Value = value; + } + public int Value { get; set; } + + public ListElement? Next { get; set; } + + public int SizeList { get; set; } + } +} diff --git a/ListAndUniqueList/ListAndUniqueList/ListAndUniqueList.csproj b/ListAndUniqueList/ListAndUniqueList/ListAndUniqueList.csproj new file mode 100644 index 0000000..dc2bb05 --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList/ListAndUniqueList.csproj @@ -0,0 +1,10 @@ + + + + Library + net7.0 + enable + enable + + + diff --git a/ListAndUniqueList/ListAndUniqueList/NullPointerException.cs b/ListAndUniqueList/ListAndUniqueList/NullPointerException.cs new file mode 100644 index 0000000..6042e21 --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList/NullPointerException.cs @@ -0,0 +1,6 @@ +namespace ListAndUniqueList; + +/// +/// Throw exception when list is empty +/// +public class NullListException : Exception {} \ No newline at end of file diff --git a/ListAndUniqueList/ListAndUniqueList/UniqueList.cs b/ListAndUniqueList/ListAndUniqueList/UniqueList.cs new file mode 100644 index 0000000..5f106f9 --- /dev/null +++ b/ListAndUniqueList/ListAndUniqueList/UniqueList.cs @@ -0,0 +1,31 @@ +namespace ListAndUniqueList; + +/// +/// List only without repetitions +/// +public class UniqueList : List +{ + public override void AddElement(int position, int value) + { + if (!Contains(value)) + { + base.AddElement(position, value); + } + else + { + throw new InvalidItemException(); + } + } + + public override void ChangeValueByPosition(int position, int newValue) + { + if (!Contains(newValue) || ReturnValueByPosition(position) == newValue) + { + base.ChangeValueByPosition(position, newValue); + } + else + { + throw new InvalidItemException(); + } + } +} diff --git a/ListAndUniqueList/TestsList/TestsList.cs b/ListAndUniqueList/TestsList/TestsList.cs new file mode 100644 index 0000000..790f5f5 --- /dev/null +++ b/ListAndUniqueList/TestsList/TestsList.cs @@ -0,0 +1,88 @@ +namespace TestList; + +using ListAndUniqueList; + +public class Tests +{ + [TestCaseSource(nameof(ListForTest))] + public void ListShouldBeEmptyWhenCreated(List list) + { + Assert.True(list.IsEmpty()); + } + + [TestCaseSource(nameof(ListForTest))] + public void WhenAddedToTheListElementListShouldNotBeEmpty(List list) + { + list.AddElement(0, 1); + Assert.False(list.IsEmpty()); + } + + [TestCaseSource(nameof(ListForTest))] + public void WhenAddingAnElementToTheListAndThenDeletingItTheSheetShouldbeEmpty(List list) + { + list.AddElement(0, 1); + int item = 0; + list.RemoveElement(item); + Assert.True(list.IsEmpty()); + } + + [TestCaseSource(nameof(ListForTest))] + public void TheListShouldReturnTheCorrectDataAfterDeletion(List list) + { + list.AddElement(0, 1); + list.AddElement(1, 10); + list.AddElement(2, 12); + int item = list.RemoveElement(1); + Assert.That(item, Is.EqualTo(10)); + } + + [TestCaseSource(nameof(ListForTest))] + public void TheListShouldCorrectlyReplaceThePositionData(List list) + { + list.AddElement(0, 1); + list.AddElement(1, 10); + list.ChangeValueByPosition(1, 15); + int item = list.RemoveElement(1); + Assert.That(item, Is.EqualTo(15)); + } + + [TestCaseSource(nameof(ListForTest))] + public void AnEmptyListShouldThrowAnExceptionWhenTryingToDelete(List list) + { + Assert.Throws(() => list.RemoveElement(0)); + } + + [TestCaseSource(nameof(ListForTest))] + public void AnEmptyListShouldThrowAnExceptionWhenTryingToChangeValueByPosition(List list) + { + Assert.Throws(() => list.ChangeValueByPosition(10, 10)); + } + + [TestCaseSource(nameof(ListForTest))] + public void AnEmptyListShouldThrowAnExceptionWhenTryingToChangeCheckValueByPosition(List list) + { + Assert.Throws(() => list.ReturnValueByPosition(10)); + } + + [TestCaseSource(nameof(ListForTest))] + public void TheListShouldThrowAnExceptionIfThereIsNoPositionInTheListWhenReturningAnItemByPosition(List list) + { + list.AddElement(0, 1); + Assert.Throws(() => list.ReturnValueByPosition(10)); + } + + [TestCaseSource(nameof(ListForTest))] + public void TheListShouldReturnTheCorrectItemByPosition(List list) + { + list.AddElement(0, 15); + int item = list.ReturnValueByPosition(0); + Assert.That(item, Is.EqualTo(15)); + } + + private static IEnumerable ListForTest + => new TestCaseData[] + { + new TestCaseData(new List()), + new TestCaseData(new UniqueList()), + }; +} \ No newline at end of file diff --git a/ListAndUniqueList/TestsList/TestsList.csproj b/ListAndUniqueList/TestsList/TestsList.csproj new file mode 100644 index 0000000..16345a4 --- /dev/null +++ b/ListAndUniqueList/TestsList/TestsList.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/ListAndUniqueList/TestsList/Usings.cs b/ListAndUniqueList/TestsList/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/ListAndUniqueList/TestsList/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/ListAndUniqueList/TestsUniqueList/TestsUniqueList.cs b/ListAndUniqueList/TestsUniqueList/TestsUniqueList.cs new file mode 100644 index 0000000..b329b10 --- /dev/null +++ b/ListAndUniqueList/TestsUniqueList/TestsUniqueList.cs @@ -0,0 +1,48 @@ +namespace TestsForUniqueList; + +using ListAndUniqueList; + +public class Tests +{ + private UniqueList uniqueList; + + [SetUp] + public void Setup() + { + uniqueList = new UniqueList(); + } + + [Test] + public void UniqueListShouldThrowAnExceptionWhenReceivingARepeatingValueWhenAdding() + { + uniqueList.AddElement(0, 15); + uniqueList.AddElement(1, 10); + Assert.Throws(() => uniqueList.AddElement(2, 15)); + } + + [Test] + public void UniqueListShouldThrowAnExceptionWhenReceivingARepeatingValueWhenChangingValue() + { + uniqueList.AddElement(0, 15); + uniqueList.AddElement(1, 10); + + Assert.That(uniqueList.ReturnValueByPosition(1), Is.EqualTo(10)); + } + + [Test] + public void ChangeValueByPositionWhenValueWithChangeValueShouldWorkCorrectly() + { + uniqueList.AddElement(0, 15); + uniqueList.AddElement(1, 10); + uniqueList.ChangeValueByPosition(1, 10); + } + + [Test] + public void ChangeValueByPositionWhenValueWithChangeValueShouldThrowException() + { + uniqueList.AddElement(0, 15); + uniqueList.AddElement(1, 10); + uniqueList.ChangeValueByPosition(1, 10); + Assert.Throws(() => uniqueList.ChangeValueByPosition(0, 10)); + } +} \ No newline at end of file diff --git a/ListAndUniqueList/TestsUniqueList/TestsUniqueList.csproj b/ListAndUniqueList/TestsUniqueList/TestsUniqueList.csproj new file mode 100644 index 0000000..16345a4 --- /dev/null +++ b/ListAndUniqueList/TestsUniqueList/TestsUniqueList.csproj @@ -0,0 +1,23 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + + + + + + + + diff --git a/ListAndUniqueList/TestsUniqueList/Usings.cs b/ListAndUniqueList/TestsUniqueList/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/ListAndUniqueList/TestsUniqueList/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file