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)