/* * 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 class DescendentsTree, V> { private var root: Option> = None operator fun get(key: K): Option = get(root, key).map { it.value } private fun get( node: Option>, key: K ): Option> = node.flatMap { when { key == it.key -> node key > it.key -> get(it.right, key) else -> get(it.left, key) } } operator fun set(key: K, value: V) { root = set(root, key, value) } private fun set( node: Option>, key: K, value: V ): Option> = node.fold( { Node(key, value) }, { when { key == it.key -> it.clone(value = value) key > it.key -> it.clone(right = set(it.right, key, value)) else -> it.clone(left = set(it.left, key, value)) } } ).toOption() fun descendents(key: K): Option { val parent = get(root, key) var descendents = 0 return parent.map { inOrder(parent) { descendents++ } descendents - 1 } } private fun inOrder(node: Option>, action: (V) -> R) { node.map { inOrder(it.left, action) action(it.value) inOrder(it.right, action) } } 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 = Node(key, value, left, right) } }