advent-of-code

Perserverance, or the lack thereof

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

day-13.jl (5713B)

    1 function computer_step!(program, pc, relative_base, input)
    2     # Runs from given pc until completion or next request for input.
    3     # Modifies program and pc.
    4     # Returns if the program has terminated and the output.
    5     output = []
    6     function get_param(loc, mode)
    7         # Loc is gauranteed to exist.
    8         if mode == 0
    9             # Position mode.
   10             get(program, program[loc] + 1, 0)
   11         elseif mode == 1
   12             # Immediate mode.
   13             program[loc]
   14         else
   15             # Relative mode.
   16             get(program, relative_base + program[loc] + 1, 0)
   17         end
   18     end
   19     function get_res_loc(loc, mode)
   20         # Loc is gauranteed to exist.
   21         if mode == 0
   22             # Position mode.
   23             program[loc] + 1
   24         else
   25             # Relative mode.
   26             relative_base + program[loc] + 1
   27         end
   28     end
   29     while true
   30         op_code = program[pc] % 100
   31         mode_1 = (program[pc] % 1000) ÷ 100
   32         mode_2 = (program[pc] % 10000) ÷ 1000
   33         mode_3 = (program[pc] % 100000) ÷ 10000
   34         if op_code == 1
   35             program[get_res_loc(pc + 3, mode_3)] = (
   36                 get_param(pc + 1, mode_1)
   37                 + get_param(pc + 2, mode_2)
   38             )
   39             pc += 4
   40         elseif op_code == 2
   41             program[get_res_loc(pc + 3, mode_3)] = (
   42                 get_param(pc + 1, mode_1)
   43                 * get_param(pc + 2, mode_2)
   44             )
   45             pc += 4
   46         elseif op_code == 3
   47             if !isnothing(input)
   48                 program[get_res_loc(pc + 1, mode_1)] = input
   49                 input = nothing
   50             else
   51                 return (pc, relative_base, false, output)
   52             end
   53             pc += 2
   54         elseif op_code == 4
   55             push!(output, get_param(pc + 1, mode_1))
   56             pc += 2
   57         elseif op_code == 5
   58             if get_param(pc + 1, mode_1) != 0
   59                 pc = get_param(pc + 2, mode_2) + 1
   60             else
   61                 pc += 3
   62             end
   63         elseif op_code == 6
   64             if get_param(pc + 1, mode_1) == 0
   65                 pc = get_param(pc + 2, mode_2) + 1
   66             else
   67                 pc += 3
   68             end
   69         elseif op_code == 7
   70             program[get_res_loc(pc + 3, mode_3)] = (
   71                 get_param(pc + 1, mode_1)
   72                 < get_param(pc + 2, mode_2)
   73             ) ? 1 : 0
   74             pc += 4
   75         elseif op_code == 8
   76             program[get_res_loc(pc + 3, mode_3)] = (
   77                 get_param(pc + 1, mode_1)
   78                 == get_param(pc + 2, mode_2)
   79             ) ? 1 : 0
   80             pc += 4
   81         elseif op_code == 9
   82             relative_base += get_param(pc + 1, mode_1)
   83             pc += 2
   84         elseif op_code == 99
   85             break
   86         else
   87             println("Unknown op code: ", op_code)
   88             break
   89         end
   90     end
   91     (pc, relative_base, true, output)
   92 end
   93 
   94 function arcade(program, demo, cheat)
   95     program = Dict(enumerate(copy(program)))
   96     if !demo
   97         program[1] = 2
   98         if cheat
   99             # Replace bottom opening with walls.
  100             for i in 1584:1622
  101                 program[i] = 1
  102             end
  103         end
  104     end
  105     # Set program state.
  106     pc = 1
  107     relative_base = 0
  108     screen = Dict()
  109     command = nothing
  110     # Prepare for user input.
  111     while true
  112         pc, relative_base, finished, step_output = computer_step!(
  113             program, pc, relative_base, command
  114         )
  115         command = nothing
  116         # Parse step_output.
  117         for i in 1:3:length(step_output)
  118             screen[(step_output[i], step_output[i + 1])] = step_output[i + 2]
  119         end
  120         if !demo
  121             if cheat
  122                 command = -1
  123                 # Break when there's no block left.
  124                 if count_blocks(screen) == 0
  125                     break
  126                 end
  127             else
  128                 draw(screen)
  129                 # Read next input.
  130                 println("Move left with <h>, and move right with <l>:");
  131                 user_input = read(stdin, Char)
  132                 if user_input == 'h'
  133                     command = -1
  134                 elseif user_input == 'l'
  135                     command = 1
  136                 else
  137                     command = 0
  138                 end
  139             end
  140         end
  141         if finished
  142             break
  143         end
  144     end
  145     screen
  146 end
  147 
  148 function count_blocks(screen)
  149     count(x -> x == 2, values(screen))
  150 end
  151 
  152 function draw(screen)
  153     # Check max/min coordinates.
  154     max_x = -Inf
  155     max_y = -Inf
  156     score = 0
  157     for panel in keys(screen)
  158         max_x = max(max_x, panel[1])
  159         max_y = max(max_y, panel[2])
  160         if panel == (-1, 0)
  161             score = screen[panel]
  162         end
  163     end
  164     for y in 0:max_y
  165         for x in 0:max_x
  166             tile = get(screen, (x, y), 0)
  167             if tile == 1
  168                 # Wall
  169                 print("||")
  170             elseif tile == 2
  171                 # Block
  172                 print("##")
  173             elseif tile == 3
  174                 # Paddle
  175                 print("--")
  176             elseif tile == 4
  177                 # Ball
  178                 print("[]")
  179             else
  180                 # Empty
  181                 print("  ")
  182             end
  183         end
  184         println()
  185     end
  186     # Print score.
  187     println("Score: ", score)
  188 end
  189 
  190 function part_1(input)
  191     screen = arcade(input, true, false)
  192     count_blocks(screen)
  193 end
  194 
  195 function part_2(input)
  196     # Enable cheat and draw last screen for scores.
  197     screen = arcade(input, false, true)
  198     draw(screen)
  199 end
  200 
  201 input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
  202 
  203 println("Julia:")
  204 println("Part 1: ", part_1(input))
  205 println("Part 2: ")
  206 part_2(input)