import java.lang.Math.floor import java.lang.Math.max import javax.script.ScriptEngine import javax.script.ScriptEngineManager data class Expression(val expression: String) fun main(args:Array) { while (true) { println("---------------------------") println("Separate numbers by comma.") print("Enter numbers: ") val inputNumbers = readLine()!!.split(",").map { it.trim().toDouble() } val formula = findFormula(inputNumbers) println("Formula: $formula") println("Pattern: " + continuePattern(formula)) } } private fun findFormula(numbers: List): String { // Find difference between numbers val differences = listOf( numbers[1] - numbers[0], numbers[2] - numbers[1] ) var incrementsByDifference = true var increment = 0.0 if (differences[0] != differences[1]) // If the pattern doesn't increment by difference incrementsByDifference = false else increment = differences[0] // Start-value val nAsExponent = nAsExponent(differences, numbers) val startValueDifference = when { incrementsByDifference -> differences[0] // xn nAsExponent -> getBase(differences) // x^n else -> 1.0 // n^x } val startValue = numbers[0] - startValueDifference // Exponents var base = "n" var exponent = "" if (nAsExponent(differences, numbers)) { base = getBase(differences).cleanRedundancy() + "^" exponent = "n" } else if (!incrementsByDifference) { base = "n^" exponent = getExponent(numbers[1], startValue).cleanRedundancy() } // Add the pieces together var formula = increment.cleanRedundancy() formula += base + exponent + startValue.cleanRedundancy().addSign() return formula } private fun continuePattern(formula: String): String { var output = "" for (i in 1..20) { val expression = Expression(formula.replace("n", i.toString())) output += expression.calculate().cleanRedundancy() + ", " } return output.cleanRedundancy() } fun Double.cleanRedundancy(): String { return when { this == 0.0 -> return "" floor(this) == this -> this.toInt().toString() else -> return this.toString() } } fun String.cleanRedundancy(): String { return if (this.endsWith(", ")) this.substring(0, this.length - 3) else this } fun String.addSign(): String { return if (!this.startsWith("-")) "+" + this else this } fun Expression.calculate(): Double { val addSubSign = max(expression.indexOf("+"), expression.indexOf("-")) val addSub = expression.substring(addSubSign + 1, expression.length).toDouble() val numbers = expression.substring(0, addSubSign) .split(Regex("[*^]")).map { it.toDouble() } if (expression.contains("*")) return numbers[0] * numbers[1] + addSub else if (expression.contains("^")) return Math.pow(numbers[0], numbers[1]) + addSub return 0.0 } private fun getBase(differences: List): Double { return differences[1] / differences[0] } private fun getExponent(secondNumber: Double, startValue: Double): Double { return Math.log(secondNumber - startValue) / Math.log(2.0) } private fun nAsExponent(differences: List, numbers: List): Boolean { val base = getBase(differences) return Math.log(numbers[1] - (base - 1)) / Math.log(base) == 2.0 }