Day 9, also refactored the IntCode (or LongCode?) computer to a separate class and added the missing features
This commit is contained in:
196
src/main/kotlin/com/basdado/adventofcode/IntCodeProgram.kt
Normal file
196
src/main/kotlin/com/basdado/adventofcode/IntCodeProgram.kt
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
package com.basdado.adventofcode
|
||||||
|
|
||||||
|
val FULL_OPCODES = mapOf(
|
||||||
|
Pair(1L, OpCode(1L, 3, ::add)),
|
||||||
|
Pair(2L, OpCode(2L, 3, ::multiply)),
|
||||||
|
Pair(3L, OpCode(3L, 1, ::saveInput)),
|
||||||
|
Pair(4L, OpCode(4L, 1, ::writeOutput)),
|
||||||
|
Pair(5L, OpCode(5L, 2, ::jumpIfTrue)),
|
||||||
|
Pair(6L, OpCode(6L, 2, ::jumpIfFalse)),
|
||||||
|
Pair(7L, OpCode(7L, 3, ::lessThan)),
|
||||||
|
Pair(8L, OpCode(8L, 3, ::equals)),
|
||||||
|
Pair(9L, OpCode(9L, 1, ::adjustRelativeBase))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
fun loadProgram(inputPath: String, opCodes: Map<Long, OpCode>, input: LongArray): IntCodeProgram {
|
||||||
|
return IntCodeProgram(loadProgramData(inputPath), input, opCodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadProgramData(inputPath: String): LongArray {
|
||||||
|
return line(inputPath).split(",").map { it.toLong() }.toLongArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Instruction(
|
||||||
|
val paramModes: Array<ParamMode>,
|
||||||
|
val opcode: OpCode,
|
||||||
|
val pos: Int
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun parse(input: Long, pointer: Int, opcodes: Map<Long, OpCode>): Instruction {
|
||||||
|
val opcode = opcodes[input % 100] ?: throw IllegalArgumentException("Unknown opcode for operation $input")
|
||||||
|
val paramModes = Array<ParamMode>(opcode.paramCount) { ParamMode.POSITION }
|
||||||
|
for (i in 0 until opcode.paramCount) {
|
||||||
|
val paramMode = (input % pow10(i + 3)) / pow10(i + 2)
|
||||||
|
paramModes[i] = when (paramMode) {
|
||||||
|
0L -> ParamMode.POSITION
|
||||||
|
1L -> ParamMode.IMMEDIATE
|
||||||
|
2L -> ParamMode.RELATIVE
|
||||||
|
else -> throw IllegalStateException("Unknown parameter mode: $paramMode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Instruction(paramModes, opcode, pointer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ParamMode {
|
||||||
|
POSITION, IMMEDIATE, RELATIVE
|
||||||
|
}
|
||||||
|
|
||||||
|
class IntCodeProgram(val data: LongArray, var inputs: LongArray, val opCodes: Map<Long, OpCode> = FULL_OPCODES,
|
||||||
|
var pointer: Int = 0) {
|
||||||
|
|
||||||
|
private var inputPointer: Int = 0
|
||||||
|
var relativeBase: Long = 0
|
||||||
|
private val outputs = mutableListOf<Long>()
|
||||||
|
var done = false
|
||||||
|
|
||||||
|
fun getValue(instruction: Instruction, i: Int): Long {
|
||||||
|
val param = data[instruction.pos + i + 1]
|
||||||
|
return when(instruction.paramModes[i]) {
|
||||||
|
ParamMode.IMMEDIATE -> param
|
||||||
|
ParamMode.POSITION -> data[param.toInt()]
|
||||||
|
ParamMode.RELATIVE -> data[(relativeBase + param).toInt()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setValue(instruction: Instruction, i: Int, x: Long) {
|
||||||
|
// Setters don't care about parameter modes, they are always "position" based
|
||||||
|
when(instruction.paramModes[i]) {
|
||||||
|
ParamMode.POSITION -> data[(data[instruction.pos + i + 1]).toInt()] = x
|
||||||
|
ParamMode.RELATIVE -> data[(relativeBase + data[instruction.pos + i + 1]).toInt()] = x
|
||||||
|
else -> {
|
||||||
|
println("Calling setter instruction to a parameter in ${instruction.paramModes[i]} mode?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNextInput(): Long {
|
||||||
|
return inputs[inputPointer++]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pushInput(input: Long) {
|
||||||
|
inputs += input
|
||||||
|
}
|
||||||
|
fun getOutputs(): List<Long> {
|
||||||
|
return outputs
|
||||||
|
}
|
||||||
|
|
||||||
|
fun execute() {
|
||||||
|
while (data[pointer] != 99L) {
|
||||||
|
executeUntilOutput()
|
||||||
|
}
|
||||||
|
done = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun executeUntilOutput(): Long? {
|
||||||
|
|
||||||
|
while (data[pointer] != 99L) {
|
||||||
|
|
||||||
|
val instruction = Instruction.parse(data[pointer], pointer, opCodes)
|
||||||
|
val operationResult = instruction.opcode.operation.invoke(instruction, this)
|
||||||
|
|
||||||
|
|
||||||
|
if (operationResult.moveToNextInstruction) {
|
||||||
|
pointer += instruction.opcode.paramCount + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operationResult.output != null) {
|
||||||
|
outputs.add(operationResult.output)
|
||||||
|
return operationResult.output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done = true
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pow10(n: Int): Int {
|
||||||
|
return when (n) {
|
||||||
|
0 -> 1
|
||||||
|
1 -> 10
|
||||||
|
2 -> 100
|
||||||
|
3 -> 1000
|
||||||
|
4 -> 10000
|
||||||
|
5 -> 100000
|
||||||
|
6 -> 1000000
|
||||||
|
7 -> 10000000
|
||||||
|
8 -> 100000000
|
||||||
|
9 -> 1000000000
|
||||||
|
else -> throw IllegalArgumentException("Int overflowing with pow10($n)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
program.setValue(instruction, 2, program.getValue(instruction, 0) + program.getValue(instruction, 1))
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun multiply(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
program.setValue(instruction, 2, program.getValue(instruction, 0) * program.getValue(instruction, 1))
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveInput(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
program.setValue(instruction, 0, program.getNextInput())
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeOutput(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
return OperationResult(output = program.getValue(instruction, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun jumpIfTrue(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
|
||||||
|
return if (program.getValue(instruction, 0) != 0L) {
|
||||||
|
program.pointer = program.getValue(instruction, 1).toInt()
|
||||||
|
OperationResult(moveToNextInstruction = false)
|
||||||
|
} else {
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun jumpIfFalse(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
|
||||||
|
return if (program.getValue(instruction, 0) == 0L) {
|
||||||
|
program.pointer = program.getValue(instruction, 1).toInt()
|
||||||
|
OperationResult(moveToNextInstruction = false)
|
||||||
|
} else {
|
||||||
|
VOID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun lessThan(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
program.setValue(instruction, 2,
|
||||||
|
if (program.getValue(instruction, 0) < program.getValue(instruction, 1)) 1 else 0)
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun equals(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
program.setValue(instruction, 2,
|
||||||
|
if (program.getValue(instruction, 0) == program.getValue(instruction, 1)) 1 else 0)
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
fun adjustRelativeBase(instruction: Instruction, program: IntCodeProgram): OperationResult {
|
||||||
|
program.relativeBase += program.getValue(instruction, 0)
|
||||||
|
return VOID
|
||||||
|
}
|
||||||
|
|
||||||
|
data class OpCode(val code: Long, val paramCount: Int, val operation: (instruction: Instruction, intCodeProgram: IntCodeProgram) -> OperationResult)
|
||||||
|
|
||||||
|
data class OperationResult(val moveToNextInstruction: Boolean = true, val output: Long? = null)
|
||||||
|
|
||||||
|
private val VOID = OperationResult()
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.basdado.adventofcode.day5
|
package com.basdado.adventofcode.day5
|
||||||
|
|
||||||
import com.basdado.adventofcode.line
|
import com.basdado.adventofcode.*
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
const val DAY5_INPUT_PATH = "/day/5/input.txt"
|
const val DAY5_INPUT_PATH = "/day/5/input.txt"
|
||||||
|
|
||||||
@@ -16,22 +15,22 @@ fun main() {
|
|||||||
object Day5 {
|
object Day5 {
|
||||||
|
|
||||||
private val puzzle1OpCodes = mapOf(
|
private val puzzle1OpCodes = mapOf(
|
||||||
Pair(1, OpCode(1, 3, ::add)),
|
Pair(1L, OpCode(1L, 3, ::add)),
|
||||||
Pair(2, OpCode(2, 3, ::multiply)),
|
Pair(2L, OpCode(2L, 3, ::multiply)),
|
||||||
Pair(3, OpCode(3, 1, ::saveInput)),
|
Pair(3L, OpCode(3L, 1, ::saveInput)),
|
||||||
Pair(4, OpCode(4, 1, ::writeOutput))
|
Pair(4L, OpCode(4L, 1, ::writeOutput))
|
||||||
)
|
)
|
||||||
|
|
||||||
val puzzle2OpCodes = puzzle1OpCodes + mapOf(
|
val puzzle2OpCodes = puzzle1OpCodes + mapOf(
|
||||||
Pair(5, OpCode(5, 2, ::jumpIfTrue)),
|
Pair(5L, OpCode(5, 2, ::jumpIfTrue)),
|
||||||
Pair(6, OpCode(6, 2, ::jumpIfFalse)),
|
Pair(6L, OpCode(6, 2, ::jumpIfFalse)),
|
||||||
Pair(7, OpCode(7, 3, ::lessThan)),
|
Pair(7L, OpCode(7, 3, ::lessThan)),
|
||||||
Pair(8, OpCode(8, 3, ::equals))
|
Pair(8L, OpCode(8, 3, ::equals))
|
||||||
)
|
)
|
||||||
|
|
||||||
fun puzzle1() {
|
fun puzzle1() {
|
||||||
|
|
||||||
val program = loadProgram(DAY5_INPUT_PATH, puzzle1OpCodes, intArrayOf(1))
|
val program = loadProgram(DAY5_INPUT_PATH, puzzle1OpCodes, longArrayOf(1))
|
||||||
|
|
||||||
program.execute()
|
program.execute()
|
||||||
|
|
||||||
@@ -40,168 +39,10 @@ object Day5 {
|
|||||||
|
|
||||||
fun puzzle2() {
|
fun puzzle2() {
|
||||||
|
|
||||||
val program = loadProgram(DAY5_INPUT_PATH, puzzle2OpCodes, intArrayOf(5))
|
val program = loadProgram(DAY5_INPUT_PATH, puzzle2OpCodes, longArrayOf(5))
|
||||||
|
|
||||||
program.execute()
|
program.execute()
|
||||||
|
|
||||||
println(program.getOutputs().last())
|
println(program.getOutputs().last())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadProgram(inputPath: String, opCodes: Map<Int, OpCode>, input: IntArray): Program {
|
|
||||||
return Program(loadProgramData(inputPath), opCodes, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadProgramData(inputPath: String): IntArray {
|
|
||||||
return line(inputPath).split(",").map { it.toInt() }.toIntArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
class Instruction(
|
|
||||||
val paramModeImmediate: BooleanArray,
|
|
||||||
val opcode: OpCode,
|
|
||||||
val pos: Int
|
|
||||||
) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun parse(input: Int, pointer: Int, opcodes: Map<Int, OpCode>): Instruction {
|
|
||||||
val opcode = opcodes[input % 100] ?: throw IllegalArgumentException("Unknown opcode for operation $input")
|
|
||||||
val paramModes = BooleanArray(opcode.paramCount)
|
|
||||||
for (i in 0 until opcode.paramCount) {
|
|
||||||
paramModes[i] = (input % pow10(i + 3)) / pow10(i + 2) == 1
|
|
||||||
}
|
|
||||||
return Instruction(paramModes, opcode, pointer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Program(val data: IntArray, val opCodes: Map<Int, OpCode>, var inputs: IntArray,
|
|
||||||
var pointer: Int = 0) {
|
|
||||||
|
|
||||||
private var inputPointer: Int = 0
|
|
||||||
private val outputs = mutableListOf<Int>()
|
|
||||||
var done = false
|
|
||||||
|
|
||||||
fun getValue(instruction: Instruction, i: Int): Int {
|
|
||||||
return if (instruction.paramModeImmediate[i]) {
|
|
||||||
data[instruction.pos + i + 1]
|
|
||||||
} else {
|
|
||||||
data[data[instruction.pos + i + 1]]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setValue(instruction: Instruction, i: Int, x: Int) {
|
|
||||||
// Setters don't care about parameter modes, they are always "position" based
|
|
||||||
data[data[instruction.pos + i + 1]] = x
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNextInput(): Int {
|
|
||||||
return inputs[inputPointer++]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pushInput(input: Int) {
|
|
||||||
inputs += input
|
|
||||||
}
|
|
||||||
fun getOutputs(): List<Int> {
|
|
||||||
return outputs
|
|
||||||
}
|
|
||||||
|
|
||||||
fun execute() {
|
|
||||||
while (data[pointer] != 99) {
|
|
||||||
val output = executeUntilOutput()
|
|
||||||
}
|
|
||||||
done = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun executeUntilOutput(): Int? {
|
|
||||||
|
|
||||||
while (data[pointer] != 99) {
|
|
||||||
|
|
||||||
val instruction = Instruction.parse(data[pointer], pointer, opCodes)
|
|
||||||
val operationResult = instruction.opcode.operation.invoke(instruction, this)
|
|
||||||
|
|
||||||
|
|
||||||
if (operationResult.moveToNextInstruction) {
|
|
||||||
pointer += instruction.opcode.paramCount + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operationResult.output != null) {
|
|
||||||
outputs.add(operationResult.output)
|
|
||||||
return operationResult.output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done = true
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun pow10(n: Int): Int {
|
|
||||||
return when (n) {
|
|
||||||
0 -> 1
|
|
||||||
1 -> 10
|
|
||||||
2 -> 100
|
|
||||||
3 -> 1000
|
|
||||||
4 -> 10000
|
|
||||||
5 -> 100000
|
|
||||||
6 -> 1000000
|
|
||||||
7 -> 10000000
|
|
||||||
8 -> 100000000
|
|
||||||
9 -> 1000000000
|
|
||||||
else -> throw IllegalArgumentException("Int overflowing with pow10($n)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun add(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
program.setValue(instruction, 2, program.getValue(instruction, 0) + program.getValue(instruction, 1))
|
|
||||||
return VOID
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun multiply(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
program.setValue(instruction, 2, program.getValue(instruction, 0) * program.getValue(instruction, 1))
|
|
||||||
return VOID
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveInput(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
program.setValue(instruction, 0, program.getNextInput())
|
|
||||||
return VOID
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun writeOutput(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
return OperationResult(output = program.getValue(instruction, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun jumpIfTrue(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
|
|
||||||
return if (program.getValue(instruction, 0) != 0) {
|
|
||||||
program.pointer = program.getValue(instruction, 1)
|
|
||||||
OperationResult(moveToNextInstruction = false)
|
|
||||||
} else {
|
|
||||||
return VOID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun jumpIfFalse(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
|
|
||||||
return if (program.getValue(instruction, 0) == 0) {
|
|
||||||
program.pointer = program.getValue(instruction, 1)
|
|
||||||
OperationResult(moveToNextInstruction = false)
|
|
||||||
} else {
|
|
||||||
VOID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun lessThan(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
program.setValue(instruction, 2,
|
|
||||||
if (program.getValue(instruction, 0) < program.getValue(instruction, 1)) 1 else 0)
|
|
||||||
return VOID
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun equals(instruction: Instruction, program: Program): OperationResult {
|
|
||||||
program.setValue(instruction, 2,
|
|
||||||
if (program.getValue(instruction, 0) == program.getValue(instruction, 1)) 1 else 0)
|
|
||||||
return VOID
|
|
||||||
}
|
|
||||||
|
|
||||||
data class OpCode(val code: Int, val paramCount: Int, val operation: (instruction: Instruction, program: Program) -> OperationResult)
|
|
||||||
|
|
||||||
data class OperationResult(val moveToNextInstruction: Boolean = true, val output: Int? = null)
|
|
||||||
|
|
||||||
private val VOID = OperationResult()
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.basdado.adventofcode.day7
|
package com.basdado.adventofcode.day7
|
||||||
|
|
||||||
import com.basdado.adventofcode.day5.Day5
|
import com.basdado.adventofcode.IntCodeProgram
|
||||||
|
import com.basdado.adventofcode.loadProgramData
|
||||||
|
|
||||||
const val DAY7_INPUT_PATH = "/day/7/input.txt"
|
const val DAY7_INPUT_PATH = "/day/7/input.txt"
|
||||||
|
|
||||||
@@ -13,45 +14,45 @@ object Day7 {
|
|||||||
|
|
||||||
fun puzzle1() {
|
fun puzzle1() {
|
||||||
|
|
||||||
val programData = Day5.loadProgramData(DAY7_INPUT_PATH)
|
val programData = loadProgramData(DAY7_INPUT_PATH)
|
||||||
var maxOutput = Int.MIN_VALUE
|
var maxOutput = Long.MIN_VALUE
|
||||||
var maxOutputPhases = ""
|
var maxOutputPhases = ""
|
||||||
|
|
||||||
for (A in 0..4) {
|
for (A in 0L..4) {
|
||||||
|
|
||||||
val programA = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(A, 0))
|
val programA = IntCodeProgram(programData.clone(), longArrayOf(A, 0))
|
||||||
programA.execute()
|
programA.execute()
|
||||||
val outputA = programA.getOutputs().last()
|
val outputA = programA.getOutputs().last()
|
||||||
|
|
||||||
for (B in 0..4) {
|
for (B in 0L..4) {
|
||||||
|
|
||||||
if (B == A) continue
|
if (B == A) continue
|
||||||
|
|
||||||
val programB = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(B, outputA))
|
val programB = IntCodeProgram(programData.clone(), longArrayOf(B, outputA))
|
||||||
programB.execute()
|
programB.execute()
|
||||||
val outputB = programB.getOutputs().last()
|
val outputB = programB.getOutputs().last()
|
||||||
|
|
||||||
for (C in 0..4) {
|
for (C in 0L..4) {
|
||||||
|
|
||||||
if (C == A || C == B) continue
|
if (C == A || C == B) continue
|
||||||
|
|
||||||
val programC = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(C, outputB))
|
val programC = IntCodeProgram(programData.clone(), longArrayOf(C, outputB))
|
||||||
programC.execute()
|
programC.execute()
|
||||||
val outputC = programC.getOutputs().last()
|
val outputC = programC.getOutputs().last()
|
||||||
|
|
||||||
for (D in 0..4) {
|
for (D in 0L..4) {
|
||||||
|
|
||||||
if (D == A || D == B || D == C) continue
|
if (D == A || D == B || D == C) continue
|
||||||
|
|
||||||
val programD = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(D, outputC))
|
val programD = IntCodeProgram(programData.clone(), longArrayOf(D, outputC))
|
||||||
programD.execute()
|
programD.execute()
|
||||||
val outputD = programD.getOutputs().last()
|
val outputD = programD.getOutputs().last()
|
||||||
|
|
||||||
for (E in 0..4) {
|
for (E in 0L..4) {
|
||||||
|
|
||||||
if (E == A || E == B || E == C || E == D) continue
|
if (E == A || E == B || E == C || E == D) continue
|
||||||
|
|
||||||
val programE = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(E, outputD))
|
val programE = IntCodeProgram(programData.clone(), longArrayOf(E, outputD))
|
||||||
programE.execute()
|
programE.execute()
|
||||||
val outputE = programE.getOutputs().last()
|
val outputE = programE.getOutputs().last()
|
||||||
// Beautiful
|
// Beautiful
|
||||||
@@ -93,18 +94,18 @@ object Day7 {
|
|||||||
return perms
|
return perms
|
||||||
}
|
}
|
||||||
|
|
||||||
fun executeFeedbackLoop(phaseSettings: IntArray): Int? {
|
fun executeFeedbackLoop(phaseSettings: IntArray): Long? {
|
||||||
|
|
||||||
val programData = Day5.loadProgramData(DAY7_INPUT_PATH)
|
val programData = loadProgramData(DAY7_INPUT_PATH)
|
||||||
|
|
||||||
val ampA = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(phaseSettings[0]))
|
val ampA = IntCodeProgram(programData.clone(), longArrayOf(phaseSettings[0].toLong()))
|
||||||
val ampB = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(phaseSettings[1]))
|
val ampB = IntCodeProgram(programData.clone(), longArrayOf(phaseSettings[1].toLong()))
|
||||||
val ampC = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(phaseSettings[2]))
|
val ampC = IntCodeProgram(programData.clone(), longArrayOf(phaseSettings[2].toLong()))
|
||||||
val ampD = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(phaseSettings[3]))
|
val ampD = IntCodeProgram(programData.clone(), longArrayOf(phaseSettings[3].toLong()))
|
||||||
val ampE = Day5.Program(programData.clone(), Day5.puzzle2OpCodes, intArrayOf(phaseSettings[4]))
|
val ampE = IntCodeProgram(programData.clone(), longArrayOf(phaseSettings[4].toLong()))
|
||||||
|
|
||||||
|
|
||||||
var ampAInput = 0
|
var ampAInput = 0L
|
||||||
var anyAmpRunning = true
|
var anyAmpRunning = true
|
||||||
while (anyAmpRunning) {
|
while (anyAmpRunning) {
|
||||||
ampA.pushInput(ampAInput)
|
ampA.pushInput(ampAInput)
|
||||||
|
|||||||
31
src/main/kotlin/com/basdado/adventofcode/day9/Day9.kt
Normal file
31
src/main/kotlin/com/basdado/adventofcode/day9/Day9.kt
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package com.basdado.adventofcode.day9
|
||||||
|
|
||||||
|
import com.basdado.adventofcode.IntCodeProgram
|
||||||
|
import com.basdado.adventofcode.loadProgramData
|
||||||
|
|
||||||
|
const val DAY9_INPUT_PATH = "/day/9/input.txt"
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
Day9.puzzle1()
|
||||||
|
Day9.puzzle2()
|
||||||
|
}
|
||||||
|
|
||||||
|
object Day9 {
|
||||||
|
|
||||||
|
fun puzzle1() {
|
||||||
|
|
||||||
|
val programData = loadProgramData(DAY9_INPUT_PATH)
|
||||||
|
val program = IntCodeProgram(programData + LongArray(65536), longArrayOf(1))
|
||||||
|
program.execute()
|
||||||
|
println(program.getOutputs())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun puzzle2() {
|
||||||
|
|
||||||
|
val programData = loadProgramData(DAY9_INPUT_PATH)
|
||||||
|
val program = IntCodeProgram(programData + LongArray(65536), longArrayOf(2))
|
||||||
|
program.execute()
|
||||||
|
println(program.getOutputs())
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/main/resources/day/9/input.txt
Normal file
1
src/main/resources/day/9/input.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,396,1029,1101,0,356,1023,1101,401,0,1028,1101,24,0,1008,1101,33,0,1019,1101,35,0,1010,1102,359,1,1022,1102,32,1,1001,1101,37,0,1004,1101,0,31,1009,1101,0,30,1003,1101,28,0,1002,1102,1,36,1014,1102,20,1,1012,1101,21,0,1000,1101,0,22,1015,1102,23,1,1013,1102,1,1,1021,1102,1,39,1007,1102,26,1,1017,1101,0,38,1016,1101,0,437,1024,1102,432,1,1025,1101,0,421,1026,1101,0,29,1005,1101,27,0,1011,1102,1,0,1020,1101,0,25,1018,1101,0,414,1027,1102,34,1,1006,109,6,2108,33,-3,63,1005,63,201,1001,64,1,64,1105,1,203,4,187,1002,64,2,64,109,14,21108,40,40,-6,1005,1014,221,4,209,1105,1,225,1001,64,1,64,1002,64,2,64,109,-21,2102,1,3,63,1008,63,28,63,1005,63,251,4,231,1001,64,1,64,1106,0,251,1002,64,2,64,109,12,2101,0,-3,63,1008,63,21,63,1005,63,275,1001,64,1,64,1105,1,277,4,257,1002,64,2,64,109,-10,1207,1,27,63,1005,63,293,1105,1,299,4,283,1001,64,1,64,1002,64,2,64,109,9,21108,41,42,3,1005,1013,315,1105,1,321,4,305,1001,64,1,64,1002,64,2,64,109,-12,1202,6,1,63,1008,63,37,63,1005,63,347,4,327,1001,64,1,64,1105,1,347,1002,64,2,64,109,29,2105,1,-4,1105,1,365,4,353,1001,64,1,64,1002,64,2,64,109,-17,2108,32,-9,63,1005,63,387,4,371,1001,64,1,64,1105,1,387,1002,64,2,64,109,17,2106,0,1,4,393,1105,1,405,1001,64,1,64,1002,64,2,64,109,1,2106,0,-1,1001,64,1,64,1106,0,423,4,411,1002,64,2,64,109,-13,2105,1,9,4,429,1106,0,441,1001,64,1,64,1002,64,2,64,109,3,21107,42,41,-1,1005,1017,461,1001,64,1,64,1106,0,463,4,447,1002,64,2,64,109,-4,21107,43,44,1,1005,1015,481,4,469,1106,0,485,1001,64,1,64,1002,64,2,64,109,-6,21101,44,0,6,1008,1014,47,63,1005,63,505,1106,0,511,4,491,1001,64,1,64,1002,64,2,64,109,-6,1208,-1,32,63,1005,63,529,4,517,1105,1,533,1001,64,1,64,1002,64,2,64,109,11,1205,7,545,1106,0,551,4,539,1001,64,1,64,1002,64,2,64,109,11,21102,45,1,-7,1008,1017,48,63,1005,63,575,1001,64,1,64,1106,0,577,4,557,1002,64,2,64,109,-8,1206,5,593,1001,64,1,64,1105,1,595,4,583,1002,64,2,64,109,7,1206,-3,609,4,601,1106,0,613,1001,64,1,64,1002,64,2,64,109,-10,2101,0,-6,63,1008,63,39,63,1005,63,635,4,619,1106,0,639,1001,64,1,64,1002,64,2,64,109,-9,1208,0,39,63,1005,63,655,1106,0,661,4,645,1001,64,1,64,1002,64,2,64,109,4,2107,25,0,63,1005,63,681,1001,64,1,64,1105,1,683,4,667,1002,64,2,64,109,-5,2107,31,-2,63,1005,63,701,4,689,1106,0,705,1001,64,1,64,1002,64,2,64,109,19,1205,-1,719,4,711,1105,1,723,1001,64,1,64,1002,64,2,64,109,-17,1201,3,0,63,1008,63,24,63,1005,63,745,4,729,1106,0,749,1001,64,1,64,1002,64,2,64,109,13,21102,46,1,-3,1008,1015,46,63,1005,63,771,4,755,1105,1,775,1001,64,1,64,1002,64,2,64,109,-13,1207,4,32,63,1005,63,793,4,781,1106,0,797,1001,64,1,64,1002,64,2,64,109,7,2102,1,-9,63,1008,63,27,63,1005,63,821,1001,64,1,64,1105,1,823,4,803,1002,64,2,64,109,-18,1201,8,0,63,1008,63,25,63,1005,63,847,1001,64,1,64,1106,0,849,4,829,1002,64,2,64,109,23,21101,47,0,2,1008,1019,47,63,1005,63,871,4,855,1106,0,875,1001,64,1,64,1002,64,2,64,109,-22,1202,5,1,63,1008,63,19,63,1005,63,899,1001,64,1,64,1106,0,901,4,881,4,64,99,21102,27,1,1,21102,1,915,0,1105,1,922,21201,1,25165,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,942,1,0,1105,1,922,22102,1,1,-1,21201,-2,-3,1,21101,0,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,21201,-2,0,-2,109,-3,2105,1,0
|
||||||
Reference in New Issue
Block a user