-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day5.kt
150 lines (140 loc) · 5.24 KB
/
Day5.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package aoc2019.day05
import java.io.BufferedReader
import java.io.FileReader
import java.io.IOException
import java.util.*
// 1: sum values at addresses (1) and (2), stores result at address (3)
// 2: multiply values at addresses (1) and (2), stores result at address (3)
// 3: read input and save it at address (1)
// 4: output value of address (1)
// 5: (1) != 0 set the pointer to the value of (2)
// 6: (1) == 0 set the pointer to the value of (2)
// 7: ((1) < (2) ? store 1 : store 0 ) at value of (3)
// 8: ((1) == (2) ? store 1 : store 0 ) at value of (3)
// 0 = position mode
// 1 = immediate mode
// Parameters that an instruction writes to will never be in immediate mode.
// PARAMETER MODE DETAILS:
// - Immediate mode for 4 (104) should output the value of the parameter (e.g. 104,0 -> out: 0). Otherwise it should output the
// value at index 0 (e.g. 3,...,104,0 -> out: 3)
// - 5,6: 105 - (1) and (2) can be in immediate mode
// - 7,8: 1107 - only (1) and (2) can be in immediate mode
// The pointer should increment based on the number of parameters (e.g. 4 for Codes 1 and 2, 2 for Codes 3 and 4),
// except for 5 and 6 where the pointer is updated as described
fun readInput(input: String): ArrayList<Int> {
val list = ArrayList<Int>()
val reader: BufferedReader
try {
reader = BufferedReader(FileReader(input))
var line = reader.readLine()
while (line != null) {
Arrays.stream(line.split(",").toTypedArray()).map { s: String -> s.toInt() }
.forEachOrdered { e: Int? -> list.add(e!!) }
line = reader.readLine()
}
reader.close()
} catch (e: IOException) {
e.printStackTrace()
}
return list
}
fun processInput(numbers: ArrayList<Int>, input: Int): Int {
var i = 0
val outputBuilder = StringBuilder()
while (i < numbers.size) {
val opCode = numbers[i]
if (opCode == 99) {
break
}
val output = processParameterMode(numbers, i, opCode, input)
outputBuilder.append(output.code)
i += output.index
}
return outputBuilder.toString().toInt()
}
fun processParameterMode(numbers: ArrayList<Int>, index: Int, opCode: Int, inputValue: Int): Output {
val reducedOpCode = opCode % 100
val parameterModeMap: MutableMap<Int, Int> = HashMap()
parameterModeMap[1] = opCode / 100 % 10
parameterModeMap[2] = opCode / 1000 % 10
parameterModeMap[3] = opCode / 10000 % 10
return when (reducedOpCode) {
1, 2 -> {
sumAndSubtractParam(numbers, index, reducedOpCode, parameterModeMap)
Output("", 4)
}
3, 4 -> inputAndOutputParam(numbers, index, reducedOpCode, parameterModeMap, inputValue)
5, 6 -> Output("", jumpIf(numbers, index, reducedOpCode, parameterModeMap))
7, 8 -> {
lessThanOrEquals(numbers, index, reducedOpCode, parameterModeMap)
Output("", 4)
}
else -> Output("err")
}
}
private fun sumAndSubtractParam(numbers: ArrayList<Int>, index: Int, opCode: Int, map: Map<Int, Int>) {
val input1Pos = numbers[index + 1]
val input2Pos = numbers[index + 2]
val outputPos = numbers[index + 3]
if (opCode == 1) {
numbers[if (map[3] == 0) outputPos else index + 3] = numbers[if (map[1] == 0) input1Pos else index + 1] +
numbers[if (map[2] == 0) input2Pos else index + 2]
} else {
numbers[if (map[3] == 0) outputPos else index + 3] = numbers[if (map[1] == 0) input1Pos else index + 1] *
numbers[if (map[2] == 0) input2Pos else index + 2]
}
}
private fun inputAndOutputParam(
numbers: ArrayList<Int>,
index: Int,
opCode: Int,
map: Map<Int, Int>,
inputValue: Int
): Output {
val pos = numbers[index + 1]
return if (opCode == 3) {
numbers[pos] = getInput(inputValue)
Output("", 2)
} else {
Output(numbers[if (map[1] == 0) pos else index + 1].toString() + "", 2)
}
}
private fun jumpIf(numbers: ArrayList<Int>, index: Int, opCode: Int, map: Map<Int, Int>): Int {
val input1Pos = numbers[index + 1]
val input2Pos = numbers[index + 2]
if (opCode == 5) {
if (numbers[if (map[1] == 0) input1Pos else index + 1] != 0) {
return numbers[if (map[2] == 0) input2Pos else index + 2] - index
}
} else {
if (numbers[if (map[1] == 0) input1Pos else index + 1] == 0) {
return numbers[if (map[2] == 0) input2Pos else index + 2] - index
}
}
return 3
}
private fun lessThanOrEquals(numbers: ArrayList<Int>, index: Int, opCode: Int, map: Map<Int, Int>) {
val input1Pos = numbers[index + 1]
val input2Pos = numbers[index + 2]
val outputPos = numbers[index + 3]
if (opCode == 7) {
if (numbers[if (map[1] == 0) input1Pos else index + 1] <
numbers[if (map[2] == 0) input2Pos else index + 2]
) {
numbers[outputPos] = 1
} else {
numbers[outputPos] = 0
}
} else {
if (numbers[if (map[1] == 0) input1Pos else index + 1] ==
numbers[if (map[2] == 0) input2Pos else index + 2]
) {
numbers[outputPos] = 1
} else {
numbers[outputPos] = 0
}
}
}
private fun getInput(input: Int): Int {
return input
}