Perserverance, or the lack thereof

`git clone git://git.shimmy1996.com/advent-of-code.git`
```commit 05075a757a7f27700d84013b99dc169e60ee5ae9
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date:   Wed, 11 Dec 2019 09:56:20 -0500

Add Julia solution for day 11

Diffstat:
```
```1 file changed, 213 insertions(+), 0 deletions(-)
diff --git a/day-11/day-11.jl b/day-11/day-11.jl
@@ -0,0 +1,213 @@
+function turn_left(dir)
+    if dir == (0, 1)
+        (-1, 0)
+    elseif dir == (1, 0)
+        (0, 1)
+    elseif dir == (0, -1)
+        (1, 0)
+    elseif dir == (-1, 0)
+        (0, -1)
+    else
+        print("Invalid direction.")
+    end
+end
+
+function turn_right(dir)
+    if dir == (0, 1)
+        (1, 0)
+    elseif dir == (1, 0)
+        (0, -1)
+    elseif dir == (0, -1)
+        (-1, 0)
+    elseif dir == (-1, 0)
+        (0, 1)
+    else
+        print("Invalid direction.")
+    end
+end
+
+function robot!(program, panels)
+    program = Dict(enumerate(copy(program)))
+    pc = 1
+    relative_base = 0
+    coord = (0, 0)
+    # Initially facing north.
+    dir = (0, 1)
+    while true
+        # Get color for current panel. Panels start black (0).
+        # This records only panels the robot has stepped on.
+        color = get!(panels, coord, 0)
+        pc, relative_base, finished, step_output = computer_step!(
+            program, pc, relative_base,
+            color
+        )
+        # First instruction is color to paint the panel to.
+        panels[coord] = step_output[1]
+        # Second instruction is direction to turn the robot.
+        if step_output[2] == 0
+            dir = turn_left(dir)
+        else
+            dir = turn_right(dir)
+        end
+        # Move robot forward by one panel.
+        coord = (coord[1] + dir[1], coord[2] + dir[2])
+        if finished
+            break
+        end
+    end
+end
+
+
+function computer(program, input)
+    program = Dict(enumerate(copy(program)))
+    input = copy(input)
+    output = []
+    pc = 1
+    relative_base = 0
+    while true
+        pc, relative_base, finished, step_output = computer_step!(
+            program, pc, relative_base,
+            isempty(input) ? nothing : popfirst!(input)
+        )
+        append!(output, step_output)
+        if finished
+            break
+        end
+    end
+    output
+end
+
+function computer_step!(program, pc, relative_base, 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 = []
+    function get_param(loc, mode)
+        # Loc is gauranteed to exist.
+        if mode == 0
+            # Position mode.
+            get(program, program[loc] + 1, 0)
+        elseif mode == 1
+            # Immediate mode.
+            program[loc]
+        else
+            # Relative mode.
+            get(program, relative_base + program[loc] + 1, 0)
+        end
+    end
+    function get_res_loc(loc, mode)
+        # Loc is gauranteed to exist.
+        if mode == 0
+            # Position mode.
+            program[loc] + 1
+        else
+            # Relative mode.
+            relative_base + program[loc] + 1
+        end
+    end
+    while true
+        op_code = program[pc] % 100
+        mode_1 = (program[pc] % 1000) ÷ 100
+        mode_2 = (program[pc] % 10000) ÷ 1000
+        mode_3 = (program[pc] % 100000) ÷ 10000
+        if op_code == 1
+            program[get_res_loc(pc + 3, mode_3)] = (
+                get_param(pc + 1, mode_1)
+                + get_param(pc + 2, mode_2)
+            )
+            pc += 4
+        elseif op_code == 2
+            program[get_res_loc(pc + 3, mode_3)] = (
+                get_param(pc + 1, mode_1)
+                * get_param(pc + 2, mode_2)
+            )
+            pc += 4
+        elseif op_code == 3
+            if !isnothing(input)
+                program[get_res_loc(pc + 1, mode_1)] = input
+                input = nothing
+            else
+                return (pc, relative_base, false, output)
+            end
+            pc += 2
+        elseif op_code == 4
+            push!(output, get_param(pc + 1, mode_1))
+            pc += 2
+        elseif op_code == 5
+            if get_param(pc + 1, mode_1) != 0
+                pc = get_param(pc + 2, mode_2) + 1
+            else
+                pc += 3
+            end
+        elseif op_code == 6
+            if get_param(pc + 1, mode_1) == 0
+                pc = get_param(pc + 2, mode_2) + 1
+            else
+                pc += 3
+            end
+        elseif op_code == 7
+            program[get_res_loc(pc + 3, mode_3)] = (
+                get_param(pc + 1, mode_1)
+                < get_param(pc + 2, mode_2)
+            ) ? 1 : 0
+            pc += 4
+        elseif op_code == 8
+            program[get_res_loc(pc + 3, mode_3)] = (
+                get_param(pc + 1, mode_1)
+                == get_param(pc + 2, mode_2)
+            ) ? 1 : 0
+            pc += 4
+        elseif op_code == 9
+            relative_base += get_param(pc + 1, mode_1)
+            pc += 2
+        elseif op_code == 99
+            break
+        else
+            println("Unknown op code: ", op_code)
+            break
+        end
+    end
+    (pc, relative_base, true, output)
+end
+
+function part_1(input)
+    panels = Dict()
+    robot!(input, panels)
+    length(panels)
+end
+
+function part_2(input)
+    # Set initial panel white.
+    panels = Dict([(0, 0) => 1])
+    robot!(input, panels)
+    # Display the panel results.
+    # Check max/min coordinates.
+    min_x = Inf
+    max_x = -Inf
+    min_y = Inf
+    max_y = -Inf
+    for panel in keys(panels)
+        min_x = min(min_x, panel[1])
+        max_x = max(max_x, panel[1])
+        min_y = min(min_y, panel[2])
+        max_y = max(max_y, panel[2])
+    end
+    # Print the panels.
+    for y in reverse(min_y:max_y)
+        for x in min_x:max_x
+            if get(panels, (x, y), 0) == 1
+                print("██")
+            else
+                print("  ")
+            end
+        end
+        println()
+    end
+end
+
+input = map(x -> parse(Int128, x), split(readlines(open("input.txt"))[1], ','))
+
+println("Julia:")
+println("Part 1: ", part_1(input))
+println("Part 2: ")
+part_2(input)
```