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:
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