Jelikož byl den 15. naprostá šílenost, tak jsem si řekl, že si určitě najdu nějakou zábavnější činnost než celý víkend od rána do večera sedět u PC ve snaze získat alespoň 1 hvězdičku. Děkuji, ale za tohle mi to opravdu nestojí. Nicméně den 16. se opět vrátil do rozumných mezí, kde obě řešení se mi podařilo najít na první dobrou a to dokonce bez unit testů!
import com.svetylkovo.rojo.Rojo
import com.svetylkovo.rojo.annotations.Group
import com.svetylkovo.rojo.annotations.Regex
import java.io.File
typealias InstructionFunc = (Int, Int, Int) -> Unit
class WristDevice {
val registers = longArrayOf(0, 0, 0, 0)
fun setRegisters(value: LongArray) {
value.copyInto(registers)
}
val instructions: List<InstructionFunc> = listOf(
this::addr,
this::addi,
this::mulr,
this::muli,
this::banr,
this::bani,
this::borr,
this::bori,
this::setr,
this::seti,
this::gtir,
this::gtri,
this::gtrr,
this::eqir,
this::eqri,
this::eqrr
)
val opToInstruction = mutableMapOf<Int, InstructionFunc>()
/*
* Instructions
*/
fun addr(regA: Int, regB: Int, output: Int) {
registers[output] = registers[regA] + registers[regB]
}
fun addi(regA: Int, valueB: Int, output: Int) {
registers[output] = registers[regA] + valueB
}
fun mulr(regA: Int, regB: Int, output: Int) {
registers[output] = registers[regA] * registers[regB]
}
fun muli(regA: Int, valueB: Int, output: Int) {
registers[output] = registers[regA] * valueB
}
fun banr(regA: Int, regB: Int, output: Int) {
registers[output] = registers[regA] and registers[regB]
}
fun bani(regA: Int, valueB: Int, output: Int) {
registers[output] = registers[regA] and valueB.toLong()
}
fun borr(regA: Int, regB: Int, output: Int) {
registers[output] = registers[regA] or registers[regB]
}
fun bori(regA: Int, valueB: Int, output: Int) {
registers[output] = registers[regA] or valueB.toLong()
}
fun setr(regA: Int, ignored: Int, output: Int) {
registers[output] = registers[regA]
}
fun seti(valueA: Int, ignored: Int, output: Int) {
registers[output] = valueA.toLong()
}
fun gtir(valueA: Int, regB: Int, output: Int) {
registers[output] = if (valueA > registers[regB]) 1 else 0
}
fun gtri(regA: Int, valueB: Int, output: Int) {
registers[output] = if (registers[regA] > valueB) 1 else 0
}
fun gtrr(regA: Int, regB: Int, output: Int) {
registers[output] = if (registers[regA] > registers[regB]) 1 else 0
}
fun eqir(valueA: Int, regB: Int, output: Int) {
registers[output] = if (valueA.toLong() == registers[regB]) 1 else 0
}
fun eqri(regA: Int, valueB: Int, output: Int) {
registers[output] = if (registers[regA] == valueB.toLong()) 1 else 0
}
fun eqrr(regA: Int, regB: Int, output: Int) {
registers[output] = if (registers[regA] == registers[regB]) 1 else 0
}
/*
* End of Instructions
*/
fun getMatchingInstructions(sample: Sample) = instructions.filter { instruction ->
setRegisters(sample.input.toLongArray())
instruction(
sample.instruction[1].toInt(),
sample.instruction[2].toInt(),
sample.instruction[3].toInt()
)
registers.contentEquals(sample.output.toLongArray())
}
fun figureOutOpNumbers(samples: List<Sample>) {
val matchingOpsMap = samples.associateBy { it.instruction[0].toInt() }
.mapValues { getMatchingInstructions(it.value) }
while (opToInstruction.size != 16) {
matchingOpsMap.forEach { op, functions ->
val remaining = functions - opToInstruction.values
if (remaining.size == 1) {
opToInstruction += op to remaining.single()
}
}
}
}
fun execute(instruction: Instruction) {
opToInstruction[instruction.op.toInt()]?.let { instructionFunction ->
instructionFunction(
instruction.inputA.toInt(),
instruction.inputB.toInt(),
instruction.outputC.toInt()
)
}
}
}
@Regex("Before:(.+)\\n(.+)\\nAfter: (.+)")
class Sample {
@Group(1)
@Regex("\\d+")
var input: List<Long> = emptyList()
@Group(2)
@Regex("\\d+")
var instruction: List<Long> = emptyList()
@Group(3)
@Regex("\\d+")
var output: List<Long> = emptyList()
}
@Regex("(\\d+).+(\\d+).+(\\d+).+(\\d+)")
class Instruction {
@Group(1)
var op: Long = 0
@Group(2)
var inputA: Long = 0
@Group(3)
var inputB: Long = 0
@Group(4)
var outputC: Long = 0
}
fun main() {
val inputIterator = File("input16.txt").readLines().iterator()
//A
val inputA = inputIterator.asSequence().take(3109).joinToString("\n")
val samples = Rojo.of(Sample::class.java).matchList(inputA)
val wristDeviceA = WristDevice()
val resultA = samples.map { wristDeviceA.getMatchingInstructions(it).count() }
.count { it >= 3 }
println(resultA)
//B
val inputB = inputIterator.asSequence().joinToString("\n")
val instructions = Rojo.of(Instruction::class.java).matchList(inputB)
val wristDeviceB = WristDevice()
wristDeviceB.figureOutOpNumbers(samples)
wristDeviceB.setRegisters(longArrayOf(0, 0, 0, 0))
instructions.forEach { wristDeviceB.execute(it) }
println(wristDeviceB.registers.joinToString(","))
}