advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

day-07.jl (6209B)

    1 function computer(program, input)
    2     program = copy(program)
    3     input = copy(input)
    4     output = []
    5     pc = 1
    6     while true
    7         pc, finished, step_output = computer_step!(
    8             program, pc,
    9             isempty(input) ? nothing : popfirst!(input)
   10         )
   11         # println(finished, " ", step_output)
   12         append!(output, step_output)
   13         if finished
   14             break
   15         end
   16     end
   17     output
   18 end
   19 
   20 function computer_step!(program, pc, input)
   21     # Runs from given pc until completion or next request for input.
   22     # Modifies program and pc.
   23     # Returns if the program has terminated and the output.
   24     output = []
   25     get_param(loc, im_mode) = (im_mode ? program[loc] : program[program[loc] + 1])
   26     while true
   27         op_code = program[pc] % 100
   28         im_mode_1 = (program[pc] % 1000) ÷ 100 > 0;
   29         im_mode_2 = (program[pc] % 10000) ÷ 1000 > 0;
   30         if op_code == 1
   31             program[program[pc + 3] + 1] = (
   32                 get_param(pc + 1, im_mode_1)
   33                 + get_param(pc + 2, im_mode_2)
   34             )
   35             pc += 4
   36         elseif op_code == 2
   37             program[program[pc + 3] + 1] = (
   38                 get_param(pc + 1, im_mode_1)
   39                 * get_param(pc + 2, im_mode_2)
   40             )
   41             pc += 4
   42         elseif op_code == 3
   43             if !isnothing(input)
   44                 program[program[pc + 1] + 1] = input
   45                 input = nothing
   46             else
   47                 return (pc, false, output)
   48             end
   49             pc += 2
   50         elseif op_code == 4
   51             push!(output, get_param(pc + 1, im_mode_1))
   52             pc += 2
   53         elseif op_code == 5
   54             if get_param(pc + 1, im_mode_1) != 0
   55                 pc = get_param(pc + 2, im_mode_2) + 1
   56             else
   57                 pc += 3;
   58             end
   59         elseif op_code == 6
   60             if get_param(pc + 1, im_mode_1) == 0
   61                 pc = get_param(pc + 2, im_mode_2) + 1
   62             else
   63                 pc += 3;
   64             end
   65         elseif op_code == 7
   66             program[program[pc + 3] + 1] = (
   67                 get_param(pc + 1, im_mode_1)
   68                 < get_param(pc + 2, im_mode_2)
   69             ) ? 1 : 0;
   70             pc += 4;
   71         elseif op_code == 8
   72             program[program[pc + 3] + 1] = (
   73                 get_param(pc + 1, im_mode_1)
   74                 == get_param(pc + 2, im_mode_2)
   75             ) ? 1 : 0;
   76             pc += 4;
   77         elseif op_code == 99
   78             break
   79         else
   80             println("Unknown op code: ", op_code)
   81             break
   82         end
   83     end
   84     (pc, true, output)
   85 end
   86 
   87 function feedback_amp(program, phase)
   88     num_amps = length(phase)
   89     programs = repeat([copy(program)], num_amps)
   90     pcs = repeat([1], num_amps)
   91     inputs = map(x -> [x], phase)
   92     # Additional input for first amplifier.
   93     push!(inputs[1], 0)
   94     # Index of currently working amp.
   95     work_idx = 1
   96     while true
   97         # Run current amp.
   98         pcs[work_idx], finished, step_output = computer_step!(
   99             programs[work_idx],
  100             pcs[work_idx],
  101             popfirst!(inputs[work_idx])
  102         )
  103         # Pipe output to next amp.
  104         work_idx_next = work_idx + 1 - (work_idx + 1) ÷ (num_amps + 1) * num_amps
  105         append!(inputs[work_idx_next], step_output)
  106         # Check for completion.
  107         if finished && work_idx == num_amps
  108             break
  109         end
  110         # Move to next amp.
  111         work_idx = work_idx_next
  112     end
  113     inputs[1][end]
  114 end
  115 
  116 function part_1(input)
  117     max_output = 0
  118     for phase_1 in 0:4
  119         out_1 = computer(input, [phase_1, 0])[end]
  120         for phase_2 in 0:4
  121             if phase_2 == phase_1
  122                 continue
  123             end
  124             out_2 = computer(input, [phase_2, out_1])[end]
  125             for phase_3 in 0:4
  126                 if phase_3 == phase_2 || phase_3 == phase_1
  127                     continue
  128                 end
  129                 out_3 = computer(input, [phase_3, out_2])[end]
  130                 for phase_4 in 0:4
  131                     if phase_4 == phase_1 || phase_4 == phase_2 || phase_4 == phase_3
  132                         continue
  133                     end
  134                     out_4 = computer(input, [phase_4, out_3])[end]
  135                     for phase_5 in 0:4
  136                         if (
  137                             phase_5 == phase_1
  138                             || phase_5 == phase_2
  139                             || phase_5 == phase_3
  140                             || phase_5 == phase_4
  141                         )
  142                             continue
  143                         end
  144                         out_5 = computer(input, [phase_5, out_4])[end]
  145                         max_output = max(max_output, out_5)
  146                     end
  147                 end
  148             end
  149         end
  150     end
  151     max_output
  152 end
  153 
  154 function part_2(input)
  155     max_output = 0
  156     for phase_1 in 5:9
  157         for phase_2 in 5:9
  158             if phase_2 == phase_1
  159                 continue
  160             end
  161             for phase_3 in 5:9
  162                 if phase_3 == phase_2 || phase_3 == phase_1
  163                     continue
  164                 end
  165                 for phase_4 in 5:9
  166                     if phase_4 == phase_1 || phase_4 == phase_2 || phase_4 == phase_3
  167                         continue
  168                     end
  169                     for phase_5 in 5:9
  170                         if (
  171                             phase_5 == phase_1
  172                             || phase_5 == phase_2
  173                             || phase_5 == phase_3
  174                             || phase_5 == phase_4
  175                         )
  176                             continue
  177                         end
  178                         max_output = max(
  179                             max_output,
  180                             feedback_amp(
  181                                 input,
  182                                 [phase_1, phase_2, phase_3, phase_4, phase_5]
  183                             )
  184                         )
  185                     end
  186                 end
  187             end
  188         end
  189     end
  190     max_output
  191 end
  192 
  193 input = map(x -> parse(Int32, x), split(readlines(open("input.txt"))[1], ','))
  194 
  195 println("Julia:")
  196 println("Part 1: ", part_1(input))
  197 println("Part 2: ", part_2(input))