Perserverance, or the lack thereof

commit e4e7917ec3c60453d8900fa47833973dd8e53136
parent 888daaf75fd78afcf924dd87ec556f2a569f8dc3
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date:   Sun,  8 Dec 2019 10:06:28 -0500

Add Julia solution for day 07

Diffstat:
 A day-07/day-07.jl | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 197 insertions(+), 0 deletions(-)
diff --git a/day-07/day-07.jl b/day-07/day-07.jl
@@ -0,0 +1,197 @@
+function computer(program, input)
+    program = copy(program)
+    input = copy(input)
+    output = []
+    pc = 1
+    while true
+        pc, finished, step_output = computer_step!(
+            program, pc,
+            isempty(input) ? nothing : popfirst!(input)
+        )
+        # println(finished, " ", step_output)
+        append!(output, step_output)
+        if finished
+            break
+        end
+    end
+    output
+end
+
+function computer_step!(program, pc, 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 = []
+    get_param(loc, im_mode) = (im_mode ? program[loc] : program[program[loc] + 1])
+    while true
+        op_code = program[pc] % 100
+        im_mode_1 = (program[pc] % 1000) ÷ 100 > 0;
+        im_mode_2 = (program[pc] % 10000) ÷ 1000 > 0;
+        if op_code == 1
+            program[program[pc + 3] + 1] = (
+                get_param(pc + 1, im_mode_1)
+                + get_param(pc + 2, im_mode_2)
+            )
+            pc += 4
+        elseif op_code == 2
+            program[program[pc + 3] + 1] = (
+                get_param(pc + 1, im_mode_1)
+                * get_param(pc + 2, im_mode_2)
+            )
+            pc += 4
+        elseif op_code == 3
+            if !isnothing(input)
+                program[program[pc + 1] + 1] = input
+                input = nothing
+            else
+                return (pc, false, output)
+            end
+            pc += 2
+        elseif op_code == 4
+            push!(output, get_param(pc + 1, im_mode_1))
+            pc += 2
+        elseif op_code == 5
+            if get_param(pc + 1, im_mode_1) != 0
+                pc = get_param(pc + 2, im_mode_2) + 1
+            else
+                pc += 3;
+            end
+        elseif op_code == 6
+            if get_param(pc + 1, im_mode_1) == 0
+                pc = get_param(pc + 2, im_mode_2) + 1
+            else
+                pc += 3;
+            end
+        elseif op_code == 7
+            program[program[pc + 3] + 1] = (
+                get_param(pc + 1, im_mode_1)
+                < get_param(pc + 2, im_mode_2)
+            ) ? 1 : 0;
+            pc += 4;
+        elseif op_code == 8
+            program[program[pc + 3] + 1] = (
+                get_param(pc + 1, im_mode_1)
+                == get_param(pc + 2, im_mode_2)
+            ) ? 1 : 0;
+            pc += 4;
+        elseif op_code == 99
+            break
+        else
+            println("Unknown op code: ", op_code)
+            break
+        end
+    end
+    (pc, true, output)
+end
+
+function feedback_amp(program, phase)
+    num_amps = length(phase)
+    programs = repeat([copy(program)], num_amps)
+    pcs = repeat([1], num_amps)
+    inputs = map(x -> [x], phase)
+    # Additional input for first amplifier.
+    push!(inputs[1], 0)
+    # Index of currently working amp.
+    work_idx = 1
+    while true
+        # Run current amp.
+        pcs[work_idx], finished, step_output = computer_step!(
+            programs[work_idx],
+            pcs[work_idx],
+            popfirst!(inputs[work_idx])
+        )
+        # Pipe output to next amp.
+        work_idx_next = work_idx + 1 - (work_idx + 1) ÷ (num_amps + 1) * num_amps
+        append!(inputs[work_idx_next], step_output)
+        # Check for completion.
+        if finished && work_idx == num_amps
+            break
+        end
+        # Move to next amp.
+        work_idx = work_idx_next
+    end
+    inputs[1][end]
+end
+
+function part_1(input)
+    max_output = 0
+    for phase_1 in 0:4
+        out_1 = computer(input, [phase_1, 0])[end]
+        for phase_2 in 0:4
+            if phase_2 == phase_1
+                continue
+            end
+            out_2 = computer(input, [phase_2, out_1])[end]
+            for phase_3 in 0:4
+                if phase_3 == phase_2 || phase_3 == phase_1
+                    continue
+                end
+                out_3 = computer(input, [phase_3, out_2])[end]
+                for phase_4 in 0:4
+                    if phase_4 == phase_1 || phase_4 == phase_2 || phase_4 == phase_3
+                        continue
+                    end
+                    out_4 = computer(input, [phase_4, out_3])[end]
+                    for phase_5 in 0:4
+                        if (
+                            phase_5 == phase_1
+                            || phase_5 == phase_2
+                            || phase_5 == phase_3
+                            || phase_5 == phase_4
+                        )
+                            continue
+                        end
+                        out_5 = computer(input, [phase_5, out_4])[end]
+                        max_output = max(max_output, out_5)
+                    end
+                end
+            end
+        end
+    end
+    max_output
+end
+
+function part_2(input)
+    max_output = 0
+    for phase_1 in 5:9
+        for phase_2 in 5:9
+            if phase_2 == phase_1
+                continue
+            end
+            for phase_3 in 5:9
+                if phase_3 == phase_2 || phase_3 == phase_1
+                    continue
+                end
+                for phase_4 in 5:9
+                    if phase_4 == phase_1 || phase_4 == phase_2 || phase_4 == phase_3
+                        continue
+                    end
+                    for phase_5 in 5:9
+                        if (
+                            phase_5 == phase_1
+                            || phase_5 == phase_2
+                            || phase_5 == phase_3
+                            || phase_5 == phase_4
+                        )
+                            continue
+                        end
+                        max_output = max(
+                            max_output,
+                            feedback_amp(
+                                input,
+                                [phase_1, phase_2, phase_3, phase_4, phase_5]
+                            )
+                        )
+                    end
+                end
+            end
+        end
+    end
+    max_output
+end
+
+input = map(x -> parse(Int32, x), split(readlines(open("input.txt"))[1], ','))
+
+println("Julia:")
+println("Part 1: ", part_1(input))
+println("Part 2: ", part_2(input))