From f9d26d973864b8699e57a8b7c7c0195acab76f5d Mon Sep 17 00:00:00 2001 From: norangebit Date: Sun, 10 Mar 2019 17:47:40 +0100 Subject: [PATCH] Queue & Stack Add Queue and Stack, implemented with a resizing array --- .../algorithms/datastructures/queue/Queue.kt | 38 +++++ .../queue/ResizingArrayQueue.kt | 133 ++++++++++++++++ .../stack/ResizingArrayStack.kt | 111 +++++++++++++ .../algorithms/datastructures/stack/Stack.kt | 39 +++++ .../datastructures/queue/MeasureTime.kt | 75 +++++++++ .../queue/ResizingArrayQueueTest.kt | 139 +++++++++++++++++ .../datastructures/stack/MeasureTime.kt | 75 +++++++++ .../stack/ResizingArrayStackTest.kt | 147 ++++++++++++++++++ 8 files changed, 757 insertions(+) create mode 100644 src/main/kotlin/it/norangeb/algorithms/datastructures/queue/Queue.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueue.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStack.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/datastructures/stack/Stack.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/datastructures/queue/MeasureTime.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueueTest.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/datastructures/stack/MeasureTime.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStackTest.kt diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/queue/Queue.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/queue/Queue.kt new file mode 100644 index 0000000..095ca0c --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/queue/Queue.kt @@ -0,0 +1,38 @@ +/* + * 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.queue + +import arrow.core.Option + +interface Queue { + fun enqueue(elem: T) + fun dequeue(): Option + fun isEmpty(): Boolean + fun size(): Int + fun clean() + fun map(transform: (T) -> A): Queue + fun forEach(action: (T) -> Unit) +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueue.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueue.kt new file mode 100644 index 0000000..2cdc28a --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueue.kt @@ -0,0 +1,133 @@ +/* + * 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.queue + +import arrow.core.None +import arrow.core.Option +import arrow.core.toOption + +class ResizingArrayQueue(capacity: Int = DEFAULT_CAPACITY) : Queue { + private var queue: Array = arrayOfNulls(capacity) as Array + private var size = 0 + private var tail = 0 + private var head = 0 + + override fun isEmpty(): Boolean = size == 0 + + private fun isFull(): Boolean = queue.size == size + + override fun size(): Int = size + + override fun enqueue(elem: T) { + if (isFull()) + resizeArray(size * RESIZE_FACTOR) + + queue[tail] = elem + tail = (tail + 1) % queue.size + size++ + } + + override fun dequeue(): Option { + if (isEmpty()) + return None + + val elem = queue[head] + queue[head] = null + head = (head + 1) % queue.size + size-- + + if (isOneQuarterFull()) + resizeArray(queue.size / RESIZE_FACTOR) + + return elem.toOption() + } + + private fun resizeArray(capacity: Int) { + val copy: Array = arrayOfNulls(capacity) as Array + + when { + head >= tail -> { + for (i in head until queue.size) + copy[i - head] = queue[i] + + val alreadyInsert = queue.size - head + + for (i in 0 until tail) + copy[i + alreadyInsert] = queue[i] + } + + else -> + for (i in head until tail) + copy[i - head] = queue[i] + } + + queue = copy + head = 0 + tail = size + } + + private fun isOneQuarterFull(): Boolean = size == queue.size / 4 && + size > 0 + + override fun forEach(action: (T) -> Unit) { + for (elem in queue) + if (elem != null) + action(elem) + } + + override fun map(transform: (T) -> A): Queue { + val transformedQueue: Array = arrayOfNulls(queue.size) as Array + + for (i in 0 until queue.size) { + val elem = queue[i] + if (elem == null) + transformedQueue[i] = null + else + transformedQueue[i] = transform(elem) + } + + return ResizingArrayQueue(transformedQueue, head, tail, size) + } + + override fun clean() { + queue = arrayOfNulls(DEFAULT_CAPACITY) as Array + size = 0 + tail = 0 + head = 0 + } + + private constructor(queue: Array, head: Int, tail: Int, size: Int) : this() { + this.queue = queue + this.head = head + this.tail = tail + this.size = size + } + + companion object { + const val RESIZE_FACTOR = 2 + const val DEFAULT_CAPACITY = 2 + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStack.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStack.kt new file mode 100644 index 0000000..3cb4fac --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStack.kt @@ -0,0 +1,111 @@ +/* + * 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.stack + +import arrow.core.None +import arrow.core.Option +import arrow.core.toOption + +class ResizingArrayStack(capacity: Int = DEFAULT_CAPACITY) : Stack { + private var stack: Array = arrayOfNulls(capacity) as Array + private var size = 0 + + override fun isEmpty(): Boolean = size == 0 + + private fun isFull(): Boolean = size == stack.size + + override fun size(): Int = size + + override fun peek(): Option = if (size == 0) + None + else + stack[size - 1].toOption() + + override fun pop(): Option { + val elem = peek() + + if (elem is None) + return elem + + stack[--size] = null + + if (isOneQuarterFull()) + resizeArray(stack.size / RESIZE_FACTOR) + + return elem + } + + override fun push(elem: T) { + if (isFull()) + resizeArray(size * RESIZE_FACTOR) + + stack[size++] = elem + } + + private fun resizeArray(capacity: Int) { + stack = stack.copyOf(capacity) + } + + private fun isOneQuarterFull(): Boolean { + return size > 0 && + size == stack.size / 4 + } + + override fun forEach(action: (T) -> Unit) { + for (elem in stack) + if (elem != null) + action(elem) + } + + override fun map(transform: (T) -> A): Stack { + val transformedStack: Array = arrayOfNulls(stack.size) as Array + + for (i in 0 until stack.size) { + val elem = stack[i] + if (elem == null) + transformedStack[i] = null + else + transformedStack[i] = transform(elem) + } + + return ResizingArrayStack(transformedStack, size) + } + + override fun clean() { + stack = arrayOfNulls(DEFAULT_CAPACITY) as Array + size = 0 + } + + private constructor(stack: Array, size: Int) : this() { + this.stack = stack + this.size = size + } + + companion object { + const val RESIZE_FACTOR = 2 + const val DEFAULT_CAPACITY = 2 + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/stack/Stack.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/stack/Stack.kt new file mode 100644 index 0000000..810cdf8 --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/stack/Stack.kt @@ -0,0 +1,39 @@ +/* + * 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.stack + +import arrow.core.Option + +interface Stack { + fun push(elem: T) + fun pop(): Option + fun peek(): Option + fun size(): Int + fun isEmpty(): Boolean + fun clean() + fun map(transform: (T) -> A): Stack + fun forEach(action: (T) -> Unit) +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/datastructures/queue/MeasureTime.kt b/src/test/kotlin/it/norangeb/algorithms/datastructures/queue/MeasureTime.kt new file mode 100644 index 0000000..1b00dda --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/datastructures/queue/MeasureTime.kt @@ -0,0 +1,75 @@ +/* + * 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.queue + +import org.koin.dsl.module.module +import org.koin.standalone.KoinComponent +import org.koin.standalone.StandAloneContext.startKoin +import org.koin.standalone.inject +import java.io.PrintStream +import kotlin.random.Random +import kotlin.system.measureNanoTime + +fun main(args: Array) { + startKoin(listOf(queueModule)) + + val outEnqueueData = PrintStream(args[0]) + val outEnDeQueueData = PrintStream(args[1]) + + TimeMeasure().run(outEnqueueData, outEnDeQueueData) +} + +val queueModule = module { + single { ResizingArrayQueue() as Queue } +} + +class TimeMeasure : KoinComponent { + private val queue: Queue by inject() + + fun run(outEnqueueData: PrintStream, outEnDeQueueData: PrintStream) { + (0..100000).map { + measureNanoTime { + queue.enqueue(1) + } + }.forEach { + outEnqueueData.println(it) + } + + val random = Random(System.currentTimeMillis()) + queue.clean() + + (0..100000).map { + measureNanoTime { + if (random.nextBoolean()) + queue.enqueue(1) + else + queue.dequeue() + } + }.forEach { + outEnDeQueueData.println(it) + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueueTest.kt b/src/test/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueueTest.kt new file mode 100644 index 0000000..1a2688a --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/datastructures/queue/ResizingArrayQueueTest.kt @@ -0,0 +1,139 @@ +/* + * 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.queue + +import arrow.core.None +import arrow.core.getOrElse +import org.amshove.kluent.`should be equal to` +import org.junit.jupiter.api.Test + +class ResizingArrayQueueTest { + + @Test + fun testEnqueue() { + val queue = ResizingArrayQueue() + queue.size() `should be equal to` 0 + queue.enqueue(1) + queue.size() `should be equal to` 1 + queue.enqueue(1) + queue.size() `should be equal to` 2 + } + + @Test + fun testIsEmpty() { + val queue = ResizingArrayQueue() + + queue.isEmpty() `should be equal to` true + queue.enqueue(1) + queue.isEmpty() `should be equal to` false + } + + @Test + fun testDequeue() { + val queue = ResizingArrayQueue() + + queue.size() `should be equal to` 0 + (queue.dequeue() is None) `should be equal to` true + queue.enqueue(1) + queue.dequeue().getOrElse { 0 } `should be equal to` 1 + queue.size() `should be equal to` 0 + } + + @Test + fun testIncreaseSize() { + val queue = ResizingArrayQueue() + + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + queue.enqueue(4) + queue.enqueue(5) + } + + @Test + fun testDecreaseSize() { + val queue = ResizingArrayQueue() + + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + queue.enqueue(4) + queue.enqueue(5) + + queue.dequeue() + queue.dequeue() + queue.dequeue() + queue.dequeue() + queue.dequeue() + } + + @Test + fun testMap() { + val queue = ResizingArrayQueue() + + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + queue.enqueue(4) + queue.enqueue(5) + + val newQueue = queue.map { it * 2 } as ResizingArrayQueue + + newQueue.size() `should be equal to` 5 + newQueue.dequeue().getOrElse { 0 } `should be equal to` 2 + newQueue.dequeue().getOrElse { 0 } `should be equal to` 4 + newQueue.dequeue().getOrElse { 0 } `should be equal to` 6 + newQueue.dequeue().getOrElse { 0 } `should be equal to` 8 + newQueue.dequeue().getOrElse { 0 } `should be equal to` 10 + } + + @Test + fun testForEach() { + val queue = ResizingArrayQueue() + + queue.enqueue(1) + queue.enqueue(2) + queue.enqueue(3) + queue.enqueue(4) + queue.enqueue(5) + + var x = 0 + queue.forEach { x++ } + + x `should be equal to` 5 + } + + @Test + fun testClean() { + val queue = ResizingArrayQueue() + + queue.enqueue(1) + queue.enqueue(2) + queue.clean() + + queue.size() `should be equal to` 0 + } +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/datastructures/stack/MeasureTime.kt b/src/test/kotlin/it/norangeb/algorithms/datastructures/stack/MeasureTime.kt new file mode 100644 index 0000000..dc0cc2f --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/datastructures/stack/MeasureTime.kt @@ -0,0 +1,75 @@ +/* + * 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.stack + +import org.koin.dsl.module.module +import org.koin.standalone.KoinComponent +import org.koin.standalone.inject +import org.koin.standalone.StandAloneContext.startKoin +import java.io.PrintStream +import kotlin.random.Random +import kotlin.system.measureNanoTime + +fun main(args: Array) { + startKoin(listOf(stackModule)) + + val outPushData = PrintStream(args[0]) + val outPushPopData = PrintStream(args[1]) + + MeasureTime().run(outPushData, outPushPopData) +} + +val stackModule = module { + single { ResizingArrayStack() as Stack } +} + +class MeasureTime : KoinComponent { + private val stack: Stack by inject() + + fun run(outPushData: PrintStream, outPushPopData: PrintStream) { + (0..100000).map { + measureNanoTime { + stack.push(1) + } + }.forEach { + outPushData.println(it) + } + + val random = Random(System.currentTimeMillis()) + stack.clean() + + (0..100000).map { + measureNanoTime { + if (random.nextBoolean()) + stack.push(1) + else + stack.pop() + } + }.forEach { + outPushPopData.println(it) + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStackTest.kt b/src/test/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStackTest.kt new file mode 100644 index 0000000..b4142e1 --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/datastructures/stack/ResizingArrayStackTest.kt @@ -0,0 +1,147 @@ +/* + * 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.stack + +import arrow.core.None +import arrow.core.getOrElse +import org.amshove.kluent.`should be equal to` +import org.junit.jupiter.api.Test + +class ResizingArrayStackTest { + + @Test + fun testPush() { + val stack = ResizingArrayStack() + + stack.size() `should be equal to` 0 + stack.push(1) + stack.size() `should be equal to` 1 + } + + @Test + fun testIsEmpty() { + val stack = ResizingArrayStack() + + stack.isEmpty() `should be equal to` true + stack.push(1) + stack.isEmpty() `should be equal to` false + } + + @Test + fun testPeek() { + val stack = ResizingArrayStack() + + (stack.peek() is None) `should be equal to` true + stack.push(1) + (stack.peek().getOrElse { 0 }) `should be equal to` 1 + stack.size() `should be equal to` 1 + } + + @Test + fun testPop() { + val stack = ResizingArrayStack() + + (stack.pop() is None) `should be equal to` true + stack.push(1) + (stack.pop().getOrElse { 0 }) `should be equal to` 1 + stack.size() `should be equal to` 0 + } + + @Test + fun testIncrease() { + val stack = ResizingArrayStack() + + stack.push(1) + stack.push(2) + stack.push(3) + stack.push(4) + stack.push(5) + } + + @Test + fun testDescrese() { + val stack = ResizingArrayStack() + + stack.push(1) + stack.push(2) + stack.push(3) + stack.push(4) + stack.push(5) + + stack.pop() + stack.pop() + stack.pop() + stack.pop() + stack.pop() + } + + @Test + fun testMap() { + val stack = ResizingArrayStack() + + stack.push(1) + stack.push(2) + stack.push(3) + stack.push(4) + stack.push(5) + + val newStack = stack.map { it * 2 } as ResizingArrayStack + + newStack.size() `should be equal to` 5 + newStack.pop().getOrElse { 0 } `should be equal to` 10 + newStack.pop().getOrElse { 0 } `should be equal to` 8 + newStack.pop().getOrElse { 0 } `should be equal to` 6 + newStack.pop().getOrElse { 0 } `should be equal to` 4 + newStack.pop().getOrElse { 0 } `should be equal to` 2 + } + + @Test + fun testForEach() { + val stack = ResizingArrayStack() + + stack.push(1) + stack.push(2) + stack.push(3) + stack.push(4) + stack.push(5) + + var x = 0 + stack.forEach { x++ } + + x `should be equal to` 5 + } + + @Test + fun testClean() { + val stack = ResizingArrayStack() + + stack.push(1) + stack.push(2) + stack.clean() + + stack.size() `should be equal to` 0 + } +}