From ea9f44a12c289c12cea5fd3b61c712d78b11771c Mon Sep 17 00:00:00 2001 From: chrisly42 Date: Sat, 7 Dec 2024 06:53:50 +0100 Subject: [PATCH] Day 7 (unoptimized) --- src/Utils.kt | 4 +- src/aoc2024/Day07.kt | 107 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 src/aoc2024/Day07.kt diff --git a/src/Utils.kt b/src/Utils.kt index 0102cf3..81efaae 100644 --- a/src/Utils.kt +++ b/src/Utils.kt @@ -26,8 +26,8 @@ fun Iterable>.chineseRemainder(): Long { fun readInput(name: String) = File("src", "$name.txt") .readLines() -fun String.splitInts(): List = split(" ").filter(String::isNotBlank).map(String::toInt) -fun String.splitLongs(): List = split(" ").filter(String::isNotBlank).map(String::toLong) +fun String.splitInts(vararg del: String = arrayOf(" ")): List = split(*del).filter(String::isNotBlank).map(String::toInt) +fun String.splitLongs(vararg del: String = arrayOf(" ")): List = split(*del).filter(String::isNotBlank).map(String::toLong) fun listOfIntegerLists(input: List): ArrayList> { val output = ArrayList>() diff --git a/src/aoc2024/Day07.kt b/src/aoc2024/Day07.kt new file mode 100644 index 0000000..8680eda --- /dev/null +++ b/src/aoc2024/Day07.kt @@ -0,0 +1,107 @@ +package aoc2024 + +import println +import readInput +import splitLongs +import kotlin.math.pow +import kotlin.math.roundToLong + +/* +--- Day 7: Bridge Repair --- +The Historians take you to a familiar rope bridge over a river in the middle of a jungle. The Chief isn't on this side of the bridge, though; maybe he's on the other side? +When you go to cross the bridge, you notice a group of engineers trying to repair it. (Apparently, it breaks pretty frequently.) You won't be able to cross until it's fixed. +You ask how long it'll take; the engineers tell you that it only needs final calibrations, but some young elephants were playing nearby and stole all the operators from their calibration equations! They could finish the calibrations if only someone could determine which test values could possibly be produced by placing any combination of operators into their calibration equations (your puzzle input). +For example: +190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20 + +Each line represents a single equation. The test value appears before the colon on each line; it is your job to determine whether the remaining numbers can be combined with operators to produce the test value. +Operators are always evaluated left-to-right, not according to precedence rules. Furthermore, numbers in the equations cannot be rearranged. Glancing into the jungle, you can see elephants holding two different types of operators: add (+) and multiply (*). +Only three of the above equations can be made true by inserting operators: + +190: 10 19 has only one position that accepts an operator: between 10 and 19. Choosing + would give 29, but choosing * would give the test value (10 * 19 = 190). +3267: 81 40 27 has two positions for operators. Of the four possible configurations of the operators, two cause the right side to match the test value: 81 + 40 * 27 and 81 * 40 + 27 both equal 3267 (when evaluated left-to-right)! +292: 11 6 16 20 can be solved in exactly one way: 11 + 6 * 16 + 20. + +The engineers just need the total calibration result, which is the sum of the test values from just the equations that could possibly be true. In the above example, the sum of the test values for the three equations listed above is 3749. +Determine which equations could possibly be true. What is their total calibration result? + +*/ +fun main() { + + val inlineTestInput = """ +190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20 +""" + + fun part1(input: List): Long { + var sum = 0L + for (i in input) { + val numbers = i.splitLongs(" ", ":") + val eqres = numbers[0] + val ops = numbers.drop(1) + val combs = (1 shl (ops.size - 1)) + for (t in 0 until combs) { + val res = ops.reduceIndexed { index, acc, l -> if (((1 shl (index - 1)) and t) != 0) acc * l else acc + l } + if (res == eqres) { + sum += eqres + break + } + } + } + return sum + } + + fun part2(input: List): Long { + var sum = 0L + for (i in input) { + val numbers = i.splitLongs(" ", ":") + val eqres = numbers[0] + val ops = numbers.drop(1) + val combs = 3.0.pow(ops.size - 1).toInt() + for (t in 0 until combs) { + val res = ops.reduceIndexed { index, acc, l -> + when ((t / (3.0.pow(index - 1).toInt())) % 3) { + 0 -> acc + l + 1 -> acc * l + 2 -> acc * (10.0.pow(l.toString().length.toDouble()).roundToLong()) + l + else -> throw IllegalArgumentException() + } + } + if (res == eqres) { + sum += eqres + break + } + } + } + return sum + } + + // test if implementation meets criteria from the description, like: + val testInput = inlineTestInput.trim().reader().readLines() + //val testInput = readInput("aoc2024/Day07_test") + val testInputPart1Result = part1(testInput) + println("Part 1 Test: $testInputPart1Result") + val testInputPart2Result = part2(testInput) + println("Part 2 Test: $testInputPart2Result") + check(testInputPart1Result == 3749L) + check(testInputPart2Result == 11387L) + + val input = readInput("aoc2024/Day07") + part1(input).println() + part2(input).println() +}