diff --git a/src/year2021/day08/Day08.kt b/src/year2021/day08/Day08.kt new file mode 100644 index 0000000..10c9132 --- /dev/null +++ b/src/year2021/day08/Day08.kt @@ -0,0 +1,98 @@ +package year2021.day08 + +import readInput + +class Patterns(private val patterns: MutableList) { + private val segments: List> = listOf( + "abcefg", "cf", "acdeg", "acdfg", "bcdf", "abdfg", "abdefg", "acf", "abcdefg", "abcdfg" + ).map { it.toSet() } + private val mapping: Map> = mapOf( + 2 to listOf(1), 3 to listOf(7), 4 to listOf(4), 7 to listOf(8), 6 to listOf(0, 6, 9), 5 to listOf(2, 3, 5) + ) + + private val usedDigits: MutableList = (0..9).map { false }.toMutableList() + private var decoded: MutableMap> = mutableMapOf() + + constructor(patternsAsString: String) : this(patternsAsString.split(" ").toMutableList()) + + private fun preprocess() { + val toRemove = mutableSetOf() + + patterns.forEach { pattern -> + val options = mapping[pattern.length] ?: listOf() + if (options.size == 1) { + decoded[options.first()] = pattern.toSet() + usedDigits[options.first()] = true + toRemove.add(pattern) + } + } + + toRemove.forEach { patterns.remove(it) } + } + + private fun check(): Boolean = + segments + .indices + .flatMap { i -> segments.indices.map { j -> Pair(i, j) } } + .all { (i, j) -> + segments[i].intersect(segments[j]).size == (decoded[i] ?: emptySet()).intersect( + (decoded[j] ?: emptySet()).toSet() + ).size + } + + private fun resolve(i: Int): Boolean { + if (i == patterns.size) { + return check() + } + + for (possibleDigit in mapping[patterns[i].length]!!) { + if (usedDigits[possibleDigit]) { + continue + } + + decoded[possibleDigit] = patterns[i].toSet() + usedDigits[possibleDigit] = true + + if (resolve(i + 1)) { + return true + } + usedDigits[possibleDigit] = false + } + + return false + } + + fun decode(allDigits: Boolean = false): MutableMap> { + preprocess() + if (allDigits) { + resolve(0) + } + return decoded + } +} + +fun part1(input: List): Int = input.sumOf { entry -> + val (patterns, output) = entry.split(" | ") + val decodedPatterns = Patterns(patterns).decode() + + output.split(" ").map { it.toSet() }.count { decodedPatterns.values.contains(it) } +} + +fun part2(input: List): Int = input.sumOf { entry -> + val (patterns, output) = entry.split(" | ") + val decodedPatterns = Patterns(patterns).decode(true).map { (key, value) -> Pair(value, key) }.toMap() + + output.split(" ").map { it.toSet() }.fold(0) { n, digit -> 10 * n + decodedPatterns[digit]!! }.toLong() +}.toInt() + +fun main() { + val sample = readInput(8, "sample") + val input = readInput(8, "input") + + check(part1(sample) == 26) + println(part1(input)) + + check(part2(listOf("acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf")) == 5353) + check(part2(sample) == 61229) + println(part2(input)) +} diff --git a/src/year2021/day08/sample.txt b/src/year2021/day08/sample.txt new file mode 100644 index 0000000..8614893 --- /dev/null +++ b/src/year2021/day08/sample.txt @@ -0,0 +1,10 @@ +be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe +edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc +fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg +fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb +aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea +fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb +dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe +bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef +egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb +gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce \ No newline at end of file