commit 2c5197e02c9b7431c42a39368b0d5fc7822ec901
parent a02ab51af0f32d7be541fdc4e0cac36f24b1637b
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date: Fri, 13 Dec 2019 11:28:58 -0500
Add Julia solution for day 13
Diffstat:
A | day-13/day-13.jl | | | 206 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 206 insertions(+), 0 deletions(-)
diff --git a/day-13/day-13.jl b/day-13/day-13.jl
@@ -0,0 +1,206 @@
+function computer_step!(program, pc, relative_base, input)
+ # Runs from given pc until completion or next request for input.
+ # Modifies program and pc.
+ # Returns if the program has terminated and the output.
+ output = []
+ function get_param(loc, mode)
+ # Loc is gauranteed to exist.
+ if mode == 0
+ # Position mode.
+ get(program, program[loc] + 1, 0)
+ elseif mode == 1
+ # Immediate mode.
+ program[loc]
+ else
+ # Relative mode.
+ get(program, relative_base + program[loc] + 1, 0)
+ end
+ end
+ function get_res_loc(loc, mode)
+ # Loc is gauranteed to exist.
+ if mode == 0
+ # Position mode.
+ program[loc] + 1
+ else
+ # Relative mode.
+ relative_base + program[loc] + 1
+ end
+ end
+ while true
+ op_code = program[pc] % 100
+ mode_1 = (program[pc] % 1000) ÷ 100
+ mode_2 = (program[pc] % 10000) ÷ 1000
+ mode_3 = (program[pc] % 100000) ÷ 10000
+ if op_code == 1
+ program[get_res_loc(pc + 3, mode_3)] = (
+ get_param(pc + 1, mode_1)
+ + get_param(pc + 2, mode_2)
+ )
+ pc += 4
+ elseif op_code == 2
+ program[get_res_loc(pc + 3, mode_3)] = (
+ get_param(pc + 1, mode_1)
+ * get_param(pc + 2, mode_2)
+ )
+ pc += 4
+ elseif op_code == 3
+ if !isnothing(input)
+ program[get_res_loc(pc + 1, mode_1)] = input
+ input = nothing
+ else
+ return (pc, relative_base, false, output)
+ end
+ pc += 2
+ elseif op_code == 4
+ push!(output, get_param(pc + 1, mode_1))
+ pc += 2
+ elseif op_code == 5
+ if get_param(pc + 1, mode_1) != 0
+ pc = get_param(pc + 2, mode_2) + 1
+ else
+ pc += 3
+ end
+ elseif op_code == 6
+ if get_param(pc + 1, mode_1) == 0
+ pc = get_param(pc + 2, mode_2) + 1
+ else
+ pc += 3
+ end
+ elseif op_code == 7
+ program[get_res_loc(pc + 3, mode_3)] = (
+ get_param(pc + 1, mode_1)
+ < get_param(pc + 2, mode_2)
+ ) ? 1 : 0
+ pc += 4
+ elseif op_code == 8
+ program[get_res_loc(pc + 3, mode_3)] = (
+ get_param(pc + 1, mode_1)
+ == get_param(pc + 2, mode_2)
+ ) ? 1 : 0
+ pc += 4
+ elseif op_code == 9
+ relative_base += get_param(pc + 1, mode_1)
+ pc += 2
+ elseif op_code == 99
+ break
+ else
+ println("Unknown op code: ", op_code)
+ break
+ end
+ end
+ (pc, relative_base, true, output)
+end
+
+function arcade(program, demo, cheat)
+ program = Dict(enumerate(copy(program)))
+ if !demo
+ program[1] = 2
+ if cheat
+ # Replace bottom opening with walls.
+ for i in 1584:1622
+ program[i] = 1
+ end
+ end
+ end
+ # Set program state.
+ pc = 1
+ relative_base = 0
+ screen = Dict()
+ command = nothing
+ # Prepare for user input.
+ while true
+ pc, relative_base, finished, step_output = computer_step!(
+ program, pc, relative_base, command
+ )
+ command = nothing
+ # Parse step_output.
+ for i in 1:3:length(step_output)
+ screen[(step_output[i], step_output[i + 1])] = step_output[i + 2]
+ end
+ if !demo
+ if cheat
+ command = -1
+ # Break when there's no block left.
+ if count_blocks(screen) == 0
+ break
+ end
+ else
+ draw(screen)
+ # Read next input.
+ println("Move left with <h>, and move right with <l>:");
+ user_input = read(stdin, Char)
+ if user_input == 'h'
+ command = -1
+ elseif user_input == 'l'
+ command = 1
+ else
+ command = 0
+ end
+ end
+ end
+ if finished
+ break
+ end
+ end
+ screen
+end
+
+function count_blocks(screen)
+ count(x -> x == 2, values(screen))
+end
+
+function draw(screen)
+ # Check max/min coordinates.
+ max_x = -Inf
+ max_y = -Inf
+ score = 0
+ for panel in keys(screen)
+ max_x = max(max_x, panel[1])
+ max_y = max(max_y, panel[2])
+ if panel == (-1, 0)
+ score = screen[panel]
+ end
+ end
+ for y in 0:max_y
+ for x in 0:max_x
+ tile = get(screen, (x, y), 0)
+ if tile == 1
+ # Wall
+ print("||")
+ elseif tile == 2
+ # Block
+ print("##")
+ elseif tile == 3
+ # Paddle
+ print("--")
+ elseif tile == 4
+ # Ball
+ print("[]")
+ else
+ # Empty
+ print(" ")
+ end
+ end
+ println()
+ end
+ # Print score.
+ println("Score: ", score)
+end
+
+function part_1(input)
+ screen = arcade(input, true, false)
+ count_blocks(screen)
+end
+
+function part_2(input)
+ # Enable cheat and draw last screen for scores.
+ screen = arcade(input, false, true)
+ draw(screen)
+end
+
+input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
+
+println("Julia:")
+println("Part 1: ", part_1(input))
+println("Part 2: ")
+part_2(input)