diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/Bag.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/Bag.kt new file mode 100644 index 0000000..d21a7e4 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/Bag.kt @@ -0,0 +1,35 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.datastructures.bag + +interface Bag { + fun add(elem: T) + fun size(): Int + fun isEmpty(): Boolean + fun clear() + fun map(transform: (T) -> A): Bag + fun forEach(action: (T) -> Unit) +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/LinkedListBag.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/LinkedListBag.kt new file mode 100644 index 0000000..630e557 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/LinkedListBag.kt @@ -0,0 +1,82 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.datastructures.bag + +import arrow.core.None +import arrow.core.Option +import arrow.core.Some +import arrow.core.toOption + +class LinkedListBag() : Bag { + data class Node(val value: A, val next: Option> = None) + + private var head: Option> = None + private var size = 0 + + override fun add(elem: T) { + val node = Node(elem, head).toOption() + head = node + size++ + } + + override fun size(): Int = size + + override fun isEmpty(): Boolean = size == 0 + + override fun clear() { + head = None + size = 0 + } + + override fun map(transform: (T) -> A): Bag { + var newCurrent: Option> = None + var oldCurrent = head + + while (oldCurrent is Some) { + val node = Node(transform(oldCurrent.t.value), newCurrent) + .toOption() + + newCurrent = node + oldCurrent = oldCurrent.t.next + } + + return LinkedListBag(newCurrent, size) + } + + private constructor(head: Option>, size: Int) : this() { + this.head = head + this.size = size + } + + override fun forEach(action: (T) -> Unit) { + var current = head + + while (current is Some) { + action(current.t.value) + current = current.t.next + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/ResizingArrayBag.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/ResizingArrayBag.kt new file mode 100644 index 0000000..c6d3688 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/bag/ResizingArrayBag.kt @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.datastructures.bag + +class ResizingArrayBag(capacity: Int = DEFAULT_CAPACITY) : Bag { + private var bag: Array = arrayOfNulls(capacity) as Array + private var size = 0 + + override fun add(elem: T) { + if (isFull()) + resizeArray(size * RESIZE_FACTOR) + + bag[size++] = elem + } + + private fun isFull(): Boolean = size == bag.size + + private fun resizeArray(capacity: Int) { + bag = bag.copyOf(capacity) + } + + override fun size(): Int = size + + override fun isEmpty(): Boolean = size == 0 + + override fun map(transform: (T) -> A): Bag { + val newBag: Array = arrayOfNulls(size) as Array + + for (i in 0 until size) { + val elem = bag[i] ?: continue + newBag[i] = transform(elem) + } + + return ResizingArrayBag(size, newBag) + } + + private constructor(size: Int, bag: Array) : this() { + this.size = size + this.bag = bag + } + + override fun forEach(action: (T) -> Unit) { + for (elem in bag) + if (elem != null) + action(elem) + } + + override fun clear() { + size = 0 + resizeArray(DEFAULT_CAPACITY) + } + + companion object { + const val DEFAULT_CAPACITY = 2 + const val RESIZE_FACTOR = 2 + } +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/datastructures/bag/LinkedListBagTest.kt b/src/test/kotlin/it/norangeb/algorithms/datastructures/bag/LinkedListBagTest.kt new file mode 100644 index 0000000..92856c3 --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/datastructures/bag/LinkedListBagTest.kt @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.datastructures.bag + +import org.amshove.kluent.`should be equal to` +import org.junit.Before +import org.junit.jupiter.api.Test + +class LinkedListBagTest { + private var bag = LinkedListBag() + + @Before + fun makeBag() { + bag = LinkedListBag() + } + + @Test + fun testAdd() { + bag.size() `should be equal to` 0 + bag.add(1) + bag.size() `should be equal to` 1 + bag.add(1) + bag.size() `should be equal to` 2 + bag.add(1) + bag.size() `should be equal to` 3 + } + + @Test + fun testIsEmpty() { + bag.isEmpty() `should be equal to` true + bag.add(1) + bag.isEmpty() `should be equal to` false + } + + @Test + fun testMap() { + bag.add(1) + bag.add(2) + bag.add(3) + bag.add(4) + bag.add(5) + + bag.map { it * 2 }.size() `should be equal to` 5 + } + + @Test + fun testForEach() { + bag.add(1) + bag.add(2) + bag.add(3) + bag.add(4) + bag.add(5) + + var x = 0 + + bag.forEach { x++ } + + x `should be equal to` 5 + } + + @Test + fun testClear() { + bag.add(1) + bag.add(2) + bag.add(3) + bag.add(4) + bag.add(5) + bag.clear() + + bag.size() `should be equal to` 0 + } +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/datastructures/bag/ResizingArrayBagTest.kt b/src/test/kotlin/it/norangeb/algorithms/datastructures/bag/ResizingArrayBagTest.kt new file mode 100644 index 0000000..747cba9 --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/datastructures/bag/ResizingArrayBagTest.kt @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (c) 2019 norangebit + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package it.norangeb.algorithms.datastructures.bag + +import org.amshove.kluent.`should be equal to` +import org.junit.Before +import org.junit.jupiter.api.Test + +class ResizingArrayBagTest { + private var bag = ResizingArrayBag() + + @Before + fun makeBag() { + bag = ResizingArrayBag() + } + + @Test + fun testAdd() { + bag.size() `should be equal to` 0 + bag.add(1) + bag.size() `should be equal to` 1 + bag.add(1) + bag.size() `should be equal to` 2 + bag.add(1) + bag.size() `should be equal to` 3 + } + + @Test + fun testIsEmpty() { + bag.isEmpty() `should be equal to` true + bag.add(1) + bag.isEmpty() `should be equal to` false + } + + @Test + fun testMap() { + bag.add(1) + bag.add(2) + bag.add(3) + bag.add(4) + bag.add(5) + + bag.map { it * 2 }.size() `should be equal to` 5 + } + + @Test + fun testForEach() { + bag.add(1) + bag.add(2) + bag.add(3) + bag.add(4) + bag.add(5) + + var x = 0 + + bag.forEach { x++ } + + x `should be equal to` 5 + } + + @Test + fun testClear() { + bag.add(1) + bag.add(2) + bag.add(3) + bag.add(4) + bag.add(5) + bag.clear() + + bag.size() `should be equal to` 0 + } +} \ No newline at end of file