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))