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)