advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git
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:
Aday-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))