day-11.jl (5729B)
1 function turn_left(dir)
2 if dir == (0, 1)
3 (-1, 0)
4 elseif dir == (1, 0)
5 (0, 1)
6 elseif dir == (0, -1)
7 (1, 0)
8 elseif dir == (-1, 0)
9 (0, -1)
10 else
11 print("Invalid direction.")
12 end
13 end
14
15 function turn_right(dir)
16 if dir == (0, 1)
17 (1, 0)
18 elseif dir == (1, 0)
19 (0, -1)
20 elseif dir == (0, -1)
21 (-1, 0)
22 elseif dir == (-1, 0)
23 (0, 1)
24 else
25 print("Invalid direction.")
26 end
27 end
28
29 function robot!(program, panels)
30 program = Dict(enumerate(copy(program)))
31 pc = 1
32 relative_base = 0
33 coord = (0, 0)
34 # Initially facing north.
35 dir = (0, 1)
36 while true
37 # Get color for current panel. Panels start black (0).
38 # This records only panels the robot has stepped on.
39 color = get!(panels, coord, 0)
40 pc, relative_base, finished, step_output = computer_step!(
41 program, pc, relative_base,
42 color
43 )
44 # First instruction is color to paint the panel to.
45 panels[coord] = step_output[1]
46 # Second instruction is direction to turn the robot.
47 if step_output[2] == 0
48 dir = turn_left(dir)
49 else
50 dir = turn_right(dir)
51 end
52 # Move robot forward by one panel.
53 coord = (coord[1] + dir[1], coord[2] + dir[2])
54 if finished
55 break
56 end
57 end
58 end
59
60
61 function computer(program, input)
62 program = Dict(enumerate(copy(program)))
63 input = copy(input)
64 output = []
65 pc = 1
66 relative_base = 0
67 while true
68 pc, relative_base, finished, step_output = computer_step!(
69 program, pc, relative_base,
70 isempty(input) ? nothing : popfirst!(input)
71 )
72 append!(output, step_output)
73 if finished
74 break
75 end
76 end
77 output
78 end
79
80 function computer_step!(program, pc, relative_base, input)
81 # Runs from given pc until completion or next request for input.
82 # Modifies program and pc.
83 # Returns if the program has terminated and the output.
84 output = []
85 function get_param(loc, mode)
86 # Loc is gauranteed to exist.
87 if mode == 0
88 # Position mode.
89 get(program, program[loc] + 1, 0)
90 elseif mode == 1
91 # Immediate mode.
92 program[loc]
93 else
94 # Relative mode.
95 get(program, relative_base + program[loc] + 1, 0)
96 end
97 end
98 function get_res_loc(loc, mode)
99 # Loc is gauranteed to exist.
100 if mode == 0
101 # Position mode.
102 program[loc] + 1
103 else
104 # Relative mode.
105 relative_base + program[loc] + 1
106 end
107 end
108 while true
109 op_code = program[pc] % 100
110 mode_1 = (program[pc] % 1000) ÷ 100
111 mode_2 = (program[pc] % 10000) ÷ 1000
112 mode_3 = (program[pc] % 100000) ÷ 10000
113 if op_code == 1
114 program[get_res_loc(pc + 3, mode_3)] = (
115 get_param(pc + 1, mode_1)
116 + get_param(pc + 2, mode_2)
117 )
118 pc += 4
119 elseif op_code == 2
120 program[get_res_loc(pc + 3, mode_3)] = (
121 get_param(pc + 1, mode_1)
122 * get_param(pc + 2, mode_2)
123 )
124 pc += 4
125 elseif op_code == 3
126 if !isnothing(input)
127 program[get_res_loc(pc + 1, mode_1)] = input
128 input = nothing
129 else
130 return (pc, relative_base, false, output)
131 end
132 pc += 2
133 elseif op_code == 4
134 push!(output, get_param(pc + 1, mode_1))
135 pc += 2
136 elseif op_code == 5
137 if get_param(pc + 1, mode_1) != 0
138 pc = get_param(pc + 2, mode_2) + 1
139 else
140 pc += 3
141 end
142 elseif op_code == 6
143 if get_param(pc + 1, mode_1) == 0
144 pc = get_param(pc + 2, mode_2) + 1
145 else
146 pc += 3
147 end
148 elseif op_code == 7
149 program[get_res_loc(pc + 3, mode_3)] = (
150 get_param(pc + 1, mode_1)
151 < get_param(pc + 2, mode_2)
152 ) ? 1 : 0
153 pc += 4
154 elseif op_code == 8
155 program[get_res_loc(pc + 3, mode_3)] = (
156 get_param(pc + 1, mode_1)
157 == get_param(pc + 2, mode_2)
158 ) ? 1 : 0
159 pc += 4
160 elseif op_code == 9
161 relative_base += get_param(pc + 1, mode_1)
162 pc += 2
163 elseif op_code == 99
164 break
165 else
166 println("Unknown op code: ", op_code)
167 break
168 end
169 end
170 (pc, relative_base, true, output)
171 end
172
173 function part_1(input)
174 panels = Dict()
175 robot!(input, panels)
176 length(panels)
177 end
178
179 function part_2(input)
180 # Set initial panel white.
181 panels = Dict([(0, 0) => 1])
182 robot!(input, panels)
183 # Display the panel results.
184 # Check max/min coordinates.
185 min_x = Inf
186 max_x = -Inf
187 min_y = Inf
188 max_y = -Inf
189 for panel in keys(panels)
190 min_x = min(min_x, panel[1])
191 max_x = max(max_x, panel[1])
192 min_y = min(min_y, panel[2])
193 max_y = max(max_y, panel[2])
194 end
195 # Print the panels.
196 for y in reverse(min_y:max_y)
197 for x in min_x:max_x
198 if get(panels, (x, y), 0) == 1
199 print("██")
200 else
201 print(" ")
202 end
203 end
204 println()
205 end
206 end
207
208 input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
209
210 println("Julia:")
211 println("Part 1: ", part_1(input))
212 println("Part 2: ")
213 part_2(input)