From 0bac46d701f657206edee47580a0bd937ba030f4 Mon Sep 17 00:00:00 2001 From: norangebit Date: Thu, 6 Jun 2019 19:14:09 +0200 Subject: [PATCH] add inbalance tree --- .../datastructures/dictionary/RedBlackBST.kt | 90 +++++++++++++ .../it/norangeb/algorithms/exam/Inbalance.kt | 98 ++++++++++++++ .../norangeb/algorithms/exam/InbalanceTest.kt | 125 ++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 src/main/kotlin/it/norangeb/algorithms/datastructures/dictionary/RedBlackBST.kt create mode 100644 src/main/kotlin/it/norangeb/algorithms/exam/Inbalance.kt create mode 100644 src/test/kotlin/it/norangeb/algorithms/exam/InbalanceTest.kt diff --git a/src/main/kotlin/it/norangeb/algorithms/datastructures/dictionary/RedBlackBST.kt b/src/main/kotlin/it/norangeb/algorithms/datastructures/dictionary/RedBlackBST.kt new file mode 100644 index 0000000..64ebf7a --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/datastructures/dictionary/RedBlackBST.kt @@ -0,0 +1,90 @@ +/* + * 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.dictionary + +import arrow.core.Option + +class RedBlackBST, V> : OrderedDictionary { + override fun get(key: K): Option { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun set(key: K, value: V) { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun delete(key: K) { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun contains(key: K): Boolean { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun isEmpty(): Boolean { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun size(): Int { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun max(): Option { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun min(): Option { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun floor(key: K): Option { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun ceiling(key: K): Option { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun select(pos: Int): Option { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun rank(key: K): Int { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun preOrder(transform: (K) -> R) { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun inOrder(transform: (K) -> R) { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } + + override fun postOrder(transform: (K) -> R) { + TODO("not implemented") // To change body of created functions use File | Settings | File Templates. + } +} \ No newline at end of file diff --git a/src/main/kotlin/it/norangeb/algorithms/exam/Inbalance.kt b/src/main/kotlin/it/norangeb/algorithms/exam/Inbalance.kt new file mode 100644 index 0000000..e18ca9f --- /dev/null +++ b/src/main/kotlin/it/norangeb/algorithms/exam/Inbalance.kt @@ -0,0 +1,98 @@ +/* + * 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.exam + +import arrow.core.None +import arrow.core.Option +import arrow.core.toOption +import kotlin.math.abs + +class Inbalance, V> { + + private var root: Option> = None + + operator fun set(key: K, value: V) { + root = set(key, value, root) + } + + private fun set( + key: K, + value: V, + node: Option> + ): Option> = node.fold( + { Node(key, value) }, + { + when { + key == it.key -> it.clone(value = value) + key > it.key -> it.clone(right = set(key, value, it.right)) + else -> it.clone(left = set(key, value, it.left)) + } + }).toOption() + + operator fun get(key: K): Option = get(key, root).map { it.value } + + private fun get( + key: K, + node: Option> + ): Option> = node.flatMap { + when { + key == it.key -> node + key > it.key -> get(key, it.right) + else -> get(key, it.left) + } + } + + fun inbalance(key: K): Option = get(key, root) + .map { computeInbalance(it) } + + private fun computeInbalance(node: Node): Int { + val leftLeaf = node.left.fold({ 0 }, { leaf(it) }) + val rightLeaf = node.right.fold({ 0 }, { leaf(it) }) + + return abs(leftLeaf - rightLeaf) + } + + private fun leaf(node: Node): Int = when { + node.left == None && node.right == None -> 1 + else -> + node.left.fold({ 0 }, { leaf(it) }) + + node.right.fold({ 0 }, { leaf(it) }) + } + + private data class Node( + val key: K, + val value: V, + val left: Option> = None, + val right: Option> = None + ) { + fun clone( + key: K = this.key, + value: V = this.value, + left: Option> = this.left, + right: Option> = this.right + ) = Node(key, value, left, right) + } +} \ No newline at end of file diff --git a/src/test/kotlin/it/norangeb/algorithms/exam/InbalanceTest.kt b/src/test/kotlin/it/norangeb/algorithms/exam/InbalanceTest.kt new file mode 100644 index 0000000..e7764e8 --- /dev/null +++ b/src/test/kotlin/it/norangeb/algorithms/exam/InbalanceTest.kt @@ -0,0 +1,125 @@ +/* + * 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.exam + +import arrow.core.None +import arrow.core.Option +import arrow.core.Some +import org.amshove.kluent.`should equal` +import org.spekframework.spek2.Spek +import org.spekframework.spek2.style.gherkin.Feature + +object InbalanceTest : Spek({ + Feature("inbalance") { + Scenario("get and set") { + val tree by memoized { Inbalance() } + + When("add couple 15-15, 13-13, 23-23, 5-5") { + tree[15] = 15 + tree[13] = 13 + tree[23] = 24 + tree[5] = 5 + } + + Then("tree of 23 should equal 24") { + tree[23] `should equal` Some(24) + } + + Then("tree of 25 should equal None") { + tree[25] `should equal` None + } + + Then("tree of 5 should equal 5") { + tree[5] `should equal` Some(5) + } + + When("add couple 1-1, 17-17, 25-25, 23-23") { + tree[1] = 1 + tree[17] = 17 + tree[25] = 25 + tree[23] = 23 + } + + Then("tree of 23 should equal 23") { + tree[23] `should equal` Some(23) + } + + Then("tree of 25 should equal 25") { + tree[25] `should equal` Some(25) + } + } + + Scenario("inbalance") { + val tree by memoized { Inbalance() } + + Given("tree 15, 23, 7, 18, 25, 21, 22, 20") { + tree[15] = 15 + tree[23] = 23 + tree[7] = 7 + tree[18] = 18 + tree[25] = 25 + tree[21] = 21 + tree[22] = 22 + tree[20] = 20 + tree[10] = 10 + } + + lateinit var inbalance: Option + + When("compute imbalance of 1") { + inbalance = tree.inbalance(1) + } + + Then("inbalance should equal None") { + inbalance `should equal` None + } + + When("compute imbalance of 23") { + inbalance = tree.inbalance(23) + } + + Then("inbalance should equal 1") { + inbalance `should equal` Some(1) + } + + When("compute inbalance of 15") { + inbalance = tree.inbalance(15) + } + + Then("inbalance should equal 2") { + inbalance `should equal` Some(2) + } + + When("compute inbalance of 10") { + inbalance = tree.inbalance(10) + } + + Then("inbalance should equal 0") { + inbalance `should equal` Some(0) + } + } + } +}) \ No newline at end of file