/* * 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 MaxWidthTree, 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 getMaxWidth(): Int { val count = Array(100) { 0 } val level = 0 computeWidth(root, count, level) return count[getMax(count)] } private fun computeWidth( node: Option>, count: Array, level: Int ) { node.map { count[level]++ computeWidth(it.left, count, level + 1) computeWidth(it.right, count, level + 1) } } private fun getMax(count: Array): Int { var maxIndex = 0 count.forEachIndexed { index, i -> if (i > count[maxIndex]) maxIndex = index } return maxIndex } 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) } }