advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git
commit f8360d8b6dc3d70a9cad23d1f07d665b320c0f4d
parent 703e896dca75fbefc681f099c68449f0590c8681
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date:   Wed, 11 Dec 2019 09:16:37 -0500

Add Rust solution for day 11.

Diffstat:
Aday-11/Makefile | 9+++++++++
Aday-11/day-11.rs | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aday-11/input.txt | 1+
3 files changed, 243 insertions(+), 0 deletions(-)
diff --git a/day-11/Makefile b/day-11/Makefile
@@ -0,0 +1,9 @@
+CC := g++
+CCFLAGS := --std=c++17 -Wall
+
+all: day-11-rust day-11.jl
+	julia day-11.jl
+	./day-11-rust
+
+day-11-rust: day-11.rs
+	rustc $^ -o $@
diff --git a/day-11/day-11.rs b/day-11/day-11.rs
@@ -0,0 +1,233 @@
+use std::collections::HashMap;
+type Op = i128;
+
+fn main() {
+    let input = std::fs::read_to_string("input.txt")
+        .unwrap()
+        .trim()
+        .split(",")
+        .map(|op| op.parse::<Op>().unwrap())
+        .collect::<Vec<Op>>();
+    println!("Rust:");
+    println!("Part 1: {}", part_1(&input));
+    println!("Part 2: ");
+    part_2(&input);
+}
+
+fn turn_left(dir: (Op, Op)) -> (Op, Op) {
+    // Takes in dir in the form of (0, 1).
+    match dir {
+        (0, 1) => (-1, 0),
+        (1, 0) => (0, 1),
+        (0, -1) => (1, 0),
+        (-1, 0) => (0, -1),
+        _ => panic!(),
+    }
+}
+
+fn turn_right(dir: (Op, Op)) -> (Op, Op) {
+    // Takes in dir in the form of (0, 1).
+    match dir {
+        (0, 1) => (1, 0),
+        (1, 0) => (0, -1),
+        (0, -1) => (-1, 0),
+        (-1, 0) => (0, 1),
+        _ => panic!(),
+    }
+}
+
+fn robot(program: &Vec<Op>, panels: &mut HashMap<(Op, Op), usize>) {
+    let mut program = program
+        .iter()
+        .enumerate()
+        .map(|(idx, &op)| (idx, op))
+        .collect::<HashMap<usize, Op>>();
+    let mut pc = 0;
+    let mut relative_base = 0;
+    let mut coord = (0, 0);
+    // Initially facing north.
+    let mut dir = (0, 1);
+
+    loop {
+        // Get color for current panel. Panels start black (0).
+        // This records only panels the robot has stepped on.
+        let color = panels.entry(coord).or_insert(0);
+        let (finished, step_output) = computer_step(
+            &mut program,
+            &mut pc,
+            &mut relative_base,
+            Some(*color as Op),
+        );
+        // First instruction is color to paint the panel to.
+        *panels.get_mut(&coord).unwrap() = step_output[0] as usize;
+        // Second instruction is direction to turn the robot.
+        if step_output[1] == 0 {
+            dir = turn_left(dir);
+        } else {
+            dir = turn_right(dir);
+        }
+        // Move robot forward by one panel.
+        coord = (coord.0 + dir.0, coord.1 + dir.1);
+        if finished {
+            break;
+        }
+    }
+}
+
+fn computer_step(
+    program: &mut HashMap<usize, Op>,
+    pc: &mut usize,
+    relative_base: &mut Op,
+    mut input: Option<Op>,
+) -> (bool, Vec<Op>) {
+    let mut output = vec![];
+    let get_param = |loc: usize, mode, program: &HashMap<usize, Op>, relative_base: &Op| -> Op {
+        match mode {
+            // Position mode.
+            0 => *program.get(&(program[&loc] as usize)).unwrap_or(&0),
+            // Immediate mode.
+            1 => program[&loc],
+            // Relative mode.
+            2 => *program
+                .get(&((*relative_base + program[&loc]) as usize))
+                .unwrap_or(&0),
+            _ => panic!(),
+        }
+    };
+
+    let get_res_loc =
+        |loc: usize, mode, program: &HashMap<usize, Op>, relative_base: &Op| -> usize {
+            match mode {
+                // Position mode.
+                0 => program[&loc] as usize,
+                // Immediate mode is banned.
+                // Relative mode.
+                2 => (relative_base + program[&loc]) as usize,
+                _ => panic!(),
+            }
+        };
+
+    loop {
+        let op_code = program[pc] % 100;
+        let mode_1 = (program[pc] % 1000) / 100;
+        let mode_2 = (program[pc] % 10000) / 1000;
+        let mode_3 = (program[pc] % 100000) / 10000;
+        match op_code {
+            1 => {
+                let res_loc = get_res_loc(*pc + 3, mode_3, &program, relative_base);
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                let param_2 = get_param(*pc + 2, mode_2, &program, relative_base);
+                *program.entry(res_loc).or_default() = param_1 + param_2;
+                *pc += 4;
+            }
+            2 => {
+                let res_loc = get_res_loc(*pc + 3, mode_3, &program, relative_base);
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                let param_2 = get_param(*pc + 2, mode_2, &program, relative_base);
+                *program.entry(res_loc as usize).or_default() = param_1 * param_2;
+                *pc += 4;
+            }
+            3 => {
+                let res_loc = get_res_loc(*pc + 1, mode_1, &program, relative_base);
+                // Only use input once.
+                if input.is_some() {
+                    *program.entry(res_loc as usize).or_default() = input.unwrap();
+                    input = None;
+                } else {
+                    // Need new input.
+                    return (false, output);
+                };
+                *pc += 2;
+            }
+            4 => {
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                output.push(param_1);
+                *pc += 2;
+            }
+            5 => {
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                let param_2 = get_param(*pc + 2, mode_2, &program, relative_base);
+                if param_1 != 0 {
+                    *pc = param_2 as usize;
+                } else {
+                    *pc += 3;
+                }
+            }
+            6 => {
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                let param_2 = get_param(*pc + 2, mode_2, &program, relative_base);
+                if param_1 == 0 {
+                    *pc = param_2 as usize;
+                } else {
+                    *pc += 3;
+                }
+            }
+            7 => {
+                let res_loc = get_res_loc(*pc + 3, mode_3, &program, relative_base);
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                let param_2 = get_param(*pc + 2, mode_2, &program, relative_base);
+                *program.entry(res_loc as usize).or_default() =
+                    if param_1 < param_2 { 1 } else { 0 };
+                *pc += 4;
+            }
+            8 => {
+                let res_loc = get_res_loc(*pc + 3, mode_3, &program, relative_base);
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                let param_2 = get_param(*pc + 2, mode_2, &program, relative_base);
+                *program.entry(res_loc as usize).or_default() =
+                    if param_1 == param_2 { 1 } else { 0 };
+                *pc += 4;
+            }
+            9 => {
+                let param_1 = get_param(*pc + 1, mode_1, &program, relative_base);
+                *relative_base += param_1;
+                *pc += 2;
+            }
+            99 => {
+                break;
+            }
+            _ => {
+                println!("Unknown op {}", op_code);
+                println!("{}", program[pc]);
+                panic!();
+            }
+        }
+    }
+
+    (true, output)
+}
+
+fn part_1(input: &Vec<Op>) -> usize {
+    let mut panels = HashMap::new();
+    robot(input, &mut panels);
+    panels.len()
+}
+
+fn part_2(input: &Vec<Op>) {
+    let mut panels = HashMap::new();
+    // Set initial panel white.
+    panels.insert((0, 0), 1);
+    robot(input, &mut panels);
+    // Display the panel results.
+    // Check max/min coordinates.
+    let mut min_x = Op::max_value();
+    let mut max_x = Op::min_value();
+    let mut min_y = Op::max_value();
+    let mut max_y = Op::min_value();
+    for panel in panels.keys() {
+        min_x = min_x.min(panel.0);
+        max_x = max_x.max(panel.0);
+        min_y = min_y.min(panel.1);
+        max_y = max_y.max(panel.1);
+    }
+    // Print the panels.
+    for y in (min_y..=max_y).rev() {
+        for x in min_x..=max_x {
+            match *panels.get(&(x, y)).unwrap_or(&0) {
+                1 => print!("██"),
+                _ => print!("  "),
+            }
+        }
+        println!();
+    }
+}
diff --git a/day-11/input.txt b/day-11/input.txt
@@ -0,0 +1 @@
+3,8,1005,8,291,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1002,8,1,28,1,1003,20,10,2,1103,19,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,1001,8,0,59,1,1004,3,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,84,1006,0,3,1,1102,12,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,101,0,8,114,3,8,1002,8,-1,10,101,1,10,10,4,10,108,1,8,10,4,10,101,0,8,135,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,158,2,9,9,10,2,2,10,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,188,1006,0,56,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,212,1006,0,76,2,1005,8,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,241,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1002,8,1,264,1006,0,95,1,1001,12,10,101,1,9,9,1007,9,933,10,1005,10,15,99,109,613,104,0,104,1,21102,838484206484,1,1,21102,1,308,0,1106,0,412,21102,1,937267929116,1,21101,0,319,0,1105,1,412,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21102,206312598619,1,1,21102,366,1,0,1105,1,412,21101,179410332867,0,1,21102,377,1,0,1105,1,412,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,709580595968,1,21102,1,400,0,1106,0,412,21102,868389384552,1,1,21101,411,0,0,1106,0,412,99,109,2,21202,-1,1,1,21102,1,40,2,21102,1,443,3,21101,0,433,0,1106,0,476,109,-2,2105,1,0,0,1,0,0,1,109,2,3,10,204,-1,1001,438,439,454,4,0,1001,438,1,438,108,4,438,10,1006,10,470,1102,0,1,438,109,-2,2106,0,0,0,109,4,1202,-1,1,475,1207,-3,0,10,1006,10,493,21102,0,1,-3,21202,-3,1,1,21201,-2,0,2,21101,0,1,3,21102,1,512,0,1106,0,517,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,540,2207,-4,-2,10,1006,10,540,22101,0,-4,-4,1106,0,608,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21101,0,559,0,1106,0,517,21201,1,0,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,578,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,600,21201,-1,0,1,21102,600,1,0,106,0,475,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0