day-17.jl (5656B)
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 get_view(input)
95 # Get view of the scaffoldings.
96 program = Dict(enumerate(copy(input)))
97 # Set program state.
98 pc = 1
99 relative_base = 0
100 _, _, _, output = computer_step!(
101 program, pc, relative_base, nothing
102 )
103 # Split output into vector of vector.
104 width = findfirst(output .== 10)
105 chart = []
106 for i in 1:size(output, 1)
107 # No need to include the new lines at the end.
108 if output[i] != 10
109 row = i ÷ width + 1
110 if size(chart, 1) < row
111 push!(chart, [])
112 end
113 push!(chart[row], Char(output[i]))
114 end
115 end
116 chart
117 end
118
119 function print_view(view)
120 for row in view
121 for px in row
122 print(px)
123 end
124 println()
125 end
126 end
127
128 function calc_alignment_parameter(view)
129 width = size(view[1], 1)
130 height = size(view, 1)
131 alignment_param = 0
132 # Current coordinate.
133 # No intersection can occur on the borders.
134 for x in 2:(width - 1)
135 for y in 2:(height - 1)
136 # Check for intersection.
137 # All 5 squares should be scaffolding.
138 if (view[y][x] != '.'
139 && view[y][x + 1] != '.'
140 && view[y][x - 1] != '.'
141 && view[y + 1][x] != '.'
142 && view[y - 1][x] != '.')
143 alignment_param += (x - 1) * (y - 1)
144 end
145 end
146 end
147 alignment_param
148 end
149
150 function collect_dust(input, main_routine, func_a, func_b, func_c)
151 # Get view of the scaffoldings.
152 program = Dict(enumerate(copy(input)))
153 # Enable movements.
154 program[1] = 2
155 # Set program state.
156 pc = 1
157 relative_base = 0
158 # Assemble commands.
159 commands = map(
160 ch -> Int(ch),
161 collect(
162 main_routine
163 * func_a
164 * func_b
165 * func_c
166 * "n\n" # No video feeds.
167 )
168 )
169 # Collect output.
170 output = []
171 # Run program.
172 while true
173 pc, relative_base, finished, step_output = computer_step!(
174 program, pc, relative_base, popfirst!(commands)
175 )
176 append!(output, step_output)
177 if finished
178 break
179 end
180 end
181 output[end]
182 end
183
184 function part_1(input)
185 view = get_view(input)
186 print_view(view)
187 calc_alignment_parameter(view)
188 end
189
190 function part_2(input)
191 main_routine = "A,B,A,B,C,A,B,C,A,C\n"
192 func_a = "R,6,L,6,L,10\n"
193 func_b = "L,8,L,6,L,10,L,6\n"
194 func_c = "R,6,L,8,L,10,R,6\n"
195 collect_dust(input, main_routine, func_a, func_b, func_c)
196 end
197
198 input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
199
200 println("Julia:")
201 println("Part 1: ", part_1(input))
202 println("Part 2: ", part_2(input))