commit 2aa81542a9512116c2efbc36c5a8d727ee02b731
parent b3b2b4976d8d0d0ddac2021569d24ec61b628e05
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date: Sat, 28 Dec 2019 10:39:27 -0600
Add Julia solution for day-17
Diffstat:
A | day-17/day-17.jl | | | 202 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 202 insertions(+), 0 deletions(-)
diff --git a/day-17/day-17.jl b/day-17/day-17.jl
@@ -0,0 +1,202 @@
+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 get_view(input)
+ # Get view of the scaffoldings.
+ program = Dict(enumerate(copy(input)))
+ # Set program state.
+ pc = 1
+ relative_base = 0
+ _, _, _, output = computer_step!(
+ program, pc, relative_base, nothing
+ )
+ # Split output into vector of vector.
+ width = findfirst(output .== 10)
+ chart = []
+ for i in 1:size(output, 1)
+ # No need to include the new lines at the end.
+ if output[i] != 10
+ row = i ÷ width + 1
+ if size(chart, 1) < row
+ push!(chart, [])
+ end
+ push!(chart[row], Char(output[i]))
+ end
+ end
+ chart
+end
+
+function print_view(view)
+ for row in view
+ for px in row
+ print(px)
+ end
+ println()
+ end
+end
+
+function calc_alignment_parameter(view)
+ width = size(view[1], 1)
+ height = size(view, 1)
+ alignment_param = 0
+ # Current coordinate.
+ # No intersection can occur on the borders.
+ for x in 2:(width - 1)
+ for y in 2:(height - 1)
+ # Check for intersection.
+ # All 5 squares should be scaffolding.
+ if (view[y][x] != '.'
+ && view[y][x + 1] != '.'
+ && view[y][x - 1] != '.'
+ && view[y + 1][x] != '.'
+ && view[y - 1][x] != '.')
+ alignment_param += (x - 1) * (y - 1)
+ end
+ end
+ end
+ alignment_param
+end
+
+function collect_dust(input, main_routine, func_a, func_b, func_c)
+ # Get view of the scaffoldings.
+ program = Dict(enumerate(copy(input)))
+ # Enable movements.
+ program[1] = 2
+ # Set program state.
+ pc = 1
+ relative_base = 0
+ # Assemble commands.
+ commands = map(
+ ch -> Int(ch),
+ collect(
+ main_routine
+ * func_a
+ * func_b
+ * func_c
+ * "n\n" # No video feeds.
+ )
+ )
+ # Collect output.
+ output = []
+ # Run program.
+ while true
+ pc, relative_base, finished, step_output = computer_step!(
+ program, pc, relative_base, popfirst!(commands)
+ )
+ append!(output, step_output)
+ if finished
+ break
+ end
+ end
+ output[end]
+end
+
+function part_1(input)
+ view = get_view(input)
+ print_view(view)
+ calc_alignment_parameter(view)
+end
+
+function part_2(input)
+ main_routine = "A,B,A,B,C,A,B,C,A,C\n"
+ func_a = "R,6,L,6,L,10\n"
+ func_b = "L,8,L,6,L,10,L,6\n"
+ func_c = "R,6,L,8,L,10,R,6\n"
+ collect_dust(input, main_routine, func_a, func_b, func_c)
+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))