day-13.jl (5713B)
1 function computer_step!(program, pc, relative_base, input)
2 # Runs from given pc until completion or next request for input.
3 # Modifies program and pc.
4 # Returns if the program has terminated and the output.
5 output = []
6 function get_param(loc, mode)
7 # Loc is gauranteed to exist.
8 if mode == 0
9 # Position mode.
10 get(program, program[loc] + 1, 0)
11 elseif mode == 1
12 # Immediate mode.
13 program[loc]
14 else
15 # Relative mode.
16 get(program, relative_base + program[loc] + 1, 0)
17 end
18 end
19 function get_res_loc(loc, mode)
20 # Loc is gauranteed to exist.
21 if mode == 0
22 # Position mode.
23 program[loc] + 1
24 else
25 # Relative mode.
26 relative_base + program[loc] + 1
27 end
28 end
29 while true
30 op_code = program[pc] % 100
31 mode_1 = (program[pc] % 1000) ÷ 100
32 mode_2 = (program[pc] % 10000) ÷ 1000
33 mode_3 = (program[pc] % 100000) ÷ 10000
34 if op_code == 1
35 program[get_res_loc(pc + 3, mode_3)] = (
36 get_param(pc + 1, mode_1)
37 + get_param(pc + 2, mode_2)
38 )
39 pc += 4
40 elseif op_code == 2
41 program[get_res_loc(pc + 3, mode_3)] = (
42 get_param(pc + 1, mode_1)
43 * get_param(pc + 2, mode_2)
44 )
45 pc += 4
46 elseif op_code == 3
47 if !isnothing(input)
48 program[get_res_loc(pc + 1, mode_1)] = input
49 input = nothing
50 else
51 return (pc, relative_base, false, output)
52 end
53 pc += 2
54 elseif op_code == 4
55 push!(output, get_param(pc + 1, mode_1))
56 pc += 2
57 elseif op_code == 5
58 if get_param(pc + 1, mode_1) != 0
59 pc = get_param(pc + 2, mode_2) + 1
60 else
61 pc += 3
62 end
63 elseif op_code == 6
64 if get_param(pc + 1, mode_1) == 0
65 pc = get_param(pc + 2, mode_2) + 1
66 else
67 pc += 3
68 end
69 elseif op_code == 7
70 program[get_res_loc(pc + 3, mode_3)] = (
71 get_param(pc + 1, mode_1)
72 < get_param(pc + 2, mode_2)
73 ) ? 1 : 0
74 pc += 4
75 elseif op_code == 8
76 program[get_res_loc(pc + 3, mode_3)] = (
77 get_param(pc + 1, mode_1)
78 == get_param(pc + 2, mode_2)
79 ) ? 1 : 0
80 pc += 4
81 elseif op_code == 9
82 relative_base += get_param(pc + 1, mode_1)
83 pc += 2
84 elseif op_code == 99
85 break
86 else
87 println("Unknown op code: ", op_code)
88 break
89 end
90 end
91 (pc, relative_base, true, output)
92 end
93
94 function arcade(program, demo, cheat)
95 program = Dict(enumerate(copy(program)))
96 if !demo
97 program[1] = 2
98 if cheat
99 # Replace bottom opening with walls.
100 for i in 1584:1622
101 program[i] = 1
102 end
103 end
104 end
105 # Set program state.
106 pc = 1
107 relative_base = 0
108 screen = Dict()
109 command = nothing
110 # Prepare for user input.
111 while true
112 pc, relative_base, finished, step_output = computer_step!(
113 program, pc, relative_base, command
114 )
115 command = nothing
116 # Parse step_output.
117 for i in 1:3:length(step_output)
118 screen[(step_output[i], step_output[i + 1])] = step_output[i + 2]
119 end
120 if !demo
121 if cheat
122 command = -1
123 # Break when there's no block left.
124 if count_blocks(screen) == 0
125 break
126 end
127 else
128 draw(screen)
129 # Read next input.
130 println("Move left with <h>, and move right with <l>:");
131 user_input = read(stdin, Char)
132 if user_input == 'h'
133 command = -1
134 elseif user_input == 'l'
135 command = 1
136 else
137 command = 0
138 end
139 end
140 end
141 if finished
142 break
143 end
144 end
145 screen
146 end
147
148 function count_blocks(screen)
149 count(x -> x == 2, values(screen))
150 end
151
152 function draw(screen)
153 # Check max/min coordinates.
154 max_x = -Inf
155 max_y = -Inf
156 score = 0
157 for panel in keys(screen)
158 max_x = max(max_x, panel[1])
159 max_y = max(max_y, panel[2])
160 if panel == (-1, 0)
161 score = screen[panel]
162 end
163 end
164 for y in 0:max_y
165 for x in 0:max_x
166 tile = get(screen, (x, y), 0)
167 if tile == 1
168 # Wall
169 print("||")
170 elseif tile == 2
171 # Block
172 print("##")
173 elseif tile == 3
174 # Paddle
175 print("--")
176 elseif tile == 4
177 # Ball
178 print("[]")
179 else
180 # Empty
181 print(" ")
182 end
183 end
184 println()
185 end
186 # Print score.
187 println("Score: ", score)
188 end
189
190 function part_1(input)
191 screen = arcade(input, true, false)
192 count_blocks(screen)
193 end
194
195 function part_2(input)
196 # Enable cheat and draw last screen for scores.
197 screen = arcade(input, false, true)
198 draw(screen)
199 end
200
201 input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
202
203 println("Julia:")
204 println("Part 1: ", part_1(input))
205 println("Part 2: ")
206 part_2(input)