Skip to content

Instantly share code, notes, and snippets.

@xpepper
Created July 26, 2020 13:11
Show Gist options
  • Save xpepper/df38024e303b86ce33a36039b8540345 to your computer and use it in GitHub Desktop.
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
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