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