This commit is contained in:
2018-12-16 23:33:59 +01:00
parent f73e6b5c42
commit a4471f5886
4 changed files with 4161 additions and 1 deletions

View File

@@ -3,6 +3,7 @@ package com.basdado.adventofcode
import java.util.Arrays.stream
import java.util.function.Function
import java.util.stream.Collectors
import kotlin.system.measureTimeMillis
const val DAY15_INPUT = "/day/15/input.txt"
@@ -10,7 +11,7 @@ fun main() {
val day = Day15()
day.puzzle1()
day.puzzle2()
println("Puzzle 2: " + measureTimeMillis { day.puzzle2() } + " ms")
}
class Day15 {

View File

@@ -0,0 +1,149 @@
package com.basdado.adventofcode
import java.util.*
import java.util.stream.Collectors
const val DAY16_INPUT = "/day/16/input.txt"
fun main() {
val day = Day16()
day.puzzle1()
day.puzzle2()
}
class Day16 {
fun puzzle1() {
val input = lines(DAY16_INPUT).collect(Collectors.toList())
val beforeRegex = Regex("""Before:\s+\[(\d+), (\d+), (\d+), (\d+)\]""")
val afterRegex = Regex("""After:\s+\[(\d+), (\d+), (\d+), (\d+)\]""")
var result = 0;
val iterator = input.iterator()
while(iterator.hasNext()) {
val line = iterator.next()
val beforeMatch = beforeRegex.matchEntire(line)
if (beforeMatch != null) {
val regs = beforeMatch.groupValues.stream().skip(1).map { it.toInt() }.collect(Collectors.toList<Int>()).toIntArray()
val operationParams= iterator.next().split(Regex("""\s+""")).map { it.toInt() }
val afterRegs = afterRegex.matchEntire(iterator.next())!!.groupValues.stream().skip(1).map { it.toInt() }.collect(Collectors.toList()).toIntArray()
val matchingOpcodes = mutableListOf<Opcode>()
for (opcode in Opcode.values()) {
val opRegs = regs.clone()
opcode.operation.invoke(opRegs, operationParams[1], operationParams[2], operationParams[3])
if (Arrays.equals(afterRegs, opRegs)) {
matchingOpcodes.add(opcode)
}
}
if (matchingOpcodes.size >= 3) {
// println(matchingOpcodes)
result++
}
}
iterator.next()
}
println(result)
}
fun puzzle2() {
val input = lines(DAY16_INPUT).collect(Collectors.toList())
val beforeRegex = Regex("""Before:\s+\[(\d+), (\d+), (\d+), (\d+)\]""")
val afterRegex = Regex("""After:\s+\[(\d+), (\d+), (\d+), (\d+)\]""")
var result = 0
val opcodeIds = (0 until Opcode.values().size).map { Pair(it, Opcode.values().toMutableSet()) }.toMap()
val iterator = input.iterator()
var emptyLineCount = 0
while(iterator.hasNext()) {
val line = iterator.next()
if (line.isBlank()) {
emptyLineCount++
} else {
emptyLineCount = 0
}
if (emptyLineCount >= 3) {
break
}
val beforeMatch = beforeRegex.matchEntire(line)
if (beforeMatch != null) {
val regs = beforeMatch.groupValues.stream().skip(1).map { it.toInt() }.collect(Collectors.toList<Int>()).toIntArray()
val instruction= iterator.next().split(Regex("""\s+""")).map { it.toInt() }
val afterRegs = afterRegex.matchEntire(iterator.next())!!.groupValues.stream().skip(1).map { it.toInt() }.collect(Collectors.toList()).toIntArray()
val matchingOpcodes = mutableListOf<Opcode>()
for (opcode in Opcode.values()) {
val opRegs = regs.clone()
opcode.operation.invoke(opRegs, instruction[1], instruction[2], instruction[3])
if (Arrays.equals(afterRegs, opRegs)) {
matchingOpcodes.add(opcode)
}
}
opcodeIds[instruction[0]]!!.removeAll { !matchingOpcodes.contains(it) }
}
}
// println(opcodeIds)
// At this point, we've excluded many options from the opcode Ids
// The next step is to actually assign the opcodeIds, so we find the opcodes for which we have a unique mapping,
// and eliminate those from the options, until we have a complete one-to-one mapping
var opcodesAssigned = mutableMapOf<Int, Opcode>()
while(!opcodesAssigned.values.containsAll(Opcode.values().toList())) {
val opcodeToAssign = opcodeIds.entries.find { it.value.size == 1 && !opcodesAssigned.containsKey(it.key) }!!;
val opcodeTaken = opcodeToAssign.value.first()
opcodeIds.values.filter { it.size > 1 }.forEach { it.removeAll { opcode -> opcode == opcodeTaken } }
opcodesAssigned.put(opcodeToAssign.key, opcodeToAssign.value.first())
// println(opcodeIds)
}
println(opcodeIds)
// Now the program (the previous loop only read until the program starts
val regs = IntArray(4) {0}
while(iterator.hasNext()) {
val line = iterator.next()
val instruction= line.split(Regex("""\s+""")).map { it.toInt() }
// println(line)
opcodesAssigned[instruction[0]]!!.operation.invoke(regs, instruction[1], instruction[2], instruction[3])
}
println(regs.joinToString(" "))
}
enum class Opcode(val operation: (IntArray, Int, Int, Int) -> Unit) {
ADDR({regs, a, b, c -> regs[c] = regs[a] + regs[b]}),
ADDI({regs, a, b, c -> regs[c] = regs[a] + b}),
MULR({regs, a, b, c -> regs[c] = regs[a] * regs[b]}),
MULI({regs, a, b, c -> regs[c] = regs[a] * b}),
BANR({regs, a, b, c -> regs[c] = regs[a] and regs[b]}),
BANI({regs, a, b, c -> regs[c] = regs[a] and b}),
BORR({regs, a, b, c -> regs[c] = regs[a] or regs[b]}),
BORI({regs, a, b, c -> regs[c] = regs[a] or b}),
SETR({regs, a, b, c -> regs[c] = regs[a]}),
SETI({regs, a, b, c -> regs[c] = a}),
GTIR({regs, a, b, c -> regs[c] = if (a > regs[b]) 1 else 0}),
GTRI({regs, a, b, c -> regs[c] = if (regs[a] > b) 1 else 0}),
GTRR({regs, a, b, c -> regs[c] = if (regs[a] > regs[b]) 1 else 0}),
EQIR({regs, a, b, c -> regs[c] = if (a == regs[b]) 1 else 0}),
EQRI({regs, a, b, c -> regs[c] = if (regs[a] == b) 1 else 0}),
EQRR({regs, a, b, c -> regs[c] = if (regs[a] == regs[b]) 1 else 0}),
}
}

View File

@@ -0,0 +1,4 @@
Before: [3, 2, 1, 1]
9 2 1 2
After: [3, 2, 2, 1]

File diff suppressed because it is too large Load Diff