advent-of-code

Perserverance, or the lack thereof

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

day-11.jl (5729B)

    1 function turn_left(dir)
    2     if dir == (0, 1)
    3         (-1, 0)
    4     elseif dir == (1, 0)
    5         (0, 1)
    6     elseif dir == (0, -1)
    7         (1, 0)
    8     elseif dir == (-1, 0)
    9         (0, -1)
   10     else
   11         print("Invalid direction.")
   12     end
   13 end
   14 
   15 function turn_right(dir)
   16     if dir == (0, 1)
   17         (1, 0)
   18     elseif dir == (1, 0)
   19         (0, -1)
   20     elseif dir == (0, -1)
   21         (-1, 0)
   22     elseif dir == (-1, 0)
   23         (0, 1)
   24     else
   25         print("Invalid direction.")
   26     end
   27 end
   28 
   29 function robot!(program, panels)
   30     program = Dict(enumerate(copy(program)))
   31     pc = 1
   32     relative_base = 0
   33     coord = (0, 0)
   34     # Initially facing north.
   35     dir = (0, 1)
   36     while true
   37         # Get color for current panel. Panels start black (0).
   38         # This records only panels the robot has stepped on.
   39         color = get!(panels, coord, 0)
   40         pc, relative_base, finished, step_output = computer_step!(
   41             program, pc, relative_base,
   42             color
   43         )
   44         # First instruction is color to paint the panel to.
   45         panels[coord] = step_output[1]
   46         # Second instruction is direction to turn the robot.
   47         if step_output[2] == 0
   48             dir = turn_left(dir)
   49         else
   50             dir = turn_right(dir)
   51         end
   52         # Move robot forward by one panel.
   53         coord = (coord[1] + dir[1], coord[2] + dir[2])
   54         if finished
   55             break
   56         end
   57     end
   58 end
   59 
   60 
   61 function computer(program, input)
   62     program = Dict(enumerate(copy(program)))
   63     input = copy(input)
   64     output = []
   65     pc = 1
   66     relative_base = 0
   67     while true
   68         pc, relative_base, finished, step_output = computer_step!(
   69             program, pc, relative_base,
   70             isempty(input) ? nothing : popfirst!(input)
   71         )
   72         append!(output, step_output)
   73         if finished
   74             break
   75         end
   76     end
   77     output
   78 end
   79 
   80 function computer_step!(program, pc, relative_base, input)
   81     # Runs from given pc until completion or next request for input.
   82     # Modifies program and pc.
   83     # Returns if the program has terminated and the output.
   84     output = []
   85     function get_param(loc, mode)
   86         # Loc is gauranteed to exist.
   87         if mode == 0
   88             # Position mode.
   89             get(program, program[loc] + 1, 0)
   90         elseif mode == 1
   91             # Immediate mode.
   92             program[loc]
   93         else
   94             # Relative mode.
   95             get(program, relative_base + program[loc] + 1, 0)
   96         end
   97     end
   98     function get_res_loc(loc, mode)
   99         # Loc is gauranteed to exist.
  100         if mode == 0
  101             # Position mode.
  102             program[loc] + 1
  103         else
  104             # Relative mode.
  105             relative_base + program[loc] + 1
  106         end
  107     end
  108     while true
  109         op_code = program[pc] % 100
  110         mode_1 = (program[pc] % 1000) ÷ 100
  111         mode_2 = (program[pc] % 10000) ÷ 1000
  112         mode_3 = (program[pc] % 100000) ÷ 10000
  113         if op_code == 1
  114             program[get_res_loc(pc + 3, mode_3)] = (
  115                 get_param(pc + 1, mode_1)
  116                 + get_param(pc + 2, mode_2)
  117             )
  118             pc += 4
  119         elseif op_code == 2
  120             program[get_res_loc(pc + 3, mode_3)] = (
  121                 get_param(pc + 1, mode_1)
  122                 * get_param(pc + 2, mode_2)
  123             )
  124             pc += 4
  125         elseif op_code == 3
  126             if !isnothing(input)
  127                 program[get_res_loc(pc + 1, mode_1)] = input
  128                 input = nothing
  129             else
  130                 return (pc, relative_base, false, output)
  131             end
  132             pc += 2
  133         elseif op_code == 4
  134             push!(output, get_param(pc + 1, mode_1))
  135             pc += 2
  136         elseif op_code == 5
  137             if get_param(pc + 1, mode_1) != 0
  138                 pc = get_param(pc + 2, mode_2) + 1
  139             else
  140                 pc += 3
  141             end
  142         elseif op_code == 6
  143             if get_param(pc + 1, mode_1) == 0
  144                 pc = get_param(pc + 2, mode_2) + 1
  145             else
  146                 pc += 3
  147             end
  148         elseif op_code == 7
  149             program[get_res_loc(pc + 3, mode_3)] = (
  150                 get_param(pc + 1, mode_1)
  151                 < get_param(pc + 2, mode_2)
  152             ) ? 1 : 0
  153             pc += 4
  154         elseif op_code == 8
  155             program[get_res_loc(pc + 3, mode_3)] = (
  156                 get_param(pc + 1, mode_1)
  157                 == get_param(pc + 2, mode_2)
  158             ) ? 1 : 0
  159             pc += 4
  160         elseif op_code == 9
  161             relative_base += get_param(pc + 1, mode_1)
  162             pc += 2
  163         elseif op_code == 99
  164             break
  165         else
  166             println("Unknown op code: ", op_code)
  167             break
  168         end
  169     end
  170     (pc, relative_base, true, output)
  171 end
  172 
  173 function part_1(input)
  174     panels = Dict()
  175     robot!(input, panels)
  176     length(panels)
  177 end
  178 
  179 function part_2(input)
  180     # Set initial panel white.
  181     panels = Dict([(0, 0) => 1])
  182     robot!(input, panels)
  183     # Display the panel results.
  184     # Check max/min coordinates.
  185     min_x = Inf
  186     max_x = -Inf
  187     min_y = Inf
  188     max_y = -Inf
  189     for panel in keys(panels)
  190         min_x = min(min_x, panel[1])
  191         max_x = max(max_x, panel[1])
  192         min_y = min(min_y, panel[2])
  193         max_y = max(max_y, panel[2])
  194     end
  195     # Print the panels.
  196     for y in reverse(min_y:max_y)
  197         for x in min_x:max_x
  198             if get(panels, (x, y), 0) == 1
  199                 print("██")
  200             else
  201                 print("  ")
  202             end
  203         end
  204         println()
  205     end
  206 end
  207 
  208 input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
  209 
  210 println("Julia:")
  211 println("Part 1: ", part_1(input))
  212 println("Part 2: ")
  213 part_2(input)