1+ package de.ronny_h.aoc.year2015.day07
2+
3+ import de.ronny_h.aoc.AdventOfCode
4+ import de.ronny_h.aoc.extensions.isInt
5+ import de.ronny_h.aoc.year2015.day07.Operator.BinaryOperator
6+ import de.ronny_h.aoc.year2015.day07.Operator.UnaryOperator
7+ import de.ronny_h.aoc.year2015.day07.OperatorOutput.NoSignal
8+ import de.ronny_h.aoc.year2015.day07.OperatorOutput.ValueOutput
9+
10+ fun main () = SomeAssemblyRequired ().run (956 , 40149 )
11+
12+ class SomeAssemblyRequired : AdventOfCode <Int >(2015 , 7 ) {
13+
14+ override fun part1 (input : List <String >): Int = input
15+ .map(::parse)
16+ .calculateSignalForA()
17+
18+ private fun List<Operation>.calculateSignalForA (): Int {
19+ var operations = this
20+ val values = mutableMapOf<String , UShort >()
21+ while (values[" a" ] == null ) {
22+ val remainingOperations = buildList {
23+ operations.forEach {
24+ val result = it.execute(values)
25+ if (result.out is ValueOutput ) {
26+ values.put(result.wire, result.out .value)
27+ } else {
28+ this .add(it)
29+ }
30+ }
31+ }
32+ operations = remainingOperations
33+ }
34+ return values.getValue(" a" ).toInt()
35+ }
36+
37+ fun parse (line : String ): Operation {
38+ val (lhs, rhs) = line.split(" -> " )
39+ val operation = lhs.split(" " )
40+ return when (operation.size) {
41+ 1 -> if (operation.first().isInt()) {
42+ Scalar (operation.first().toUShort(), rhs)
43+ } else {
44+ ReWire (operation.first(), rhs)
45+ }
46+
47+ 2 -> UnaryOperation (operation[1 ], UnaryOperator .valueOf(operation.first()), rhs)
48+ 3 -> BinaryOperation (operation[0 ], operation[2 ], BinaryOperator .valueOf(operation[1 ]), rhs)
49+ else -> error(" invalid operation: $operation " )
50+ }
51+ }
52+
53+ override fun part2 (input : List <String >): Int {
54+ val signalOfA = part1(input)
55+ val operations = input.map(::parse)
56+ .filter { it !is Scalar || it.out != " b" } + Scalar (signalOfA.toUShort(), " b" )
57+ return operations.calculateSignalForA()
58+ }
59+ }
60+
61+
62+ sealed interface Operation {
63+ fun execute (values : Map <String , UShort >): Output
64+ }
65+
66+ data class Scalar (val value : UShort , val out : String ) : Operation {
67+ override fun execute (values : Map <String , UShort >) = Output (out , ValueOutput (value))
68+ }
69+
70+ data class ReWire (val from : String , val out : String ) : Operation {
71+ override fun execute (values : Map <String , UShort >) = Output (out , values[from]?.let { ValueOutput (it) } ? : NoSignal )
72+ }
73+
74+ data class UnaryOperation (val operand : String , val operator : UnaryOperator , val out : String ) : Operation {
75+ override fun execute (values : Map <String , UShort >) = Output (out , operator .execute(values, operand))
76+ }
77+
78+ data class BinaryOperation (val op1 : String , val op2 : String , val operator : BinaryOperator , val out : String ) :
79+ Operation {
80+ override fun execute (values : Map <String , UShort >) = Output (out , operator .execute(values, op1, op2))
81+ }
82+
83+
84+ sealed interface Operator {
85+ fun execute (values : Map <String , UShort >, vararg operands : String ): OperatorOutput
86+
87+ enum class BinaryOperator : Operator {
88+ AND {
89+ override fun execute (values : Map <String , UShort >, vararg operands : String ) =
90+ execute(operands, values) { a, b -> a and b }
91+ },
92+ OR {
93+ override fun execute (values : Map <String , UShort >, vararg operands : String ) =
94+ execute(operands, values) { a, b -> a or b }
95+ },
96+ RSHIFT {
97+ override fun execute (values : Map <String , UShort >, vararg operands : String ) =
98+ execute(operands, values) { a, b -> (a.toInt() shr b.toInt()).toUShort() }
99+ },
100+ LSHIFT {
101+ override fun execute (values : Map <String , UShort >, vararg operands : String ) =
102+ execute(operands, values) { a, b -> (a.toInt() shl b.toInt()).toUShort() }
103+ };
104+
105+ fun execute (
106+ operands : Array <out String >,
107+ values : Map <String , UShort >,
108+ operation : (UShort , UShort ) -> UShort
109+ ): OperatorOutput {
110+ require(operands.size == 2 ) { " invalid number of operands for AND: $operands " }
111+ fun valueOfParameter (idx : Int ): UShort? =
112+ if (operands[idx].isInt()) operands[idx].toUShort() else values[operands[idx]]
113+
114+ val op1 = valueOfParameter(0 )
115+ val op2 = valueOfParameter(1 )
116+ if (op1 == null || op2 == null ) {
117+ return NoSignal
118+ }
119+ return ValueOutput (operation(op1, op2))
120+ }
121+ }
122+
123+ enum class UnaryOperator : Operator {
124+ NOT {
125+ override fun execute (values : Map <String , UShort >, vararg operands : String ): OperatorOutput {
126+ require(operands.size == 1 ) { " invalid number of operands for unary operator NOT: $operands " }
127+ return values[operands.first()]?.let { ValueOutput (it.inv ()) } ? : NoSignal
128+ }
129+ }
130+ }
131+ }
132+
133+ data class Output (val wire : String , val out : OperatorOutput )
134+
135+ sealed interface OperatorOutput {
136+ data class ValueOutput (val value : UShort ) : OperatorOutput
137+ object NoSignal : OperatorOutput
138+ }
0 commit comments