Created
July 26, 2020 13:11
-
-
Save xpepper/df38024e303b86ce33a36039b8540345 to your computer and use it in GitHub Desktop.
given number sequence 1,2,3,4,5,6,7,8,9, find a combination of + and - to split those digits so that the result of the operation equals 100
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlin.math.pow | |
import kotlin.random.Random | |
val digits = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9) | |
fun main() { | |
val random = Random(System.currentTimeMillis()) | |
val validResults = mutableListOf<String>() | |
while (true) { | |
val numbersToSum = StringBuilder() | |
digits.forEach { digit: Int -> | |
when (plusOrMinus(random)) { | |
0 -> addOperator(digit, numbersToSum, "+") | |
1 -> addOperator(digit, numbersToSum, "-") | |
2 -> numbersToSum.append(digit) | |
} | |
} | |
val stringToEval = numbersToSum.toString() | |
val result = eval(stringToEval) | |
if (result == 100.0 && !validResults.contains(stringToEval)) { | |
validResults.add(stringToEval) | |
println("$stringToEval = $result") | |
} | |
} | |
} | |
private fun plusOrMinus(random: Random): Int { | |
return random.nextInt(3) | |
} | |
private fun addOperator(digit: Int, numbersToSum: StringBuilder, operator: String) { | |
if (digit == digits.last()) { | |
numbersToSum.append(digit) | |
} else { | |
numbersToSum.append("$digit $operator ") | |
} | |
} | |
fun eval(string: String): Double { | |
val value = object { | |
var pos = -1 | |
var ch = 0 | |
fun nextChar() { | |
ch = if (++pos < string.length) string[pos].toInt() else -1 | |
} | |
fun eat(charToEat: Int): Boolean { | |
while (ch == ' '.toInt()) nextChar() | |
if (ch == charToEat) { | |
nextChar() | |
return true | |
} | |
return false | |
} | |
fun parse(): Double { | |
nextChar() | |
val x = parseExpression() | |
if (pos < string.length) throw RuntimeException("Unexpected: " + ch.toChar()) | |
return x | |
} | |
fun parseExpression(): Double { | |
var x = parseTerm() | |
while (true) { | |
when { | |
eat('+'.toInt()) -> x += parseTerm() // addition | |
eat('-'.toInt()) -> x -= parseTerm() // subtraction | |
else -> return x | |
} | |
} | |
} | |
fun parseTerm(): Double { | |
var x = parseFactor() | |
while (true) { | |
if (eat('*'.toInt())) x *= parseFactor() // multiplication | |
else if (eat('/'.toInt())) x /= parseFactor() // division | |
else return x | |
} | |
} | |
fun parseFactor(): Double { | |
if (eat('+'.toInt())) return parseFactor() // unary plus | |
if (eat('-'.toInt())) return -parseFactor() // unary minus | |
var x: Double | |
val startPos = pos | |
if (eat('('.toInt())) { // parentheses | |
x = parseExpression() | |
eat(')'.toInt()) | |
} else if (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) { // numbers | |
while (ch >= '0'.toInt() && ch <= '9'.toInt() || ch == '.'.toInt()) nextChar() | |
x = string.substring(startPos, pos).toDouble() | |
} else if (ch >= 'a'.toInt() && ch <= 'z'.toInt()) { // functions | |
while (ch >= 'a'.toInt() && ch <= 'z'.toInt()) nextChar() | |
val func = string.substring(startPos, pos) | |
x = parseFactor() | |
x = | |
if (func == "sqrt") Math.sqrt(x) else if (func == "sin") Math.sin(Math.toRadians(x)) else if (func == "cos") Math.cos( | |
Math.toRadians(x) | |
) else if (func == "tan") Math.tan(Math.toRadians(x)) else throw RuntimeException("Unknown function: $func") | |
} else { | |
throw RuntimeException("Unexpected: " + ch.toChar()) | |
} | |
if (eat('^'.toInt())) x = x.pow(parseFactor()) // exponentiation | |
return x | |
} | |
} | |
return value.parse() | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment