From d6a738f5ea979a77bbc103f19a8a8d22bca3c890 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sat, 1 Dec 2018 22:02:53 +0100 Subject: [PATCH 01/42] day 1, part 1 From d6d9f8e9ec896ab45f0cb9ec226d3074c1c056b9 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sun, 1 Dec 2019 09:02:40 +0100 Subject: [PATCH 02/42] feat: completed day 1 --- README.md | 6 ++++ day01/src/main.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++ day01/src/part_02.rs | 30 +++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 README.md create mode 100644 day01/src/main.rs create mode 100644 day01/src/part_02.rs diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4c938b --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Advent of Code 2019 + + +## Progress: + +- [Day 1](https://github.com/ankjevel/adventofcode/tree/2019/day01) 🌟 🌟 diff --git a/day01/src/main.rs b/day01/src/main.rs new file mode 100644 index 0000000..affd444 --- /dev/null +++ b/day01/src/main.rs @@ -0,0 +1,68 @@ +use std::io; + +mod part_01; +mod part_02; + +fn main() -> io::Result<()> { + let input = parse_input(include_str!("../../input/day_01")); + + let part_01_fuel = part_01::main(&input).unwrap().iter().sum::(); + let part_02_sum_of_fuel = part_02::main(&input).unwrap(); + + println!("part 1; fuel: {}", part_01_fuel); + println!("part 2; sum: {}", part_02_sum_of_fuel); + + Ok(()) +} + +fn parse_input(string: &str) -> Vec { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|string| string.parse::().unwrap()) + .collect::>() +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_DATA_01: &'static str = " + 12 + 14 + 1969 + 100756"; + + const EXAMPLE_DATA_02: &'static str = " + 14 + 1969 + 100756"; + + #[test] + fn examples_for_part_1() { + assert_eq!( + part_01::main(&parse_input(EXAMPLE_DATA_01)).unwrap(), + [2, 2, 654, 33583] + ) + } + + #[test] + fn reduce_results_for_example_part_1() { + assert_eq!( + part_01::main(&parse_input(EXAMPLE_DATA_01)) + .unwrap() + .iter() + .sum::(), + 2 + 2 + 654 + 33583 + ) + } + + #[test] + fn example_for_part_2() { + assert_eq!( + part_02::main(&parse_input(EXAMPLE_DATA_02)).unwrap(), + 2 + 966 + 50346 + ) + } +} diff --git a/day01/src/part_02.rs b/day01/src/part_02.rs new file mode 100644 index 0000000..1215074 --- /dev/null +++ b/day01/src/part_02.rs @@ -0,0 +1,30 @@ +use std::io; + +fn calculate_fuel(input: i32, results: &mut Vec) { + let fuel = ((input as f64 / 3.0).floor() as i32) - 2; + + if fuel <= 0 { + return; + } + + &results.push(fuel); + + calculate_fuel(fuel, results) +} + +fn required_fuel(input: i32) -> i32 { + let mut results = Vec::new(); + + calculate_fuel(input, &mut results); + + results.iter().sum::() +} + +pub fn main(input: &Vec) -> io::Result { + let fuel: Vec = input + .iter() + .map(|&mass| required_fuel(mass.clone())) + .collect(); + + Ok(fuel.iter().sum::()) +} From 569e7656139087081f7f072ae9fe882ebbaec793 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 2 Dec 2019 10:47:54 +0100 Subject: [PATCH 03/42] feat: completed day 2 --- README.md | 1 + day01/src/part_01.rs | 7 +++++ day02/Cargo.toml | 9 ++++++ day02/src/main.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++ day02/src/part_01.rs | 28 ++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 day01/src/part_01.rs create mode 100644 day02/Cargo.toml create mode 100644 day02/src/main.rs create mode 100644 day02/src/part_01.rs diff --git a/README.md b/README.md index d4c938b..394af11 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,4 @@ ## Progress: - [Day 1](https://github.com/ankjevel/adventofcode/tree/2019/day01) 🌟 🌟 +- [Day 2](https://github.com/ankjevel/adventofcode/tree/2019/day02) 🌟 🌟 diff --git a/day01/src/part_01.rs b/day01/src/part_01.rs new file mode 100644 index 0000000..e4b26df --- /dev/null +++ b/day01/src/part_01.rs @@ -0,0 +1,7 @@ +use std::io; + +pub fn main(input: &Vec) -> io::Result> { + Ok(input.iter() + .map(|&mass| ((mass.clone() as f64 / 3.0).floor() as i32) - 2) + .collect()) +} diff --git a/day02/Cargo.toml b/day02/Cargo.toml new file mode 100644 index 0000000..bf0547c --- /dev/null +++ b/day02/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day02" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day02/src/main.rs b/day02/src/main.rs new file mode 100644 index 0000000..076e209 --- /dev/null +++ b/day02/src/main.rs @@ -0,0 +1,70 @@ +use std::io; + +mod part_01; + +fn main() -> io::Result<()> { + let input = parse_input(include_str!("../../input/day_02")); + + let mut input_for_part_01 = input[0].clone(); + input_for_part_01[1] = 12; + input_for_part_01[2] = 2; + + let output_for_part_01 = part_01::main(&input_for_part_01).unwrap(); + + println!("part01: {}", output_for_part_01[0]); + + for noun in 0..=99 { + for verb in 0..=99 { + let mut input_for_part_02 = input[0].clone(); + input_for_part_02[1] = noun; + input_for_part_02[2] = verb; + let output = part_01::main(&input_for_part_02).unwrap()[0]; + if output == 19690720 { + println!("part02: {}", (100 * noun + verb)); + break; + } + } + } + + Ok(()) +} + +fn parse_input(string: &str) -> Vec> { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|string| { + string + .split(",") + .map(|part| part.parse::().unwrap()) + .collect::>() + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_DATA_01: &'static str = " + 1,0,0,0,99 + 2,3,0,3,99 + 2,4,4,5,99,0 + 1,1,1,4,99,5,6,0,99"; + + #[test] + fn examples_for_part_1() { + let input = parse_input(EXAMPLE_DATA_01); + + let results = input + .iter() + .map(|row| part_01::main(&row).unwrap()) + .collect::>>(); + + assert_eq!(results[0], [2, 0, 0, 0, 99]); + assert_eq!(results[1], [2, 3, 0, 6, 99]); + assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); + assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); + } +} diff --git a/day02/src/part_01.rs b/day02/src/part_01.rs new file mode 100644 index 0000000..f084ae0 --- /dev/null +++ b/day02/src/part_01.rs @@ -0,0 +1,28 @@ +use std::io; + +pub fn main(input: &Vec) -> io::Result> { + let mut copy_of_input = input.clone(); + let mut i = 0; + + loop { + let opcode = copy_of_input[i]; + + if opcode == 99 { + break; + } + + let x = copy_of_input[copy_of_input[i + 1] as usize]; + let y = copy_of_input[copy_of_input[i + 2] as usize]; + let result = copy_of_input[i + 3] as usize; + + copy_of_input[result] = match opcode { + 1 => x + y, + 2 => x * y, + _ => panic!("unexpected opcode: {}", opcode), + }; + + i = i + 4; + } + + Ok(copy_of_input) +} From 1e0814991735b64641928365ea781294abe177ba Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 2 Dec 2019 10:59:04 +0100 Subject: [PATCH 04/42] chore: made it less of a mess --- day02/src/main.rs | 37 +++++++++++++++++++++++-------------- day02/src/part_01.rs | 23 +++++++++-------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/day02/src/main.rs b/day02/src/main.rs index 076e209..970bc4e 100644 --- a/day02/src/main.rs +++ b/day02/src/main.rs @@ -1,3 +1,5 @@ +#![feature(label_break_value)] + use std::io; mod part_01; @@ -5,23 +7,30 @@ mod part_01; fn main() -> io::Result<()> { let input = parse_input(include_str!("../../input/day_02")); - let mut input_for_part_01 = input[0].clone(); - input_for_part_01[1] = 12; - input_for_part_01[2] = 2; + 'part_01: { + let mut input_for_part_01 = input[0].clone(); + input_for_part_01[1] = 12; + input_for_part_01[2] = 2; + + let output_for_part_01 = part_01::main(&input_for_part_01).unwrap()[0]; + + println!("part_01: {}", output_for_part_01); + } - let output_for_part_01 = part_01::main(&input_for_part_01).unwrap(); + 'part_02: { + let look_for = 19690720; + for noun in 0..=99 { + for verb in 0..=99 { + let mut input_for_part_02 = input[0].clone(); + input_for_part_02[1] = noun; + input_for_part_02[2] = verb; - println!("part01: {}", output_for_part_01[0]); + let output = part_01::main(&input_for_part_02).unwrap()[0]; - for noun in 0..=99 { - for verb in 0..=99 { - let mut input_for_part_02 = input[0].clone(); - input_for_part_02[1] = noun; - input_for_part_02[2] = verb; - let output = part_01::main(&input_for_part_02).unwrap()[0]; - if output == 19690720 { - println!("part02: {}", (100 * noun + verb)); - break; + if output == look_for { + println!("part_02: {}", (100 * noun + verb)); + break; + } } } } diff --git a/day02/src/part_01.rs b/day02/src/part_01.rs index f084ae0..191557d 100644 --- a/day02/src/part_01.rs +++ b/day02/src/part_01.rs @@ -2,27 +2,22 @@ use std::io; pub fn main(input: &Vec) -> io::Result> { let mut copy_of_input = input.clone(); - let mut i = 0; - + let mut current_position = 0; loop { - let opcode = copy_of_input[i]; - + let opcode = copy_of_input[current_position]; if opcode == 99 { break; } - let x = copy_of_input[copy_of_input[i + 1] as usize]; - let y = copy_of_input[copy_of_input[i + 2] as usize]; - let result = copy_of_input[i + 3] as usize; - - copy_of_input[result] = match opcode { - 1 => x + y, - 2 => x * y, + let noun = copy_of_input[copy_of_input[current_position + 1] as usize]; + let verb = copy_of_input[copy_of_input[current_position + 2] as usize]; + let output_position = copy_of_input[current_position + 3] as usize; + copy_of_input[output_position] = match opcode { + 1 => noun + verb, + 2 => noun * verb, _ => panic!("unexpected opcode: {}", opcode), }; - - i = i + 4; + current_position += 4; } - Ok(copy_of_input) } From a55c6135420f07eea7202263dc0f76ce0d945683 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 2 Dec 2019 11:41:32 +0100 Subject: [PATCH 05/42] chore: simplified code, since there where only _one_ implementation of th program --- day02/src/main.rs | 92 +++++++++++++++++++++++++++++++------------- day02/src/part_01.rs | 23 ----------- 2 files changed, 65 insertions(+), 50 deletions(-) delete mode 100644 day02/src/part_01.rs diff --git a/day02/src/main.rs b/day02/src/main.rs index 970bc4e..6800ee1 100644 --- a/day02/src/main.rs +++ b/day02/src/main.rs @@ -1,41 +1,44 @@ #![feature(label_break_value)] -use std::io; +use std::io::Result; -mod part_01; - -fn main() -> io::Result<()> { - let input = parse_input(include_str!("../../input/day_02")); - - 'part_01: { - let mut input_for_part_01 = input[0].clone(); - input_for_part_01[1] = 12; - input_for_part_01[2] = 2; +struct Program { + input: Vec, + pointer: usize +} - let output_for_part_01 = part_01::main(&input_for_part_01).unwrap()[0]; +impl Program { + fn new(input: &Vec) -> Program { + Program { input: input.clone(), pointer: 0 } + } - println!("part_01: {}", output_for_part_01); + fn patch(&mut self, index: usize, value: u32) { + self.input[index] = value; } - 'part_02: { - let look_for = 19690720; - for noun in 0..=99 { - for verb in 0..=99 { - let mut input_for_part_02 = input[0].clone(); - input_for_part_02[1] = noun; - input_for_part_02[2] = verb; + fn run(&mut self) -> u32 { + self.pointer = 0; - let output = part_01::main(&input_for_part_02).unwrap()[0]; + loop { + let opcode = self.input[self.pointer]; - if output == look_for { - println!("part_02: {}", (100 * noun + verb)); - break; - } + if opcode == 99 { + break self.input[self.pointer]; } + + let noun = self.input[self.input[self.pointer + 1] as usize]; + let verb = self.input[self.input[self.pointer + 2] as usize]; + let output_position = self.input[self.pointer + 3] as usize; + + self.input[output_position] = match opcode { + 1 => noun + verb, + 2 => noun * verb, + _ => panic!("unexpected opcode: {}", opcode), + }; + + self.pointer += 4; } } - - Ok(()) } fn parse_input(string: &str) -> Vec> { @@ -52,6 +55,36 @@ fn parse_input(string: &str) -> Vec> { .collect() } +fn main() -> Result<()> { + let input = parse_input(include_str!("../../input/day_02")); + + 'part_01: { + let mut part_01 = Program::new(&input[0]); + part_01.patch(1, 12); + part_01.patch(2, 2); + + println!("part_01: {}", part_01.run()); + } + + 'part_02: { + let look_for = 19690720; + for noun in 0..=99 { + for verb in 0..=99 { + let mut part_02 = Program::new(&input[0]); + part_02.patch(1, noun); + part_02.patch(2, verb); + + if part_02.run() == look_for { + println!("part_02: {}", (100 * noun + verb)); + break; + } + } + } + } + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; @@ -68,7 +101,12 @@ mod tests { let results = input .iter() - .map(|row| part_01::main(&row).unwrap()) + .map(|row| { + let mut program = Program::new(&row); + program.run(); + + program.input + }) .collect::>>(); assert_eq!(results[0], [2, 0, 0, 0, 99]); diff --git a/day02/src/part_01.rs b/day02/src/part_01.rs deleted file mode 100644 index 191557d..0000000 --- a/day02/src/part_01.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::io; - -pub fn main(input: &Vec) -> io::Result> { - let mut copy_of_input = input.clone(); - let mut current_position = 0; - loop { - let opcode = copy_of_input[current_position]; - if opcode == 99 { - break; - } - - let noun = copy_of_input[copy_of_input[current_position + 1] as usize]; - let verb = copy_of_input[copy_of_input[current_position + 2] as usize]; - let output_position = copy_of_input[current_position + 3] as usize; - copy_of_input[output_position] = match opcode { - 1 => noun + verb, - 2 => noun * verb, - _ => panic!("unexpected opcode: {}", opcode), - }; - current_position += 4; - } - Ok(copy_of_input) -} From 612df74c0a06ca3a6294d2454b01c48d64db3851 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 2 Dec 2019 15:32:46 +0100 Subject: [PATCH 06/42] fix: sloppy rewrite... --- day02/src/main.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/day02/src/main.rs b/day02/src/main.rs index 6800ee1..859cca5 100644 --- a/day02/src/main.rs +++ b/day02/src/main.rs @@ -4,12 +4,15 @@ use std::io::Result; struct Program { input: Vec, - pointer: usize + pointer: usize, } impl Program { fn new(input: &Vec) -> Program { - Program { input: input.clone(), pointer: 0 } + Program { + input: input.clone(), + pointer: 0, + } } fn patch(&mut self, index: usize, value: u32) { @@ -23,7 +26,7 @@ impl Program { let opcode = self.input[self.pointer]; if opcode == 99 { - break self.input[self.pointer]; + break self.input[0]; } let noun = self.input[self.input[self.pointer + 1] as usize]; @@ -48,7 +51,7 @@ fn parse_input(string: &str) -> Vec> { .filter(|string| !string.is_empty()) .map(|string| { string - .split(",") + .split(',') .map(|part| part.parse::().unwrap()) .collect::>() }) @@ -114,4 +117,16 @@ mod tests { assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); } + + #[test] + fn patch_paramters() { + let mut program = Program::new(&vec![1, 0, 0, 0, 99]); + program.patch(1, 3); + program.patch(2, 1); + + let output = program.run(); + + assert_eq!(program.input, [3, 3, 1, 0, 99]); + assert_eq!(output, 3); + } } From 9ecf42a8e740eb3e46c3fa6977b841529b8559f2 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Tue, 3 Dec 2019 10:26:35 +0100 Subject: [PATCH 07/42] feat: added part 1 of day 3 (overly ambitious) --- day03/Cargo.toml | 9 +++++ day03/src/main.rs | 70 ++++++++++++++++++++++++++++++++ day03/src/manhattan.rs | 5 +++ day03/src/part_01.rs | 92 ++++++++++++++++++++++++++++++++++++++++++ day03/src/structs.rs | 49 ++++++++++++++++++++++ 5 files changed, 225 insertions(+) create mode 100644 day03/Cargo.toml create mode 100644 day03/src/main.rs create mode 100644 day03/src/manhattan.rs create mode 100644 day03/src/part_01.rs create mode 100644 day03/src/structs.rs diff --git a/day03/Cargo.toml b/day03/Cargo.toml new file mode 100644 index 0000000..da1cf06 --- /dev/null +++ b/day03/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day03" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day03/src/main.rs b/day03/src/main.rs new file mode 100644 index 0000000..99a7a5f --- /dev/null +++ b/day03/src/main.rs @@ -0,0 +1,70 @@ +#![feature(label_break_value)] + +use std::io::Result; + +pub mod manhattan; +mod part_01; +pub mod structs; + +use part_01::main as part_01; +use structs::Direction::{Down, Left, Right, Up}; +use structs::Movement; + +pub use structs::Point; + +fn main() -> Result<()> { + let wires = parse_input(include_str!("../../input/day_03")); + + println!("part_01: {:?}", part_01(&wires).unwrap()); + Ok(()) +} + +fn parse_input(string: &str) -> Vec> { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|string| { + let movement = string + .split(',') + .map(|part| Movement::new(part)) + .collect::>(); + + let mut position = Point::new(); + let mut points = Vec::new(); + + for current in movement.iter() { + match current.direction { + Down => position.y -= current.steps, + Left => position.x -= current.steps, + Right => position.x += current.steps, + Up => position.y += current.steps, + } + points.push(position.clone()); + } + + points + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_DATA_01: &'static str = " + R75,D30,R83,U83,L12,D49,R71,U7,L72 + U62,R66,U55,R34,D71,R55,D58,R83 + "; + + const EXAMPLE_DATA_02: &'static str = " + R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51 + U98,R91,D20,R16,D67,R40,U7,R15,U6,R77 + "; + + #[test] + fn it_gets_the_correct_result_based_on_examples() { + assert_eq!(159, part_01(&parse_input(EXAMPLE_DATA_01)).unwrap()); + assert_eq!(135, part_01(&parse_input(EXAMPLE_DATA_02)).unwrap()); + } +} diff --git a/day03/src/manhattan.rs b/day03/src/manhattan.rs new file mode 100644 index 0000000..f138753 --- /dev/null +++ b/day03/src/manhattan.rs @@ -0,0 +1,5 @@ +use super::Point; + +pub fn manhattan(point: Point, current: Point) -> u64 { + ((point.x as i64 - current.x as i64).abs() + (point.y as i64 - current.y as i64).abs()) as u64 +} diff --git a/day03/src/part_01.rs b/day03/src/part_01.rs new file mode 100644 index 0000000..c84f0f7 --- /dev/null +++ b/day03/src/part_01.rs @@ -0,0 +1,92 @@ +use std::cmp::{max, min}; +use std::collections::HashMap; +use std::i32::MAX; +use std::io::Result; + +use super::manhattan::manhattan; +use super::Point; + +enum State { + Occupied(u8), + Intersect(Point), + Start, + Empty, +} + +use State::{Empty, Intersect, Occupied, Start}; + +#[allow(dead_code)] +fn min_max(input: &Vec>) -> (i32, i32, i32, i32) { + let (max_x, max_y) = input.iter().fold((0, 0), |(max_x, max_y), point| { + point.iter().fold((0, 0), |(max_x_x, max_y_y), point| { + ( + max(max_x, max(max_x_x, point.x)), + max(max_y, max(max_y_y, point.y)), + ) + }) + }); + + let (min_x, min_y) = input.iter().fold((0, 0), |(min_x, min_y), point| { + point.iter().fold((0, 0), |(min_x_x, min_y_y), point| { + ( + min(min_x, min(min_x_x, point.x)), + min(min_y, min(min_y_y, point.y)), + ) + }) + }); + + (min_x, min_y, max_x, max_y) +} + +pub fn main(input: &Vec>) -> Result { + let mut grid = HashMap::new(); + let mut intersecting = Vec::new(); + let start_point = Point { x: 0, y: 0 }; + + grid.insert(start_point, Start); + + // # for printing the board, slow process + // let (min_x, min_y, max_x, max_y) = min_max(&input); + // for x in min_x..max_x { + // for y in min_y..max_y { + // let state = if x == 0 && y == 0 { Start } else { Empty }; + // let point = Point { x, y }; + // grid.insert(point, state); + // } + // } + + let mut current_wire = 0; + for points in input.iter() { + let mut prev = Point::new(); + + for current in points.iter().peekable() { + for x in min(prev.x, current.x)..=max(prev.x, current.x) { + for y in min(prev.y, current.y)..=max(prev.y, current.y) { + let point = Point { x, y }; + let state = grid.entry(point).or_insert(Empty); + + match state { + Empty => *state = Occupied(current_wire), + Occupied(occupied_by) => { + if *occupied_by == current_wire { + continue; + } + *state = Intersect(point); + intersecting.push(point); + } + _ => {} + }; + } + } + prev = *current; + } + current_wire += 1; + } + + let min = intersecting.iter().fold( + manhattan(start_point, Point { x: MAX, y: MAX }), + |sum, &point| min(sum, manhattan(start_point, point)), + ); + + Ok(min) +} diff --git a/day03/src/structs.rs b/day03/src/structs.rs new file mode 100644 index 0000000..892bc07 --- /dev/null +++ b/day03/src/structs.rs @@ -0,0 +1,49 @@ +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Direction { + Up, + Down, + Left, + Right +} + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct Movement { + pub direction: Direction, + pub steps: i32, +} + +impl Movement { + pub fn new (input: &str) -> Movement { + let mut chars = input.chars(); + + let direction = match chars.next().unwrap() { + 'U' => Direction::Up, + 'D' => Direction::Down, + 'L' => Direction::Left, + 'R' => Direction::Right, + _ => panic!("direction not defined") + }; + + let steps = chars.as_str().parse::().unwrap(); + + Movement { + direction, + steps, + } + } +} + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct Point { + pub x: i32, // L-R + pub y: i32, // U-D +} + +impl Point { + pub fn new () -> Point { + Point { + x: 0, + y: 0, + } + } +} From 75083d7d6d51d426c78d111212d2ed6e4d49f5e7 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Tue, 3 Dec 2019 17:03:04 +0100 Subject: [PATCH 08/42] feat: simplified things --- day03/src/main.rs | 21 ++++++++++-- day03/src/part_01.rs | 37 ++------------------ day03/src/part_02.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 36 deletions(-) create mode 100644 day03/src/part_02.rs diff --git a/day03/src/main.rs b/day03/src/main.rs index 99a7a5f..77b392e 100644 --- a/day03/src/main.rs +++ b/day03/src/main.rs @@ -4,9 +4,11 @@ use std::io::Result; pub mod manhattan; mod part_01; +mod part_02; pub mod structs; use part_01::main as part_01; +use part_02::main as part_02; use structs::Direction::{Down, Left, Right, Up}; use structs::Movement; @@ -16,6 +18,8 @@ fn main() -> Result<()> { let wires = parse_input(include_str!("../../input/day_03")); println!("part_01: {:?}", part_01(&wires).unwrap()); + println!("part_02: {:?}", part_02(&wires).unwrap()); + Ok(()) } @@ -59,12 +63,25 @@ mod tests { const EXAMPLE_DATA_02: &'static str = " R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51 - U98,R91,D20,R16,D67,R40,U7,R15,U6,R77 + U98,R91,D20,R16,D67,R40,U7,R15,U6,R7 + "; + + const EXAMPLE_DATA_00: &'static str = " + R8,U5,L5,D3 + U7,R6,D4,L4 "; #[test] - fn it_gets_the_correct_result_based_on_examples() { + fn it_gets_the_correct_result_based_on_examples_for_part_1() { + assert_eq!(6, part_01(&parse_input(EXAMPLE_DATA_00)).unwrap()); assert_eq!(159, part_01(&parse_input(EXAMPLE_DATA_01)).unwrap()); assert_eq!(135, part_01(&parse_input(EXAMPLE_DATA_02)).unwrap()); } + + #[test] + fn it_gets_the_correct_result_based_on_examples_for_part_2() { + assert_eq!(30, part_02(&parse_input(EXAMPLE_DATA_00)).unwrap()); + assert_eq!(610, part_02(&parse_input(EXAMPLE_DATA_01)).unwrap()); + assert_eq!(410, part_02(&parse_input(EXAMPLE_DATA_02)).unwrap()); + } } diff --git a/day03/src/part_01.rs b/day03/src/part_01.rs index c84f0f7..65ab073 100644 --- a/day03/src/part_01.rs +++ b/day03/src/part_01.rs @@ -15,29 +15,6 @@ enum State { use State::{Empty, Intersect, Occupied, Start}; -#[allow(dead_code)] -fn min_max(input: &Vec>) -> (i32, i32, i32, i32) { - let (max_x, max_y) = input.iter().fold((0, 0), |(max_x, max_y), point| { - point.iter().fold((0, 0), |(max_x_x, max_y_y), point| { - ( - max(max_x, max(max_x_x, point.x)), - max(max_y, max(max_y_y, point.y)), - ) - }) - }); - - let (min_x, min_y) = input.iter().fold((0, 0), |(min_x, min_y), point| { - point.iter().fold((0, 0), |(min_x_x, min_y_y), point| { - ( - min(min_x, min(min_x_x, point.x)), - min(min_y, min(min_y_y, point.y)), - ) - }) - }); - - (min_x, min_y, max_x, max_y) -} - pub fn main(input: &Vec>) -> Result { let mut grid = HashMap::new(); let mut intersecting = Vec::new(); @@ -45,21 +22,11 @@ pub fn main(input: &Vec>) -> Result { grid.insert(start_point, Start); - // # for printing the board, slow process - // let (min_x, min_y, max_x, max_y) = min_max(&input); - // for x in min_x..max_x { - // for y in min_y..max_y { - // let state = if x == 0 && y == 0 { Start } else { Empty }; - // let point = Point { x, y }; - // grid.insert(point, state); - // } - // } - let mut current_wire = 0; for points in input.iter() { let mut prev = Point::new(); - for current in points.iter().peekable() { + for current in points.iter() { for x in min(prev.x, current.x)..=max(prev.x, current.x) { for y in min(prev.y, current.y)..=max(prev.y, current.y) { let point = Point { x, y }; @@ -78,8 +45,10 @@ pub fn main(input: &Vec>) -> Result { }; } } + prev = *current; } + current_wire += 1; } diff --git a/day03/src/part_02.rs b/day03/src/part_02.rs new file mode 100644 index 0000000..80484d0 --- /dev/null +++ b/day03/src/part_02.rs @@ -0,0 +1,80 @@ +use std::cmp::{max, min}; +use std::collections::HashMap; +use std::io::Result; +use std::u64::MAX; + +use super::Point; + +enum State { + Occupied(u8, u64), + Intersect, + Start, + Empty, +} + +use State::{Empty, Intersect, Occupied, Start}; + +fn calc_steps(from: i32, to: i32) -> i64 { + (to as i64 - from as i64).abs() +} + +pub fn main(input: &Vec>) -> Result { + let mut grid = HashMap::new(); + let mut shortest_route = MAX; + + grid.insert(Point::new(), Start); + + let mut current_wire = 0; + for wire in input.iter() { + let mut prev = Point::new(); + let mut steps_total = 0; + + for current in wire.iter() { + let x_neg = prev.x > current.x; + let y_neg = prev.y > current.y; + + let mut x = prev.x; + let mut y = prev.y; + + let mut steps_x = 0; + let mut steps_y = 0; + + let mut check_current_state = |point: Point, current_steps: u64| { + let state = grid.entry(point).or_insert(Empty); + match state { + Empty => *state = Occupied(current_wire, current_steps), + Occupied(occupied_by, occupied_by_steps) => { + if *occupied_by != current_wire { + shortest_route = + min(shortest_route, *occupied_by_steps + current_steps); + *state = Intersect; + } + } + _ => {} + }; + }; + + let check_current_steps = + |steps_x: i64, steps_y: i64| -> u64 { (steps_total + (steps_x + steps_y)) as u64 }; + + for _ in min(prev.x, current.x)..max(prev.x, current.x) { + x = if x_neg { x - 1 } else { x + 1 }; + steps_x = calc_steps(prev.x, x); + check_current_state(Point { x, y }, check_current_steps(steps_x, steps_y)); + } + + for _ in min(prev.y, current.y)..max(prev.y, current.y) { + y = if y_neg { y - 1 } else { y + 1 }; + steps_y = calc_steps(prev.y, y); + check_current_state(Point { x, y }, check_current_steps(steps_x, steps_y)); + } + + steps_total += steps_x + steps_y; + prev = *current; + } + + current_wire += 1; + } + + Ok(shortest_route) +} From 8bec8362a99706ca4fecc316467924173c2730db Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Wed, 4 Dec 2019 08:09:03 +0100 Subject: [PATCH 09/42] feat: part 1 of day 4 --- day04/Cargo.toml | 9 +++++++++ day04/src/main.rs | 30 ++++++++++++++++++++++++++++++ day04/src/part_01.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 day04/Cargo.toml create mode 100644 day04/src/main.rs create mode 100644 day04/src/part_01.rs diff --git a/day04/Cargo.toml b/day04/Cargo.toml new file mode 100644 index 0000000..b6ea3d6 --- /dev/null +++ b/day04/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day04" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day04/src/main.rs b/day04/src/main.rs new file mode 100644 index 0000000..8e2d042 --- /dev/null +++ b/day04/src/main.rs @@ -0,0 +1,30 @@ +#![feature(label_break_value)] + +use std::io::Result; + +mod part_01; + +use part_01::main as part_01; + +const PUZZLE_INPUT: &'static str = "347312-805915"; + +fn main() -> Result<()> { + 'part_01: { + println!("part_01: {}", part_01(&PUZZLE_INPUT).unwrap()); + } + + 'part_02: {} + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_gets_the_right_answer_for_examples() { + assert_eq!(true, part_01::meet_criteria("111111")); + assert_eq!(false, part_01::meet_criteria("223450")); + assert_eq!(false, part_01::meet_criteria("123789")); + } +} diff --git a/day04/src/part_01.rs b/day04/src/part_01.rs new file mode 100644 index 0000000..bc84373 --- /dev/null +++ b/day04/src/part_01.rs @@ -0,0 +1,41 @@ +use std::io::Result; + +pub fn meet_criteria(input: &str) -> bool { + let bytes: Vec<_> = input + .chars() + .map(|c| c.to_string().parse::().unwrap()) + .collect(); + + let mut pairs = false; + let mut never_decrese = true; + for i in 1..bytes.len() { + let current = bytes[i]; + let prev = bytes[i - 1]; + if never_decrese == false { + break; + } + + pairs = pairs || current == prev; + + never_decrese = current >= prev; + } + + pairs && never_decrese +} + +pub fn main(input: &str) -> Result { + let range = &input + .split('-') + .map(|part| part.parse::().unwrap()) + .collect::>(); + + let mut count = 0; + for i in range[0]..range[1] { + let string = i.to_string(); + if meet_criteria(&string) { + count += 1; + } + } + + Ok(count) +} From 88f99a3ee76c5bd8e3e69e2ee2f73551d9fa308c Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Wed, 4 Dec 2019 22:12:02 +0100 Subject: [PATCH 10/42] feat: added part 2 (after some modification) --- day04/src/main.rs | 33 ++++++++++++++++++++------------ day04/src/part_01.rs | 45 ++++++++++++++++++-------------------------- day04/src/part_02.rs | 28 +++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 39 deletions(-) create mode 100644 day04/src/part_02.rs diff --git a/day04/src/main.rs b/day04/src/main.rs index 8e2d042..2429546 100644 --- a/day04/src/main.rs +++ b/day04/src/main.rs @@ -1,30 +1,39 @@ -#![feature(label_break_value)] - use std::io::Result; mod part_01; +mod part_02; use part_01::main as part_01; - -const PUZZLE_INPUT: &'static str = "347312-805915"; +use part_02::main as part_02; fn main() -> Result<()> { - 'part_01: { - println!("part_01: {}", part_01(&PUZZLE_INPUT).unwrap()); - } + let input = vec![347312, 805915]; + + println!("part_01: {}", part_01(&input).unwrap()); + println!("part_02: {}", part_02(&input).unwrap()); - 'part_02: {} Ok(()) } #[cfg(test)] mod tests { - use super::*; + use super::part_01::meet_criteria as part_01; + use super::part_02::meet_criteria as part_02; #[test] fn it_gets_the_right_answer_for_examples() { - assert_eq!(true, part_01::meet_criteria("111111")); - assert_eq!(false, part_01::meet_criteria("223450")); - assert_eq!(false, part_01::meet_criteria("123789")); + assert_eq!(part_01("111111"), true); + assert_eq!(part_01("223450"), false); + assert_eq!(part_01("123789"), false); + assert_eq!(part_01("122345"), true); + assert_eq!(part_01("135679"), false); + assert_eq!(part_01("111123"), true); + } + + #[test] + fn it_gets_the_right_answer_for_examples_on_part_2() { + assert_eq!(part_02("112233"), true); + assert_eq!(part_02("123444"), false); + assert_eq!(part_02("111122"), true); } } diff --git a/day04/src/part_01.rs b/day04/src/part_01.rs index bc84373..99e3e02 100644 --- a/day04/src/part_01.rs +++ b/day04/src/part_01.rs @@ -1,41 +1,32 @@ use std::io::Result; -pub fn meet_criteria(input: &str) -> bool { - let bytes: Vec<_> = input +pub fn to_bytes(input: &str) -> Vec { + input .chars() .map(|c| c.to_string().parse::().unwrap()) - .collect(); + .collect() +} +pub fn meet_criteria(input: &str) -> bool { + let bytes = to_bytes(&input); let mut pairs = false; - let mut never_decrese = true; + let mut never_decresed = true; for i in 1..bytes.len() { - let current = bytes[i]; - let prev = bytes[i - 1]; - if never_decrese == false { + if !never_decresed { break; } - + let current = bytes[i]; + let prev = bytes[i - 1]; + never_decresed = current >= prev; pairs = pairs || current == prev; - - never_decrese = current >= prev; } - - pairs && never_decrese + pairs && never_decresed } -pub fn main(input: &str) -> Result { - let range = &input - .split('-') - .map(|part| part.parse::().unwrap()) - .collect::>(); - - let mut count = 0; - for i in range[0]..range[1] { - let string = i.to_string(); - if meet_criteria(&string) { - count += 1; - } - } - - Ok(count) +pub fn main(input: &Vec) -> Result { + Ok((input[0]..input[1]) + .collect::>() + .iter() + .filter(|i| meet_criteria(&i.to_string())) + .count() as u32) } diff --git a/day04/src/part_02.rs b/day04/src/part_02.rs new file mode 100644 index 0000000..17482ae --- /dev/null +++ b/day04/src/part_02.rs @@ -0,0 +1,28 @@ +use std::io::Result; + +use super::part_01::to_bytes; + +pub fn meet_criteria(input: &str) -> bool { + let bytes = to_bytes(&input); + let mut ordered_bytes = to_bytes(&input); + ordered_bytes.sort(); + + if bytes != ordered_bytes { + return false; + } + + let mut repeats = vec![0; 10]; + for i in 0..bytes.len() { + repeats[bytes[i] as usize] += 1; + } + + &2 == repeats.iter().max().unwrap() || repeats.contains(&2) +} + +pub fn main(input: &Vec) -> Result { + Ok((input[0]..input[1]) + .collect::>() + .iter() + .filter(|i| meet_criteria(&i.to_string())) + .count() as u32) +} From 0a2809e29583ba633d14bc32e2f5964ab4bff290 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Wed, 4 Dec 2019 22:48:06 +0100 Subject: [PATCH 11/42] chore: renamed folders --- README.md | 6 ++++-- day01/src/part_01.rs | 7 ------- day_01/Cargo.toml | 6 ++++++ {day01 => day_01}/src/main.rs | 4 ++-- day_01/src/part_01.rs | 7 +++++++ {day01 => day_01}/src/part_02.rs | 0 {day02 => day_02}/Cargo.toml | 3 --- {day02 => day_02}/src/main.rs | 0 {day03 => day_03}/Cargo.toml | 3 --- {day03 => day_03}/src/main.rs | 4 ++-- {day03 => day_03}/src/manhattan.rs | 0 {day03 => day_03}/src/part_01.rs | 0 {day03 => day_03}/src/part_02.rs | 0 {day03 => day_03}/src/structs.rs | 0 {day04 => day_04}/Cargo.toml | 0 {day04 => day_04}/src/main.rs | 14 +++++++++++++- {day04 => day_04}/src/part_01.rs | 0 {day04 => day_04}/src/part_02.rs | 0 18 files changed, 34 insertions(+), 20 deletions(-) delete mode 100644 day01/src/part_01.rs create mode 100644 day_01/Cargo.toml rename {day01 => day_01}/src/main.rs (92%) create mode 100644 day_01/src/part_01.rs rename {day01 => day_01}/src/part_02.rs (100%) rename {day02 => day_02}/Cargo.toml (50%) rename {day02 => day_02}/src/main.rs (100%) rename {day03 => day_03}/Cargo.toml (50%) rename {day03 => day_03}/src/main.rs (95%) rename {day03 => day_03}/src/manhattan.rs (100%) rename {day03 => day_03}/src/part_01.rs (100%) rename {day03 => day_03}/src/part_02.rs (100%) rename {day03 => day_03}/src/structs.rs (100%) rename {day04 => day_04}/Cargo.toml (100%) rename {day04 => day_04}/src/main.rs (72%) rename {day04 => day_04}/src/part_01.rs (100%) rename {day04 => day_04}/src/part_02.rs (100%) diff --git a/README.md b/README.md index 394af11..c3f99c3 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,7 @@ ## Progress: -- [Day 1](https://github.com/ankjevel/adventofcode/tree/2019/day01) 🌟 🌟 -- [Day 2](https://github.com/ankjevel/adventofcode/tree/2019/day02) 🌟 🌟 +- [Day 1](https://github.com/ankjevel/adventofcode/tree/2019/day_01) 🌟 🌟 +- [Day 2](https://github.com/ankjevel/adventofcode/tree/2019/day_02) 🌟 🌟 +- [Day 3](https://github.com/ankjevel/adventofcode/tree/2019/day_03) 🌟 🌟 +- [Day 4](https://github.com/ankjevel/adventofcode/tree/2019/day_04) 🌟 🌟 diff --git a/day01/src/part_01.rs b/day01/src/part_01.rs deleted file mode 100644 index e4b26df..0000000 --- a/day01/src/part_01.rs +++ /dev/null @@ -1,7 +0,0 @@ -use std::io; - -pub fn main(input: &Vec) -> io::Result> { - Ok(input.iter() - .map(|&mass| ((mass.clone() as f64 / 3.0).floor() as i32) - 2) - .collect()) -} diff --git a/day_01/Cargo.toml b/day_01/Cargo.toml new file mode 100644 index 0000000..9942126 --- /dev/null +++ b/day_01/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "day01" +version = "0.1.0" +authors = ["Dennis Pettersson "] + +[dependencies] diff --git a/day01/src/main.rs b/day_01/src/main.rs similarity index 92% rename from day01/src/main.rs rename to day_01/src/main.rs index affd444..7118c44 100644 --- a/day01/src/main.rs +++ b/day_01/src/main.rs @@ -9,8 +9,8 @@ fn main() -> io::Result<()> { let part_01_fuel = part_01::main(&input).unwrap().iter().sum::(); let part_02_sum_of_fuel = part_02::main(&input).unwrap(); - println!("part 1; fuel: {}", part_01_fuel); - println!("part 2; sum: {}", part_02_sum_of_fuel); + println!("part 1: {}", part_01_fuel); + println!("part 2: {}", part_02_sum_of_fuel); Ok(()) } diff --git a/day_01/src/part_01.rs b/day_01/src/part_01.rs new file mode 100644 index 0000000..17cdc4a --- /dev/null +++ b/day_01/src/part_01.rs @@ -0,0 +1,7 @@ +use std::io; + +pub fn main(input: &Vec) -> io::Result> { + Ok(input.iter() + .map(|&mass| ((mass.clone() as f64 / 3.0).floor() as i32) - 2) + .collect()) +} diff --git a/day01/src/part_02.rs b/day_01/src/part_02.rs similarity index 100% rename from day01/src/part_02.rs rename to day_01/src/part_02.rs diff --git a/day02/Cargo.toml b/day_02/Cargo.toml similarity index 50% rename from day02/Cargo.toml rename to day_02/Cargo.toml index bf0547c..2ccad44 100644 --- a/day02/Cargo.toml +++ b/day_02/Cargo.toml @@ -2,8 +2,5 @@ name = "day02" version = "0.1.0" authors = ["Dennis Pettersson "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/day02/src/main.rs b/day_02/src/main.rs similarity index 100% rename from day02/src/main.rs rename to day_02/src/main.rs diff --git a/day03/Cargo.toml b/day_03/Cargo.toml similarity index 50% rename from day03/Cargo.toml rename to day_03/Cargo.toml index da1cf06..929ce85 100644 --- a/day03/Cargo.toml +++ b/day_03/Cargo.toml @@ -2,8 +2,5 @@ name = "day03" version = "0.1.0" authors = ["Dennis Pettersson "] -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/day03/src/main.rs b/day_03/src/main.rs similarity index 95% rename from day03/src/main.rs rename to day_03/src/main.rs index 77b392e..d7ad2a7 100644 --- a/day03/src/main.rs +++ b/day_03/src/main.rs @@ -17,8 +17,8 @@ pub use structs::Point; fn main() -> Result<()> { let wires = parse_input(include_str!("../../input/day_03")); - println!("part_01: {:?}", part_01(&wires).unwrap()); - println!("part_02: {:?}", part_02(&wires).unwrap()); + println!("part_01: {}", part_01(&wires).unwrap()); + println!("part_02: {}", part_02(&wires).unwrap()); Ok(()) } diff --git a/day03/src/manhattan.rs b/day_03/src/manhattan.rs similarity index 100% rename from day03/src/manhattan.rs rename to day_03/src/manhattan.rs diff --git a/day03/src/part_01.rs b/day_03/src/part_01.rs similarity index 100% rename from day03/src/part_01.rs rename to day_03/src/part_01.rs diff --git a/day03/src/part_02.rs b/day_03/src/part_02.rs similarity index 100% rename from day03/src/part_02.rs rename to day_03/src/part_02.rs diff --git a/day03/src/structs.rs b/day_03/src/structs.rs similarity index 100% rename from day03/src/structs.rs rename to day_03/src/structs.rs diff --git a/day04/Cargo.toml b/day_04/Cargo.toml similarity index 100% rename from day04/Cargo.toml rename to day_04/Cargo.toml diff --git a/day04/src/main.rs b/day_04/src/main.rs similarity index 72% rename from day04/src/main.rs rename to day_04/src/main.rs index 2429546..4c686ea 100644 --- a/day04/src/main.rs +++ b/day_04/src/main.rs @@ -7,7 +7,7 @@ use part_01::main as part_01; use part_02::main as part_02; fn main() -> Result<()> { - let input = vec![347312, 805915]; + let input = parse_input(include_str!("../../input/day_04")); println!("part_01: {}", part_01(&input).unwrap()); println!("part_02: {}", part_02(&input).unwrap()); @@ -15,6 +15,18 @@ fn main() -> Result<()> { Ok(()) } +fn parse_input(input: &str) -> Vec { + input + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .next() + .unwrap() + .split('-') + .map(|part| part.parse::().unwrap()) + .collect::>() +} + #[cfg(test)] mod tests { use super::part_01::meet_criteria as part_01; diff --git a/day04/src/part_01.rs b/day_04/src/part_01.rs similarity index 100% rename from day04/src/part_01.rs rename to day_04/src/part_01.rs diff --git a/day04/src/part_02.rs b/day_04/src/part_02.rs similarity index 100% rename from day04/src/part_02.rs rename to day_04/src/part_02.rs From 46b2c71e226db4fc2ad7b8b334a6b92f0bd7c908 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Wed, 4 Dec 2019 23:07:44 +0100 Subject: [PATCH 12/42] chore: added edition to all configurations --- day_01/Cargo.toml | 1 + day_02/Cargo.toml | 1 + day_03/Cargo.toml | 1 + day_04/Cargo.toml | 2 -- 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/day_01/Cargo.toml b/day_01/Cargo.toml index 9942126..7bd0c29 100644 --- a/day_01/Cargo.toml +++ b/day_01/Cargo.toml @@ -2,5 +2,6 @@ name = "day01" version = "0.1.0" authors = ["Dennis Pettersson "] +edition = "2018" [dependencies] diff --git a/day_02/Cargo.toml b/day_02/Cargo.toml index 2ccad44..572e448 100644 --- a/day_02/Cargo.toml +++ b/day_02/Cargo.toml @@ -2,5 +2,6 @@ name = "day02" version = "0.1.0" authors = ["Dennis Pettersson "] +edition = "2018" [dependencies] diff --git a/day_03/Cargo.toml b/day_03/Cargo.toml index 929ce85..662bd70 100644 --- a/day_03/Cargo.toml +++ b/day_03/Cargo.toml @@ -2,5 +2,6 @@ name = "day03" version = "0.1.0" authors = ["Dennis Pettersson "] +edition = "2018" [dependencies] diff --git a/day_04/Cargo.toml b/day_04/Cargo.toml index b6ea3d6..436c976 100644 --- a/day_04/Cargo.toml +++ b/day_04/Cargo.toml @@ -4,6 +4,4 @@ version = "0.1.0" authors = ["Dennis Pettersson "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] From 14843becd3dfe7adff7cd552d4a4d2716c9e90a6 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Thu, 5 Dec 2019 22:51:16 +0100 Subject: [PATCH 13/42] feat: added day 5 --- day_05/Cargo.toml | 7 ++ day_05/src/main.rs | 199 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 day_05/Cargo.toml create mode 100644 day_05/src/main.rs diff --git a/day_05/Cargo.toml b/day_05/Cargo.toml new file mode 100644 index 0000000..5c0c751 --- /dev/null +++ b/day_05/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day_05" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +[dependencies] diff --git a/day_05/src/main.rs b/day_05/src/main.rs new file mode 100644 index 0000000..110a05e --- /dev/null +++ b/day_05/src/main.rs @@ -0,0 +1,199 @@ +#![feature(label_break_value)] +use std::io::Result; +use std::option::Option; + +struct Program { + memory: Vec, + pointer: usize, + input: i32, + output: Vec, +} + +impl Program { + fn new(memory: &Vec) -> Program { + Program { + memory: memory.clone(), + pointer: 0, + input: 0, + output: Vec::new(), + } + } + + fn mode_1_2(&mut self, opcode: i32, position_mode_noun: bool, position_mode_verb: bool, position_mode_pos: bool) { + let mut noun_index: usize = self.pointer + 1; + let mut verb_index: usize = self.pointer + 2; + let mut out_index: usize = self.pointer + 3; + + if position_mode_noun { + noun_index = self.memory[noun_index] as usize; + } + if position_mode_verb { + verb_index = self.memory[verb_index] as usize; + }; + if position_mode_pos { + out_index = self.memory[out_index] as usize; + }; + + let noun = self.memory[noun_index]; + let verb = self.memory[verb_index]; + + self.memory[out_index] = if opcode == 1 { + noun + verb + } else { + noun * verb + }; + } + + fn mode_3_4(&mut self, opcode: i32, position_mode_noun: bool) { + let index = if position_mode_noun { + self.memory[self.pointer + 1] as usize + } else { + self.pointer + 1 + }; + + if opcode == 3 { + self.memory[index] = self.input.clone(); + } else { + self.output.push(self.memory[index].clone()); + } + } + + fn to_int(&mut self, input: &char) -> i32 { + (&input.to_string()).parse::().unwrap() + } + + fn position_mode(&mut self, input: &Option) -> bool { + input.unwrap_or('0') == '0' + } + + fn run(&mut self) -> i32 { + self.pointer = 0; + + loop { + let opcode = self.memory[self.pointer]; + + if opcode == 99 { + break self.memory[0]; + } + + match opcode { + 1 | 2 => { + self.mode_1_2(opcode, true, true, true); + self.pointer += 4; + } + 3 | 4 => { + self.mode_3_4(opcode, true); + self.pointer += 2; + } + _ => { + let string = opcode.to_string(); + let mut instuction = string.chars().rev(); + let opcode = self.to_int(&instuction.next().unwrap()); + instuction.next(); + match opcode { + 1 | 2 => { + let mut pointer = instuction.clone(); + let position_mode_noun = self.position_mode(&pointer.next()); + let position_mode_verb = self.position_mode(&pointer.next()); + let position_mode_pos = self.position_mode(&pointer.next()); + self.mode_1_2(opcode, position_mode_noun, position_mode_verb, position_mode_pos); + self.pointer += 4 + } + 3 | 4 => { + let position_mode = self.position_mode(&instuction.next()); + self.mode_3_4(opcode, position_mode); + self.pointer += 2 + } + _ => { + panic!("opcode: {}", opcode) + } + } + } + }; + } + } +} + +fn parse_input(string: &str) -> Vec> { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|string| { + string + .split(',') + .map(|part| part.parse::().unwrap()) + .collect::>() + }) + .collect() +} + +fn main() -> Result<()> { + let input = parse_input(include_str!("../../input/day_05")); + + let mut program = Program::new(&input[0]); + + program.input = 1; + program.run(); + + println!("part_01: {}", program.run()); + println!("part_01: {:?}", program.output); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_DATA_FROM_DAY_02: &'static str = " + 1,0,0,0,99 + 2,3,0,3,99 + 2,4,4,5,99,0 + 1,1,1,4,99,5,6,0,99 + "; + + const EXAMPLE_DATA_01: &'static str = " + 1101,100,-1,4,0 + 1002,4,3,4,33 + "; + + #[test] + fn it_still_works_with_example_data_from_day_02() { + println!("\n"); + let input = parse_input(EXAMPLE_DATA_FROM_DAY_02); + + let results = input + .iter() + .map(|row| { + let mut program = Program::new(&row); + program.run(); + + program.memory + }) + .collect::>>(); + + assert_eq!(results[0], [2, 0, 0, 0, 99]); + assert_eq!(results[1], [2, 3, 0, 6, 99]); + assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); + assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); + println!("\n"); + } + + #[test] + fn examples_for_part_1() { + let input = parse_input(EXAMPLE_DATA_01); + + let results = input + .iter() + .map(|row| { + let mut program = Program::new(&row); + program.run(); + program.memory + }) + .collect::>>(); + + assert_eq!(results[0], [1101, 100, -1, 4, 99]); + assert_eq!(results[1], [1002, 4, 3, 4, 99]); + } +} From ea3fd90b1420dd315fa0e2ae28730ae0765bbe7e Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 6 Dec 2019 00:34:46 +0100 Subject: [PATCH 14/42] feat: slow, but added part 2 --- day_05/src/main.rs | 147 +++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 64 deletions(-) diff --git a/day_05/src/main.rs b/day_05/src/main.rs index 110a05e..5d0359f 100644 --- a/day_05/src/main.rs +++ b/day_05/src/main.rs @@ -1,8 +1,8 @@ -#![feature(label_break_value)] use std::io::Result; use std::option::Option; struct Program { + original_memory: Vec, memory: Vec, pointer: usize, input: i32, @@ -13,51 +13,87 @@ impl Program { fn new(memory: &Vec) -> Program { Program { memory: memory.clone(), + original_memory: memory.clone(), pointer: 0, input: 0, output: Vec::new(), } } - fn mode_1_2(&mut self, opcode: i32, position_mode_noun: bool, position_mode_verb: bool, position_mode_pos: bool) { - let mut noun_index: usize = self.pointer + 1; - let mut verb_index: usize = self.pointer + 2; - let mut out_index: usize = self.pointer + 3; - - if position_mode_noun { - noun_index = self.memory[noun_index] as usize; + fn get_index(&mut self, step: usize, positional: bool) -> usize { + if positional { + self.memory[self.pointer + step] as usize + } else { + self.pointer + step } - if position_mode_verb { - verb_index = self.memory[verb_index] as usize; - }; - if position_mode_pos { - out_index = self.memory[out_index] as usize; - }; + } + fn mode_1_2(&mut self, opcode: i32, positional_first: bool, positional_second: bool) -> usize { + let noun_index = self.get_index(1, positional_first); + let verb_index = self.get_index(2, positional_second); + let out_index = self.get_index(3, true); let noun = self.memory[noun_index]; let verb = self.memory[verb_index]; - self.memory[out_index] = if opcode == 1 { noun + verb } else { noun * verb }; + + 4 } - fn mode_3_4(&mut self, opcode: i32, position_mode_noun: bool) { - let index = if position_mode_noun { - self.memory[self.pointer + 1] as usize + fn mode_3_4(&mut self, opcode: i32) -> usize { + let index = self.get_index(1, true); + if opcode == 3 { + self.memory[index] = self.input.clone(); } else { - self.pointer + 1 + let output = self.memory[index].clone(); + self.output.push(output); }; - if opcode == 3 { - self.memory[index] = self.input.clone(); + 2 + } + + fn mode_5_6( + &mut self, + opcode: i32, + position_mode_first: bool, + position_mode_second: bool, + ) -> usize { + let first_index = self.get_index(1, position_mode_first); + let second_index = self.get_index(2, position_mode_second); + let param_1 = self.memory[first_index]; + let param_2 = self.memory[second_index]; + + if (opcode == 5 && param_1 != 0) || (opcode == 6 && param_1 == 0) { + param_2 as usize - self.pointer } else { - self.output.push(self.memory[index].clone()); + 3 } } + fn mode_7_8( + &mut self, + opcode: i32, + position_mode_first: bool, + position_mode_second: bool, + ) -> usize { + let first_index = self.get_index(1, position_mode_first); + let second_index = self.get_index(2, position_mode_second); + let third_index = self.get_index(3, true); + + let a = self.memory[first_index]; + let b = self.memory[second_index]; + + self.memory[third_index] = if (opcode == 7 && a < b) || (opcode == 8 && a == b) { + 1 + } else { + 0 + }; + 4 + } + fn to_int(&mut self, input: &char) -> i32 { (&input.to_string()).parse::().unwrap() } @@ -68,6 +104,8 @@ impl Program { fn run(&mut self) -> i32 { self.pointer = 0; + self.output = Vec::new(); + self.memory = self.original_memory.clone(); loop { let opcode = self.memory[self.pointer]; @@ -76,39 +114,19 @@ impl Program { break self.memory[0]; } - match opcode { - 1 | 2 => { - self.mode_1_2(opcode, true, true, true); - self.pointer += 4; - } - 3 | 4 => { - self.mode_3_4(opcode, true); - self.pointer += 2; - } - _ => { - let string = opcode.to_string(); - let mut instuction = string.chars().rev(); - let opcode = self.to_int(&instuction.next().unwrap()); - instuction.next(); - match opcode { - 1 | 2 => { - let mut pointer = instuction.clone(); - let position_mode_noun = self.position_mode(&pointer.next()); - let position_mode_verb = self.position_mode(&pointer.next()); - let position_mode_pos = self.position_mode(&pointer.next()); - self.mode_1_2(opcode, position_mode_noun, position_mode_verb, position_mode_pos); - self.pointer += 4 - } - 3 | 4 => { - let position_mode = self.position_mode(&instuction.next()); - self.mode_3_4(opcode, position_mode); - self.pointer += 2 - } - _ => { - panic!("opcode: {}", opcode) - } - } - } + let string = opcode.to_string(); + let mut instuction = string.chars().rev(); + let opcode = self.to_int(&instuction.next().unwrap()); + instuction.next(); + let positional_first = self.position_mode(&instuction.next()); + let positional_second = self.position_mode(&instuction.next()); + + self.pointer += match opcode { + 1 | 2 => self.mode_1_2(opcode, positional_first, positional_second), + 3 | 4 => self.mode_3_4(opcode), + 5 | 6 => self.mode_5_6(opcode, positional_first, positional_second), + 7 | 8 => self.mode_7_8(opcode, positional_first, positional_second), + _ => panic!("opcode: {}", opcode), }; } } @@ -130,15 +148,16 @@ fn parse_input(string: &str) -> Vec> { fn main() -> Result<()> { let input = parse_input(include_str!("../../input/day_05")); - let mut program = Program::new(&input[0]); program.input = 1; program.run(); - - println!("part_01: {}", program.run()); println!("part_01: {:?}", program.output); + program.input = 5; + program.run(); + println!("part_02: {:?}", program.output); + Ok(()) } @@ -160,7 +179,6 @@ mod tests { #[test] fn it_still_works_with_example_data_from_day_02() { - println!("\n"); let input = parse_input(EXAMPLE_DATA_FROM_DAY_02); let results = input @@ -177,7 +195,6 @@ mod tests { assert_eq!(results[1], [2, 3, 0, 6, 99]); assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); - println!("\n"); } #[test] @@ -189,11 +206,13 @@ mod tests { .map(|row| { let mut program = Program::new(&row); program.run(); - program.memory + program }) - .collect::>>(); + .collect::>(); - assert_eq!(results[0], [1101, 100, -1, 4, 99]); - assert_eq!(results[1], [1002, 4, 3, 4, 99]); + assert_eq!(results[0].memory, [1101, 100, -1, 4, 99]); + assert_eq!(results[1].memory, [1002, 4, 3, 4, 99]); + assert_eq!(results[0].output, []); + assert_eq!(results[1].output, []); } } From 393db1754e99a39bf21dc0a54945f0902dc92d90 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 6 Dec 2019 00:37:14 +0100 Subject: [PATCH 15/42] feat: updated readme with day 5 --- README.md | 1 + day_01/src/part_01.rs | 3 ++- day_03/src/structs.rs | 18 ++++++------------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c3f99c3..3efab18 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,4 @@ - [Day 2](https://github.com/ankjevel/adventofcode/tree/2019/day_02) 🌟 🌟 - [Day 3](https://github.com/ankjevel/adventofcode/tree/2019/day_03) 🌟 🌟 - [Day 4](https://github.com/ankjevel/adventofcode/tree/2019/day_04) 🌟 🌟 +- [Day 5](https://github.com/ankjevel/adventofcode/tree/2019/day_05) 🌟 🌟 diff --git a/day_01/src/part_01.rs b/day_01/src/part_01.rs index 17cdc4a..09ee0b5 100644 --- a/day_01/src/part_01.rs +++ b/day_01/src/part_01.rs @@ -1,7 +1,8 @@ use std::io; pub fn main(input: &Vec) -> io::Result> { - Ok(input.iter() + Ok(input + .iter() .map(|&mass| ((mass.clone() as f64 / 3.0).floor() as i32) - 2) .collect()) } diff --git a/day_03/src/structs.rs b/day_03/src/structs.rs index 892bc07..f064af8 100644 --- a/day_03/src/structs.rs +++ b/day_03/src/structs.rs @@ -3,7 +3,7 @@ pub enum Direction { Up, Down, Left, - Right + Right, } #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] @@ -13,7 +13,7 @@ pub struct Movement { } impl Movement { - pub fn new (input: &str) -> Movement { + pub fn new(input: &str) -> Movement { let mut chars = input.chars(); let direction = match chars.next().unwrap() { @@ -21,15 +21,12 @@ impl Movement { 'D' => Direction::Down, 'L' => Direction::Left, 'R' => Direction::Right, - _ => panic!("direction not defined") + _ => panic!("direction not defined"), }; let steps = chars.as_str().parse::().unwrap(); - Movement { - direction, - steps, - } + Movement { direction, steps } } } @@ -40,10 +37,7 @@ pub struct Point { } impl Point { - pub fn new () -> Point { - Point { - x: 0, - y: 0, - } + pub fn new() -> Point { + Point { x: 0, y: 0 } } } From bcb0a15c3c09842fca8163204e4461c729b45399 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 6 Dec 2019 18:38:10 +0100 Subject: [PATCH 16/42] feat: added day 6 --- README.md | 1 + day_06/Cargo.toml | 9 ++++ day_06/src/main.rs | 108 ++++++++++++++++++++++++++++++++++++++++++ day_06/src/part_01.rs | 23 +++++++++ day_06/src/part_02.rs | 34 +++++++++++++ 5 files changed, 175 insertions(+) create mode 100644 day_06/Cargo.toml create mode 100644 day_06/src/main.rs create mode 100644 day_06/src/part_01.rs create mode 100644 day_06/src/part_02.rs diff --git a/README.md b/README.md index 3efab18..5bbdbb5 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,4 @@ - [Day 3](https://github.com/ankjevel/adventofcode/tree/2019/day_03) 🌟 🌟 - [Day 4](https://github.com/ankjevel/adventofcode/tree/2019/day_04) 🌟 🌟 - [Day 5](https://github.com/ankjevel/adventofcode/tree/2019/day_05) 🌟 🌟 +- [Day 6](https://github.com/ankjevel/adventofcode/tree/2019/day_06) 🌟 🌟 diff --git a/day_06/Cargo.toml b/day_06/Cargo.toml new file mode 100644 index 0000000..d12681b --- /dev/null +++ b/day_06/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day_06" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day_06/src/main.rs b/day_06/src/main.rs new file mode 100644 index 0000000..e385ccd --- /dev/null +++ b/day_06/src/main.rs @@ -0,0 +1,108 @@ +mod part_01; +mod part_02; + +use part_01::main as part_01; +use part_02::main as part_02; + +fn main() { + let input = parse_input(include_str!("../../input/day_06")); + println!("part_01: {}", part_01(&input)); + println!("part_02: {}", part_02(&input)); +} + +fn parse_input(string: &str) -> Vec<(String, String)> { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|line| line.split(')').map(str::to_owned).collect()) + .map(|x: Vec| (x[1].clone(), x[0].clone())) + .collect() +} + +#[cfg(test)] +mod tests { + use super::parse_input; + use super::part_01::main as part_01; + use super::part_02::main as part_02; + + const EXAMPLE_DATA_PART_01: &'static str = " + COM)B + B)C + C)D + D)E + E)F + B)G + G)H + D)I + E)J + J)K + K)L + "; + + const UNORDERED_EXAMPLE_DATA_PART_01: &'static str = " + K)L + E)J + J)K + COM)B + E)F + B)C + D)I + B)G + G)H + D)E + C)D + "; + + const EXAMPLE_DATA_PART_02: &'static str = " + COM)B + B)C + C)D + D)E + E)F + B)G + G)H + D)I + E)J + J)K + K)L + K)YOU + I)SAN + "; + + const UNORDERED_EXAMPLE_DATA_PART_02: &'static str = " + B)G + J)K + E)F + B)C + COM)B + G)H + I)SAN + D)E + C)D + E)J + K)L + K)YOU + D)I + "; + + #[test] + fn it_gets_the_example_right_for_part_01() { + let example_data = parse_input(&EXAMPLE_DATA_PART_01); + let unordered_example_data = parse_input(&UNORDERED_EXAMPLE_DATA_PART_01); + + assert_eq!(part_01(&example_data), 42); + assert_eq!(part_01(&unordered_example_data), 42); + } + + #[test] + #[ignore] + fn it_gets_the_example_right_for_part_02() { + let example_data = parse_input(&EXAMPLE_DATA_PART_02); + let unordered_example_data = parse_input(&UNORDERED_EXAMPLE_DATA_PART_02); + + assert_eq!(part_02(&example_data), 4); + assert_eq!(part_02(&unordered_example_data), 4); + } + +} diff --git a/day_06/src/part_01.rs b/day_06/src/part_01.rs new file mode 100644 index 0000000..7497320 --- /dev/null +++ b/day_06/src/part_01.rs @@ -0,0 +1,23 @@ +use std::collections::HashMap; + +type Map = HashMap; + +pub fn main(input: &Vec<(String, String)>) -> u32 { + let map = input.clone().into_iter().collect::(); + let mut results = 0; + + 'foreach: for key in map.keys() { + let mut current = key; + 'search: loop { + match map.get(current) { + Some(x) => { + results += 1; + current = x; + } + None => break 'search, + }; + } + } + + results +} diff --git a/day_06/src/part_02.rs b/day_06/src/part_02.rs new file mode 100644 index 0000000..712f0e1 --- /dev/null +++ b/day_06/src/part_02.rs @@ -0,0 +1,34 @@ +use std::collections::HashMap; + +type Map = HashMap; + +fn get_val(input: &str, map: &Map) -> String { + map.get(input).unwrap().to_owned() +} + +pub fn main(input: &Vec<(String, String)>) -> u32 { + let map = input.clone().into_iter().collect::(); + + let orbit_list = |from: String| -> Vec { + let mut list = vec![from.clone()]; + let mut orbit = from.as_str(); + while map.contains_key(orbit) { + orbit = map.get(orbit).unwrap(); + list.push(orbit.to_owned()); + } + list + }; + + let orbits1 = orbit_list(get_val("YOU", &map)); + let orbits2 = orbit_list(get_val("SAN", &map)); + + for (i, orbit1) in orbits1.iter().enumerate() { + for (j, orbit2) in orbits2.iter().enumerate() { + if orbit1 == orbit2 { + return (i + j) as u32; + } + } + } + + 1 +} From 62b0d8eb5990f32937a75b73082d6fc75e4d9f2f Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 6 Dec 2019 18:41:12 +0100 Subject: [PATCH 17/42] fix: un-ignored test --- day_06/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/day_06/src/main.rs b/day_06/src/main.rs index e385ccd..b344a6d 100644 --- a/day_06/src/main.rs +++ b/day_06/src/main.rs @@ -96,7 +96,6 @@ mod tests { } #[test] - #[ignore] fn it_gets_the_example_right_for_part_02() { let example_data = parse_input(&EXAMPLE_DATA_PART_02); let unordered_example_data = parse_input(&UNORDERED_EXAMPLE_DATA_PART_02); From ea94fae26d39a57f046a45b78d771ef5b15209cd Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sun, 8 Dec 2019 13:41:39 +0100 Subject: [PATCH 18/42] feat: added part 1 of day 7 --- README.md | 1 + day_05/Cargo.toml | 4 + day_05/src/bin/main.rs | 74 ++++++++++++++ day_05/src/lib.rs | 15 +++ day_05/src/main.rs | 218 ----------------------------------------- day_05/src/program.rs | 157 +++++++++++++++++++++++++++++ day_07/Cargo.toml | 9 ++ day_07/src/main.rs | 57 +++++++++++ 8 files changed, 317 insertions(+), 218 deletions(-) create mode 100644 day_05/src/bin/main.rs create mode 100644 day_05/src/lib.rs delete mode 100644 day_05/src/main.rs create mode 100644 day_05/src/program.rs create mode 100644 day_07/Cargo.toml create mode 100644 day_07/src/main.rs diff --git a/README.md b/README.md index 5bbdbb5..b3aae5c 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,4 @@ - [Day 4](https://github.com/ankjevel/adventofcode/tree/2019/day_04) 🌟 🌟 - [Day 5](https://github.com/ankjevel/adventofcode/tree/2019/day_05) 🌟 🌟 - [Day 6](https://github.com/ankjevel/adventofcode/tree/2019/day_06) 🌟 🌟 +- [Day 7](https://github.com/ankjevel/adventofcode/tree/2019/day_07) 🌟 diff --git a/day_05/Cargo.toml b/day_05/Cargo.toml index 5c0c751..b5bd6a7 100644 --- a/day_05/Cargo.toml +++ b/day_05/Cargo.toml @@ -5,3 +5,7 @@ authors = ["Dennis Pettersson "] edition = "2018" [dependencies] + +[[bin]] +name = "day_04" +path = "src/bin/main.rs" diff --git a/day_05/src/bin/main.rs b/day_05/src/bin/main.rs new file mode 100644 index 0000000..970634b --- /dev/null +++ b/day_05/src/bin/main.rs @@ -0,0 +1,74 @@ +use ::day_05::{parse_input, program::Program}; +use std::io::Result; + +#[allow(dead_code)] +fn main() -> Result<()> { + let input = parse_input(include_str!("../../../input/day_05")); + let mut program = Program::new(&input[0]); + + program.new_input(&vec![1]); + program.run(); + println!("part_01: {:?}", program.output); + + program.new_input(&vec![5]); + program.run(); + println!("part_02: {:?}", program.output); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_DATA_FROM_DAY_02: &'static str = " + 1,0,0,0,99 + 2,3,0,3,99 + 2,4,4,5,99,0 + 1,1,1,4,99,5,6,0,99 + "; + + const EXAMPLE_DATA_01: &'static str = " + 1101,100,-1,4,0 + 1002,4,3,4,33 + "; + + #[test] + fn it_still_works_with_example_data_from_day_02() { + let input = parse_input(EXAMPLE_DATA_FROM_DAY_02); + + let results = input + .iter() + .map(|row| { + let mut program = Program::new(&row); + program.run(); + + program.memory + }) + .collect::>>(); + + assert_eq!(results[0], [2, 0, 0, 0, 99]); + assert_eq!(results[1], [2, 3, 0, 6, 99]); + assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); + assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); + } + + #[test] + fn examples_for_part_1() { + let input = parse_input(EXAMPLE_DATA_01); + + let results = input + .iter() + .map(|row| { + let mut program = Program::new(&row); + program.run(); + program + }) + .collect::>(); + + assert_eq!(results[0].memory, [1101, 100, -1, 4, 99]); + assert_eq!(results[1].memory, [1002, 4, 3, 4, 99]); + assert_eq!(results[0].output, []); + assert_eq!(results[1].output, []); + } +} diff --git a/day_05/src/lib.rs b/day_05/src/lib.rs new file mode 100644 index 0000000..69fe57c --- /dev/null +++ b/day_05/src/lib.rs @@ -0,0 +1,15 @@ +pub fn parse_input(string: &str) -> Vec> { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|string| { + string + .split(',') + .map(|part| part.parse::().unwrap()) + .collect::>() + }) + .collect() +} + +pub mod program; diff --git a/day_05/src/main.rs b/day_05/src/main.rs deleted file mode 100644 index 5d0359f..0000000 --- a/day_05/src/main.rs +++ /dev/null @@ -1,218 +0,0 @@ -use std::io::Result; -use std::option::Option; - -struct Program { - original_memory: Vec, - memory: Vec, - pointer: usize, - input: i32, - output: Vec, -} - -impl Program { - fn new(memory: &Vec) -> Program { - Program { - memory: memory.clone(), - original_memory: memory.clone(), - pointer: 0, - input: 0, - output: Vec::new(), - } - } - - fn get_index(&mut self, step: usize, positional: bool) -> usize { - if positional { - self.memory[self.pointer + step] as usize - } else { - self.pointer + step - } - } - - fn mode_1_2(&mut self, opcode: i32, positional_first: bool, positional_second: bool) -> usize { - let noun_index = self.get_index(1, positional_first); - let verb_index = self.get_index(2, positional_second); - let out_index = self.get_index(3, true); - let noun = self.memory[noun_index]; - let verb = self.memory[verb_index]; - self.memory[out_index] = if opcode == 1 { - noun + verb - } else { - noun * verb - }; - - 4 - } - - fn mode_3_4(&mut self, opcode: i32) -> usize { - let index = self.get_index(1, true); - if opcode == 3 { - self.memory[index] = self.input.clone(); - } else { - let output = self.memory[index].clone(); - self.output.push(output); - }; - - 2 - } - - fn mode_5_6( - &mut self, - opcode: i32, - position_mode_first: bool, - position_mode_second: bool, - ) -> usize { - let first_index = self.get_index(1, position_mode_first); - let second_index = self.get_index(2, position_mode_second); - let param_1 = self.memory[first_index]; - let param_2 = self.memory[second_index]; - - if (opcode == 5 && param_1 != 0) || (opcode == 6 && param_1 == 0) { - param_2 as usize - self.pointer - } else { - 3 - } - } - - fn mode_7_8( - &mut self, - opcode: i32, - position_mode_first: bool, - position_mode_second: bool, - ) -> usize { - let first_index = self.get_index(1, position_mode_first); - let second_index = self.get_index(2, position_mode_second); - let third_index = self.get_index(3, true); - - let a = self.memory[first_index]; - let b = self.memory[second_index]; - - self.memory[third_index] = if (opcode == 7 && a < b) || (opcode == 8 && a == b) { - 1 - } else { - 0 - }; - 4 - } - - fn to_int(&mut self, input: &char) -> i32 { - (&input.to_string()).parse::().unwrap() - } - - fn position_mode(&mut self, input: &Option) -> bool { - input.unwrap_or('0') == '0' - } - - fn run(&mut self) -> i32 { - self.pointer = 0; - self.output = Vec::new(); - self.memory = self.original_memory.clone(); - - loop { - let opcode = self.memory[self.pointer]; - - if opcode == 99 { - break self.memory[0]; - } - - let string = opcode.to_string(); - let mut instuction = string.chars().rev(); - let opcode = self.to_int(&instuction.next().unwrap()); - instuction.next(); - let positional_first = self.position_mode(&instuction.next()); - let positional_second = self.position_mode(&instuction.next()); - - self.pointer += match opcode { - 1 | 2 => self.mode_1_2(opcode, positional_first, positional_second), - 3 | 4 => self.mode_3_4(opcode), - 5 | 6 => self.mode_5_6(opcode, positional_first, positional_second), - 7 | 8 => self.mode_7_8(opcode, positional_first, positional_second), - _ => panic!("opcode: {}", opcode), - }; - } - } -} - -fn parse_input(string: &str) -> Vec> { - string - .lines() - .map(|string| string.trim()) - .filter(|string| !string.is_empty()) - .map(|string| { - string - .split(',') - .map(|part| part.parse::().unwrap()) - .collect::>() - }) - .collect() -} - -fn main() -> Result<()> { - let input = parse_input(include_str!("../../input/day_05")); - let mut program = Program::new(&input[0]); - - program.input = 1; - program.run(); - println!("part_01: {:?}", program.output); - - program.input = 5; - program.run(); - println!("part_02: {:?}", program.output); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - - const EXAMPLE_DATA_FROM_DAY_02: &'static str = " - 1,0,0,0,99 - 2,3,0,3,99 - 2,4,4,5,99,0 - 1,1,1,4,99,5,6,0,99 - "; - - const EXAMPLE_DATA_01: &'static str = " - 1101,100,-1,4,0 - 1002,4,3,4,33 - "; - - #[test] - fn it_still_works_with_example_data_from_day_02() { - let input = parse_input(EXAMPLE_DATA_FROM_DAY_02); - - let results = input - .iter() - .map(|row| { - let mut program = Program::new(&row); - program.run(); - - program.memory - }) - .collect::>>(); - - assert_eq!(results[0], [2, 0, 0, 0, 99]); - assert_eq!(results[1], [2, 3, 0, 6, 99]); - assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); - assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); - } - - #[test] - fn examples_for_part_1() { - let input = parse_input(EXAMPLE_DATA_01); - - let results = input - .iter() - .map(|row| { - let mut program = Program::new(&row); - program.run(); - program - }) - .collect::>(); - - assert_eq!(results[0].memory, [1101, 100, -1, 4, 99]); - assert_eq!(results[1].memory, [1002, 4, 3, 4, 99]); - assert_eq!(results[0].output, []); - assert_eq!(results[1].output, []); - } -} diff --git a/day_05/src/program.rs b/day_05/src/program.rs new file mode 100644 index 0000000..3218391 --- /dev/null +++ b/day_05/src/program.rs @@ -0,0 +1,157 @@ +use std::iter::Iterator; +use std::option::Option; +// use std::collections::VecDeque; + +pub struct Program { + original_memory: Vec, + pointer: usize, + input_pointer: usize, + input: Vec, + halted: bool, + pub memory: Vec, + pub output: Vec, +} + +impl Program { + pub fn new(memory: &Vec) -> Program { + Program { + original_memory: memory.clone(), + pointer: 0, + input: vec![0], + input_pointer: 0, + halted: false, + memory: memory.clone(), + output: Vec::new(), + } + } + + pub fn new_input(&mut self, input: &Vec) { + self.input_pointer = 0; + self.input = input.clone(); + } + + pub fn is_halted(&self) -> bool { + self.halted + } + + fn get_index(&mut self, step: usize, positional: bool) -> usize { + if positional { + self.memory[self.pointer + step] as usize + } else { + self.pointer + step + } + } + + fn mode_1_2(&mut self, opcode: i32, positional_first: bool, positional_second: bool) -> usize { + let noun_index = self.get_index(1, positional_first); + let verb_index = self.get_index(2, positional_second); + let out_index = self.get_index(3, true); + let noun = self.memory[noun_index]; + let verb = self.memory[verb_index]; + self.memory[out_index] = if opcode == 1 { + noun + verb + } else { + noun * verb + }; + + 4 + } + + fn mode_3_4(&mut self, opcode: i32) -> usize { + let index = self.get_index(1, true); + if opcode == 3 { + let input = self.input.get(self.input_pointer).unwrap_or(&0); + self.input_pointer += 1; + self.memory[index] = *input; + } else { + let output = self.memory[index].clone(); + self.output.push(output); + }; + + 2 + } + + fn mode_5_6( + &mut self, + opcode: i32, + position_mode_first: bool, + position_mode_second: bool, + ) -> usize { + let first_index = self.get_index(1, position_mode_first); + let second_index = self.get_index(2, position_mode_second); + let param_1 = self.memory[first_index]; + let param_2 = self.memory[second_index]; + + if (opcode == 5 && param_1 != 0) || (opcode == 6 && param_1 == 0) { + param_2 as usize - self.pointer + } else { + 3 + } + } + + fn mode_7_8( + &mut self, + opcode: i32, + position_mode_first: bool, + position_mode_second: bool, + ) -> usize { + let first_index = self.get_index(1, position_mode_first); + let second_index = self.get_index(2, position_mode_second); + let third_index = self.get_index(3, true); + + let a = self.memory[first_index]; + let b = self.memory[second_index]; + + self.memory[third_index] = if (opcode == 7 && a < b) || (opcode == 8 && a == b) { + 1 + } else { + 0 + }; + 4 + } + + fn to_int(&mut self, input: &char) -> i32 { + (&input.to_string()).parse::().unwrap() + } + + fn position_mode(&mut self, input: &Option) -> bool { + input.unwrap_or('0') == '0' + } + + pub fn run(&mut self) -> i32 { + self.pointer = 0; + self.output = Vec::new(); + self.memory = self.original_memory.clone(); + self.halted = false; + + while !self.halted { + self.eval() + } + + *self.output.last().unwrap_or(&0i32) + } + + fn eval(&mut self) { + let opcode = self.memory[self.pointer]; + + if opcode == 99 { + self.halted = true; + return; + } + + let string = opcode.to_string(); + let mut instuction = string.chars().rev(); + let opcode = self.to_int(&instuction.next().unwrap()); + instuction.next(); + let positional_first = self.position_mode(&instuction.next()); + let positional_second = self.position_mode(&instuction.next()); + + self.pointer += match opcode { + 1 | 2 => self.mode_1_2(opcode, positional_first, positional_second), + 3 | 4 => self.mode_3_4(opcode), + 5 | 6 => self.mode_5_6(opcode, positional_first, positional_second), + 7 | 8 => self.mode_7_8(opcode, positional_first, positional_second), + _ => panic!("opcode: {}", opcode), + }; + } +} diff --git a/day_07/Cargo.toml b/day_07/Cargo.toml new file mode 100644 index 0000000..5489e3d --- /dev/null +++ b/day_07/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day_07" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +[dependencies] +day_05 = { path = "../day_05" } +permute = "0.1.0" diff --git a/day_07/src/main.rs b/day_07/src/main.rs new file mode 100644 index 0000000..f9f6f0b --- /dev/null +++ b/day_07/src/main.rs @@ -0,0 +1,57 @@ +extern crate day_05; +extern crate permute; + +use day_05::{parse_input, program::Program}; +use permute::permute; + +fn part_01(sequence: &Vec, memory: &Vec) -> i32 { + let mut program = Program::new(&memory); + let mut input = vec![0]; + for signal in sequence { + input.insert(0, signal.to_owned()); + program.new_input(&input); + input.insert(0, program.run()); + } + input[0] +} + +fn main() { + let input = parse_input(include_str!("../../input/day_07")); + let answer_part_01 = permute((0..=4).collect()) + .into_iter() + .map(|sequence| part_01(&sequence, &input[0])) + .max() + .unwrap(); + + permute((5..=9).collect()) + .into_iter() + .for_each(|_sequence| {}); + + // println!("part_02: {:?}", answer_part_02); + println!("part_01: {:?}", answer_part_01); +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLES_FOR_PART_01: &'static str = " + 3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0 + 3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0 + 3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0 + "; + + const EXAMPLES_FOR_PART_02: &'static str = " + 3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5 + 3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0 + "; + + #[test] + fn it_gets_the_examples_right_on_part_01() { + let input = parse_input(&EXAMPLES_FOR_PART_01); + + assert_eq!(part_01(&vec![4, 3, 2, 1, 0], &input[0]), 43210); + assert_eq!(part_01(&vec![0, 1, 2, 3, 4], &input[1]), 54321); + assert_eq!(part_01(&vec![1, 0, 4, 3, 2], &input[2]), 65210); + } +} From 352b4ec78f3d441defc35417a0efbafa5d27d5e2 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sun, 8 Dec 2019 18:43:43 +0100 Subject: [PATCH 19/42] feat: added part 2 or day 7... so hacky --- day_05/src/bin/main.rs | 75 +++++--------------------------------- day_05/src/program.rs | 83 ++++++++++++++++++++++++++++++++---------- day_07/src/main.rs | 52 +++++++++++++++++++------- 3 files changed, 111 insertions(+), 99 deletions(-) diff --git a/day_05/src/bin/main.rs b/day_05/src/bin/main.rs index 970634b..c12da43 100644 --- a/day_05/src/bin/main.rs +++ b/day_05/src/bin/main.rs @@ -1,74 +1,17 @@ -use ::day_05::{parse_input, program::Program}; +use ::day_05::{parse_input, program::exec_without_channels}; use std::io::Result; -#[allow(dead_code)] fn main() -> Result<()> { let input = parse_input(include_str!("../../../input/day_05")); - let mut program = Program::new(&input[0]); - program.new_input(&vec![1]); - program.run(); - println!("part_01: {:?}", program.output); - - program.new_input(&vec![5]); - program.run(); - println!("part_02: {:?}", program.output); + println!( + "part_01: {:?}", + exec_without_channels(input[0].clone(), None) + ); + println!( + "part_02: {:?}", + exec_without_channels(input[0].clone(), Some(vec![5])) + ); Ok(()) } - -#[cfg(test)] -mod tests { - use super::*; - - const EXAMPLE_DATA_FROM_DAY_02: &'static str = " - 1,0,0,0,99 - 2,3,0,3,99 - 2,4,4,5,99,0 - 1,1,1,4,99,5,6,0,99 - "; - - const EXAMPLE_DATA_01: &'static str = " - 1101,100,-1,4,0 - 1002,4,3,4,33 - "; - - #[test] - fn it_still_works_with_example_data_from_day_02() { - let input = parse_input(EXAMPLE_DATA_FROM_DAY_02); - - let results = input - .iter() - .map(|row| { - let mut program = Program::new(&row); - program.run(); - - program.memory - }) - .collect::>>(); - - assert_eq!(results[0], [2, 0, 0, 0, 99]); - assert_eq!(results[1], [2, 3, 0, 6, 99]); - assert_eq!(results[2], [2, 4, 4, 5, 99, 9801]); - assert_eq!(results[3], [30, 1, 1, 4, 2, 5, 6, 0, 99]); - } - - #[test] - fn examples_for_part_1() { - let input = parse_input(EXAMPLE_DATA_01); - - let results = input - .iter() - .map(|row| { - let mut program = Program::new(&row); - program.run(); - program - }) - .collect::>(); - - assert_eq!(results[0].memory, [1101, 100, -1, 4, 99]); - assert_eq!(results[1].memory, [1002, 4, 3, 4, 99]); - assert_eq!(results[0].output, []); - assert_eq!(results[1].output, []); - } -} diff --git a/day_05/src/program.rs b/day_05/src/program.rs index 3218391..6074b28 100644 --- a/day_05/src/program.rs +++ b/day_05/src/program.rs @@ -1,33 +1,41 @@ -use std::iter::Iterator; -use std::option::Option; -// use std::collections::VecDeque; +use std::{ + iter::Iterator, + option::Option, + sync::mpsc::{channel, Receiver, Sender}, + thread::{spawn, JoinHandle}, +}; pub struct Program { original_memory: Vec, pointer: usize, - input_pointer: usize, - input: Vec, + input: Receiver, halted: bool, + output: Sender, + output_value: i32, pub memory: Vec, - pub output: Vec, } impl Program { pub fn new(memory: &Vec) -> Program { + let (output, input) = channel(); + Program { original_memory: memory.clone(), pointer: 0, - input: vec![0], - input_pointer: 0, + output_value: 0, + input, halted: false, memory: memory.clone(), - output: Vec::new(), + output, } } - pub fn new_input(&mut self, input: &Vec) { - self.input_pointer = 0; - self.input = input.clone(); + pub fn new_input(&mut self, input: Receiver) { + self.input = input; + } + + pub fn new_output(&mut self, output: Sender) { + self.output = output; } pub fn is_halted(&self) -> bool { @@ -60,12 +68,12 @@ impl Program { fn mode_3_4(&mut self, opcode: i32) -> usize { let index = self.get_index(1, true); if opcode == 3 { - let input = self.input.get(self.input_pointer).unwrap_or(&0); - self.input_pointer += 1; - self.memory[index] = *input; + let input = self.input.recv().unwrap_or(0); + self.memory[index] = input.to_owned(); } else { let output = self.memory[index].clone(); - self.output.push(output); + self.output.send(output.to_owned()).unwrap_or(()); + self.output_value = output.to_owned(); }; 2 @@ -120,15 +128,15 @@ impl Program { pub fn run(&mut self) -> i32 { self.pointer = 0; - self.output = Vec::new(); - self.memory = self.original_memory.clone(); + self.output_value = 0; self.halted = false; + self.memory = self.original_memory.clone(); while !self.halted { self.eval() } - *self.output.last().unwrap_or(&0i32) + self.output_value.to_owned() } fn eval(&mut self) { @@ -151,7 +159,42 @@ impl Program { 3 | 4 => self.mode_3_4(opcode), 5 | 6 => self.mode_5_6(opcode, positional_first, positional_second), 7 | 8 => self.mode_7_8(opcode, positional_first, positional_second), - _ => panic!("opcode: {}", opcode), + 9 => { + self.halted = true; + 0 + } + _ => panic!("[{}], opcode: {}", self.pointer, opcode), }; } } + +pub fn exec(memory: Vec, input: Receiver, output: Sender) -> JoinHandle { + spawn(move || { + let mut program = Program::new(&memory); + program.new_input(input); + program.new_output(output); + program.run() + }) +} + +pub fn exec_without_channels(memory: Vec, input: Option>) -> i32 { + let (c_out, c_in) = channel(); + match input { + Some(input) => { + for seq in input.clone() { + c_out.send(seq).unwrap(); + } + } + None => { + c_out.send(0).unwrap(); + } + }; + spawn(move || { + let mut program = Program::new(&memory); + program.new_input(c_in); + program.new_output(c_out); + program.run() + }) + .join() + .unwrap() +} diff --git a/day_07/src/main.rs b/day_07/src/main.rs index f9f6f0b..5a544f9 100644 --- a/day_07/src/main.rs +++ b/day_07/src/main.rs @@ -1,34 +1,65 @@ extern crate day_05; extern crate permute; -use day_05::{parse_input, program::Program}; +use day_05::{ + parse_input, + program::{exec, exec_without_channels}, +}; use permute::permute; +use std::{iter::Iterator, sync::mpsc::channel}; fn part_01(sequence: &Vec, memory: &Vec) -> i32 { - let mut program = Program::new(&memory); let mut input = vec![0]; for signal in sequence { input.insert(0, signal.to_owned()); - program.new_input(&input); - input.insert(0, program.run()); + input.insert( + 0, + exec_without_channels(memory.clone(), Some(input.clone())), + ) } input[0] } +fn part_02(sequence: &Vec, memory: &Vec) -> i32 { + let mut seq = sequence.to_owned(); + let mut iter = seq.iter_mut(); + + let (e_out, a_in) = channel(); + let (a_out, b_in) = channel(); + let (b_out, c_in) = channel(); + let (c_out, d_in) = channel(); + let (d_out, e_in) = channel(); + + e_out.send(*iter.next().unwrap()).unwrap(); + a_out.send(*iter.next().unwrap()).unwrap(); + b_out.send(*iter.next().unwrap()).unwrap(); + c_out.send(*iter.next().unwrap()).unwrap(); + d_out.send(*iter.next().unwrap()).unwrap(); + e_out.send(0).unwrap(); + + exec(memory.clone(), a_in, a_out); + exec(memory.clone(), b_in, b_out); + exec(memory.clone(), c_in, c_out); + exec(memory.clone(), d_in, d_out); + exec(memory.clone(), e_in, e_out).join().unwrap() +} + fn main() { let input = parse_input(include_str!("../../input/day_07")); let answer_part_01 = permute((0..=4).collect()) .into_iter() .map(|sequence| part_01(&sequence, &input[0])) .max() - .unwrap(); + .unwrap_or(0); - permute((5..=9).collect()) + let answer_part_02 = permute((5..=9).collect()) .into_iter() - .for_each(|_sequence| {}); + .map(|sequence| part_02(&sequence, &input[0])) + .max() + .unwrap_or(0); - // println!("part_02: {:?}", answer_part_02); println!("part_01: {:?}", answer_part_01); + println!("part_02: {:?}", answer_part_02); } #[cfg(test)] @@ -41,11 +72,6 @@ mod tests { 3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0 "; - const EXAMPLES_FOR_PART_02: &'static str = " - 3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5 - 3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0 - "; - #[test] fn it_gets_the_examples_right_on_part_01() { let input = parse_input(&EXAMPLES_FOR_PART_01); From d8fa15599f40b4310ff114c0bac6ad3fc8adc226 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sun, 8 Dec 2019 22:17:42 +0100 Subject: [PATCH 20/42] feat: completed day 8 --- README.md | 3 +- day_08/Cargo.toml | 9 +++++ day_08/src/main.rs | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 day_08/Cargo.toml create mode 100644 day_08/src/main.rs diff --git a/README.md b/README.md index b3aae5c..846b8e9 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,5 @@ - [Day 4](https://github.com/ankjevel/adventofcode/tree/2019/day_04) 🌟 🌟 - [Day 5](https://github.com/ankjevel/adventofcode/tree/2019/day_05) 🌟 🌟 - [Day 6](https://github.com/ankjevel/adventofcode/tree/2019/day_06) 🌟 🌟 -- [Day 7](https://github.com/ankjevel/adventofcode/tree/2019/day_07) 🌟 +- [Day 7](https://github.com/ankjevel/adventofcode/tree/2019/day_07) 🌟 🌟 +- [Day 8](https://github.com/ankjevel/adventofcode/tree/2019/day_08) 🌟 🌟 diff --git a/day_08/Cargo.toml b/day_08/Cargo.toml new file mode 100644 index 0000000..a212135 --- /dev/null +++ b/day_08/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day_08" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day_08/src/main.rs b/day_08/src/main.rs new file mode 100644 index 0000000..0dbd7fe --- /dev/null +++ b/day_08/src/main.rs @@ -0,0 +1,99 @@ +use std::str::from_utf8; + +fn parse_input(string: &str) -> Vec { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(str::to_owned) + .collect() +} + +fn chars(input: &str, check: &char) -> Vec { + input + .clone() + .chars() + .into_iter() + .filter(|c| c == check) + .into_iter() + .collect() +} + +fn len(input: &str, check: &char) -> usize { + input.chars().into_iter().filter(|c| c == check).count() +} + +fn chunk_str(input: &str, chunks: usize) -> Vec { + input + .as_bytes() + .chunks(chunks) + .into_iter() + .map(|c| from_utf8(&c).unwrap().to_owned()) + .collect::>() +} + +fn part_01(input: &str, chunks: usize) -> usize { + let chunked = chunk_str(&input, chunks); + let least_zeroes = chunked + .clone() + .into_iter() + .fold(chunked[0].clone(), |acc, current| { + let check = '0'; + if len(¤t, &check) < len(&acc, &check) { + current.to_owned() + } else { + acc + } + }); + + chars(&least_zeroes, &'1').len() * chars(&least_zeroes, &'2').len() +} + +fn part_02(input: &str, width: usize, height: usize) -> String { + let chunk_size = width * height; + let mut output = vec![b'2'; chunk_size]; + + for chunk in input.as_bytes().chunks(chunk_size) { + for (image_pixel, &layer_pixel) in output.iter_mut().zip(chunk.iter()) { + if *image_pixel != b'2' { + continue; + } + + *image_pixel = layer_pixel; + } + } + + chunk_str(&from_utf8(&output) + .unwrap() + .replace('1', "*") + .replace('0', " "), width).join("\n") +} + +fn main() { + let input = parse_input(include_str!("../../input/day_08")); + + println!("part_01: {:?}", part_01(&input[0], 25 * 6)); + println!("part_02:\n{}", part_02(&input[0], 25, 6)); +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_PART_01: &'static str = "01110222012102121112"; + + const EXAMPLE_PART_02: &'static str = "0222112222120000"; + + #[test] + fn it_gets_the_first_example_right() { + assert_eq!(part_01(&parse_input(&EXAMPLE_PART_01)[0], 4), 3); + } + + #[test] + fn it_get_the_second_example_right() { + assert_eq!( + part_02(&parse_input(&EXAMPLE_PART_02)[0], 2, 2), + " *\n* " + ) + } +} From da4b15923efdc083374af87cd27e92027be6ae14 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 9 Dec 2019 16:34:10 +0100 Subject: [PATCH 21/42] feat: well, that sucked. Added day 9 --- README.md | 1 + day_05/src/bin/main.rs | 2 +- day_05/src/lib.rs | 6 +- day_05/src/program.rs | 187 ++++++++++++++++++++--------------- day_07/src/main.rs | 36 +++---- day_09/Cargo.toml | 10 ++ day_09/src/main.rs | 43 +++++++++ day_09/src/program.rs | 214 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 401 insertions(+), 98 deletions(-) create mode 100644 day_09/Cargo.toml create mode 100644 day_09/src/main.rs create mode 100644 day_09/src/program.rs diff --git a/README.md b/README.md index 846b8e9..173256f 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,4 @@ - [Day 6](https://github.com/ankjevel/adventofcode/tree/2019/day_06) 🌟 🌟 - [Day 7](https://github.com/ankjevel/adventofcode/tree/2019/day_07) 🌟 🌟 - [Day 8](https://github.com/ankjevel/adventofcode/tree/2019/day_08) 🌟 🌟 +- [Day 9](https://github.com/ankjevel/adventofcode/tree/2019/day_09) 🌟 🌟 diff --git a/day_05/src/bin/main.rs b/day_05/src/bin/main.rs index c12da43..4aeca20 100644 --- a/day_05/src/bin/main.rs +++ b/day_05/src/bin/main.rs @@ -6,7 +6,7 @@ fn main() -> Result<()> { println!( "part_01: {:?}", - exec_without_channels(input[0].clone(), None) + exec_without_channels(input[0].clone(), Some(vec![1])) ); println!( "part_02: {:?}", diff --git a/day_05/src/lib.rs b/day_05/src/lib.rs index 69fe57c..ffb35b0 100644 --- a/day_05/src/lib.rs +++ b/day_05/src/lib.rs @@ -1,4 +1,4 @@ -pub fn parse_input(string: &str) -> Vec> { +pub fn parse_input(string: &str) -> Vec> { string .lines() .map(|string| string.trim()) @@ -6,8 +6,8 @@ pub fn parse_input(string: &str) -> Vec> { .map(|string| { string .split(',') - .map(|part| part.parse::().unwrap()) - .collect::>() + .map(|part| part.parse::().unwrap()) + .collect::>() }) .collect() } diff --git a/day_05/src/program.rs b/day_05/src/program.rs index 6074b28..91567cc 100644 --- a/day_05/src/program.rs +++ b/day_05/src/program.rs @@ -5,24 +5,33 @@ use std::{ thread::{spawn, JoinHandle}, }; +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +enum Mode { + Position, + Immediate, + Relative, +} + pub struct Program { - original_memory: Vec, + original_memory: Vec, pointer: usize, - input: Receiver, + relative_base: usize, + input: Receiver, halted: bool, - output: Sender, - output_value: i32, - pub memory: Vec, + output: Sender, + output_value: i64, + pub memory: Vec, } impl Program { - pub fn new(memory: &Vec) -> Program { + pub fn new(memory: &Vec) -> Program { let (output, input) = channel(); Program { original_memory: memory.clone(), pointer: 0, output_value: 0, + relative_base: 0, input, halted: false, memory: memory.clone(), @@ -30,33 +39,60 @@ impl Program { } } - pub fn new_input(&mut self, input: Receiver) { - self.input = input; + pub fn new_input(&mut self, receiver: Receiver) { + self.input = receiver; } - pub fn new_output(&mut self, output: Sender) { - self.output = output; + pub fn new_output(&mut self, sender: Sender) { + self.output = sender; } pub fn is_halted(&self) -> bool { self.halted } - fn get_index(&mut self, step: usize, positional: bool) -> usize { - if positional { - self.memory[self.pointer + step] as usize - } else { - self.pointer + step + fn get_index(&mut self, step: usize, mode: Mode) -> usize { + match mode { + Mode::Position => self.memory[self.pointer + step] as usize, + Mode::Immediate => self.pointer + step, + Mode::Relative => self.memory[self.pointer + step] as usize, + } + } + + fn ensure_memory_available(&mut self, position: &usize) { + if *position >= self.memory.len() { + self.memory.resize(position + 1, 0); } } - fn mode_1_2(&mut self, opcode: i32, positional_first: bool, positional_second: bool) -> usize { - let noun_index = self.get_index(1, positional_first); - let verb_index = self.get_index(2, positional_second); - let out_index = self.get_index(3, true); - let noun = self.memory[noun_index]; - let verb = self.memory[verb_index]; - self.memory[out_index] = if opcode == 1 { + fn get_memory<'a>(&'a mut self, step: usize, mode: Mode) -> i64 { + let next = match mode { + Mode::Relative => { + let index = &(self.pointer + step); + self.ensure_memory_available(&index); + self.memory[*index].to_owned() + (self.relative_base as i64) + } + _ => { + let index = &self.get_index(step, mode); + self.ensure_memory_available(&index); + self.memory[*index] + } + }; + + next + } + + fn get_mut_memory_ref<'a>(&'a mut self, index: &'a usize) -> &'a mut i64 { + self.ensure_memory_available(&index); + &mut self.memory[*index] + } + + fn mode_1_2(&mut self, opcode: i64, mode_first: Mode, mode_second: Mode) -> i64 { + let noun = self.get_memory(1, mode_first); + let verb = self.get_memory(2, mode_second); + let index = &self.get_index(3, Mode::Position); + + *self.get_mut_memory_ref(index) = if opcode == 1 { noun + verb } else { noun * verb @@ -65,13 +101,13 @@ impl Program { 4 } - fn mode_3_4(&mut self, opcode: i32) -> usize { - let index = self.get_index(1, true); + fn mode_3_4(&mut self, opcode: i64, mode: Mode) -> i64 { if opcode == 3 { let input = self.input.recv().unwrap_or(0); - self.memory[index] = input.to_owned(); + let index = &self.get_index(1, Mode::Position); + *self.get_mut_memory_ref(index) = input.to_owned(); } else { - let output = self.memory[index].clone(); + let output = self.get_memory(1, mode); self.output.send(output.to_owned()).unwrap_or(()); self.output_value = output.to_owned(); }; @@ -79,38 +115,23 @@ impl Program { 2 } - fn mode_5_6( - &mut self, - opcode: i32, - position_mode_first: bool, - position_mode_second: bool, - ) -> usize { - let first_index = self.get_index(1, position_mode_first); - let second_index = self.get_index(2, position_mode_second); - let param_1 = self.memory[first_index]; - let param_2 = self.memory[second_index]; + fn mode_5_6(&mut self, opcode: i64, mode_first: Mode, mode_second: Mode) -> i64 { + let param_1 = self.get_memory(1, mode_first); + let param_2 = self.get_memory(2, mode_second); if (opcode == 5 && param_1 != 0) || (opcode == 6 && param_1 == 0) { - param_2 as usize - self.pointer + param_2 - self.pointer as i64 } else { 3 } } - fn mode_7_8( - &mut self, - opcode: i32, - position_mode_first: bool, - position_mode_second: bool, - ) -> usize { - let first_index = self.get_index(1, position_mode_first); - let second_index = self.get_index(2, position_mode_second); - let third_index = self.get_index(3, true); + fn mode_7_8(&mut self, opcode: i64, mode_first: Mode, mode_second: Mode) -> i64 { + let a = self.get_memory(1, mode_first); + let b = self.get_memory(2, mode_second); + let index = &self.get_index(3, Mode::Position); - let a = self.memory[first_index]; - let b = self.memory[second_index]; - - self.memory[third_index] = if (opcode == 7 && a < b) || (opcode == 8 && a == b) { + *self.get_mut_memory_ref(index) = if (opcode == 7 && a < b) || (opcode == 8 && a == b) { 1 } else { 0 @@ -118,19 +139,33 @@ impl Program { 4 } - fn to_int(&mut self, input: &char) -> i32 { - (&input.to_string()).parse::().unwrap() + fn mode_9(&mut self, mode: Mode) -> i64 { + let memory = self.get_memory(1, mode) as usize; + let relative_base = self.relative_base + memory as usize; + + self.relative_base = relative_base; + 2 + } + + fn to_int(&mut self, input: &char) -> i64 { + (&input.to_string()).parse::().unwrap() } - fn position_mode(&mut self, input: &Option) -> bool { - input.unwrap_or('0') == '0' + fn mode(&mut self, input: &Option) -> Mode { + match input.unwrap_or('0') { + '0' => Mode::Position, + '1' => Mode::Immediate, + '2' => Mode::Relative, + _ => Mode::Position, + } } - pub fn run(&mut self) -> i32 { + pub fn run(&mut self) -> i64 { self.pointer = 0; self.output_value = 0; self.halted = false; self.memory = self.original_memory.clone(); + self.relative_base = 0; while !self.halted { self.eval() @@ -151,48 +186,48 @@ impl Program { let mut instuction = string.chars().rev(); let opcode = self.to_int(&instuction.next().unwrap()); instuction.next(); - let positional_first = self.position_mode(&instuction.next()); - let positional_second = self.position_mode(&instuction.next()); - - self.pointer += match opcode { - 1 | 2 => self.mode_1_2(opcode, positional_first, positional_second), - 3 | 4 => self.mode_3_4(opcode), - 5 | 6 => self.mode_5_6(opcode, positional_first, positional_second), - 7 | 8 => self.mode_7_8(opcode, positional_first, positional_second), - 9 => { - self.halted = true; - 0 - } + let mode_first = self.mode(&instuction.next()); + let mode_second = self.mode(&instuction.next()); + + let next = match opcode { + 1 | 2 => self.mode_1_2(opcode, mode_first, mode_second), + 3 | 4 => self.mode_3_4(opcode, mode_first), + 5 | 6 => self.mode_5_6(opcode, mode_first, mode_second), + 7 | 8 => self.mode_7_8(opcode, mode_first, mode_second), + 9 => self.mode_9(mode_first), _ => panic!("[{}], opcode: {}", self.pointer, opcode), }; + + self.pointer = ((self.pointer as i64) + next) as usize; } } -pub fn exec(memory: Vec, input: Receiver, output: Sender) -> JoinHandle { +pub fn exec(memory: Vec, receiver: Receiver, sender: Sender) -> JoinHandle { spawn(move || { let mut program = Program::new(&memory); - program.new_input(input); - program.new_output(output); + program.new_input(receiver); + program.new_output(sender); program.run() }) } -pub fn exec_without_channels(memory: Vec, input: Option>) -> i32 { - let (c_out, c_in) = channel(); +pub fn exec_without_channels(memory: Vec, input: Option>) -> i64 { + let (sender, receiver) = channel(); match input { Some(input) => { for seq in input.clone() { - c_out.send(seq).unwrap(); + sender.send(seq).unwrap(); } } None => { - c_out.send(0).unwrap(); + sender.send(0).unwrap(); } }; + spawn(move || { let mut program = Program::new(&memory); - program.new_input(c_in); - program.new_output(c_out); + program.new_input(receiver); + program.new_output(sender); program.run() }) .join() diff --git a/day_07/src/main.rs b/day_07/src/main.rs index 5a544f9..9f9e249 100644 --- a/day_07/src/main.rs +++ b/day_07/src/main.rs @@ -8,7 +8,7 @@ use day_05::{ use permute::permute; use std::{iter::Iterator, sync::mpsc::channel}; -fn part_01(sequence: &Vec, memory: &Vec) -> i32 { +fn part_01(sequence: &Vec, memory: &Vec) -> i64 { let mut input = vec![0]; for signal in sequence { input.insert(0, signal.to_owned()); @@ -20,28 +20,28 @@ fn part_01(sequence: &Vec, memory: &Vec) -> i32 { input[0] } -fn part_02(sequence: &Vec, memory: &Vec) -> i32 { +fn part_02(sequence: &Vec, memory: &Vec) -> i64 { let mut seq = sequence.to_owned(); let mut iter = seq.iter_mut(); - let (e_out, a_in) = channel(); - let (a_out, b_in) = channel(); - let (b_out, c_in) = channel(); - let (c_out, d_in) = channel(); - let (d_out, e_in) = channel(); + let (e_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + let (b_sender, c_receiver) = channel(); + let (c_sender, d_receiver) = channel(); + let (d_sender, e_receiver) = channel(); - e_out.send(*iter.next().unwrap()).unwrap(); - a_out.send(*iter.next().unwrap()).unwrap(); - b_out.send(*iter.next().unwrap()).unwrap(); - c_out.send(*iter.next().unwrap()).unwrap(); - d_out.send(*iter.next().unwrap()).unwrap(); - e_out.send(0).unwrap(); + e_sender.send(*iter.next().unwrap()).unwrap(); + a_sender.send(*iter.next().unwrap()).unwrap(); + b_sender.send(*iter.next().unwrap()).unwrap(); + c_sender.send(*iter.next().unwrap()).unwrap(); + d_sender.send(*iter.next().unwrap()).unwrap(); + e_sender.send(0).unwrap(); - exec(memory.clone(), a_in, a_out); - exec(memory.clone(), b_in, b_out); - exec(memory.clone(), c_in, c_out); - exec(memory.clone(), d_in, d_out); - exec(memory.clone(), e_in, e_out).join().unwrap() + exec(memory.clone(), a_receiver, a_sender); + exec(memory.clone(), b_receiver, b_sender); + exec(memory.clone(), c_receiver, c_sender); + exec(memory.clone(), d_receiver, d_sender); + exec(memory.clone(), e_receiver, e_sender).join().unwrap() } fn main() { diff --git a/day_09/Cargo.toml b/day_09/Cargo.toml new file mode 100644 index 0000000..21f268e --- /dev/null +++ b/day_09/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day_09" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +day_05 = { path = "../day_05" } diff --git a/day_09/src/main.rs b/day_09/src/main.rs new file mode 100644 index 0000000..e70daff --- /dev/null +++ b/day_09/src/main.rs @@ -0,0 +1,43 @@ +extern crate day_05; + +mod program; + +use day_05::parse_input; + +use program::exec; + +fn main() { + let input = parse_input(include_str!("../../input/day_09")); + println!("part_01, {:?}", exec(&input[0], Some(vec![1]))); + println!("part_02, {:?}", exec(&input[0], Some(vec![2]))); +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLES_ON_PART_01: &'static str = " + 1102,34915192,34915192,7,4,7,99,0 + 104,1125899906842624,99 + "; + + #[test] + #[ignore] + fn it_gets_the_examples_right_on_part_01() { + let input = parse_input(&EXAMPLES_ON_PART_01); + + assert_eq!(exec(&input[1], None), 1219070632396864); + assert_eq!(exec(&input[2], None), 1125899906842624); + } + + #[test] + fn quine() { + let input = vec![ + 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, + ]; + let mut program = program::Program::new(&input); + program.input = vec![]; + assert_eq!(program.run(), 99); + assert_eq!(program.output, input.clone()); + } +} diff --git a/day_09/src/program.rs b/day_09/src/program.rs new file mode 100644 index 0000000..411d97f --- /dev/null +++ b/day_09/src/program.rs @@ -0,0 +1,214 @@ +use std::{iter::Iterator, option::Option}; + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +enum Mode { + Position, + Immediate, + Relative, +} + +pub struct Program { + original_memory: Vec, + pointer: usize, + relative_base: usize, + halted: bool, + pub input: Vec, + pub output: Vec, + pub memory: Vec, +} + +impl Program { + pub fn new(memory: &Vec) -> Program { + Program { + original_memory: memory.clone(), + pointer: 0, + relative_base: 0, + input: vec![0], + halted: false, + memory: memory.clone(), + output: vec![], + } + } + + fn get_next_input(&mut self) -> Option { + match self.input.iter_mut().next() { + Some(input) => Some(*input), + _ => None, + } + } + + fn get_index(&mut self, step: usize, mode: Mode) -> usize { + let parameter = self.pointer + step; + + match mode { + Mode::Immediate => parameter, + _ => self.memory[parameter] as usize, + } + } + + fn get_memory<'a>(&'a mut self, step: usize, mode: Mode) -> i64 { + let mut index = self.get_index(step, mode); + + if mode == Mode::Relative { + index = ((index as i64) + (self.relative_base as i64)) as usize; + } + + if let Some(&value) = self.memory.get(index.to_owned() as usize) { + value + } else { + 0 + } + } + + fn ensure_memory_available(&mut self, position: &usize) { + if *position >= self.memory.len() { + self.memory.resize(position + 1, 0); + } + } + + fn get_mut_memory_ref<'a>(&'a mut self, step: usize, mode: Mode) -> &'a mut i64 { + let mut index = self.get_index(step, mode) as i64; + + if mode == Mode::Relative { + index += self.relative_base as i64; + } + + let usize_index = index as usize; + + self.ensure_memory_available(&usize_index); + &mut self.memory[usize_index] + } + + fn to_int(&mut self, input: &char) -> i64 { + (&input.to_string()).parse::().unwrap() + } + + fn mode(&mut self, input: &Option) -> Mode { + match input.unwrap_or('0') { + '0' => Mode::Position, + '1' => Mode::Immediate, + '2' => Mode::Relative, + _ => Mode::Position, + } + } + + fn opcode_1_2( + &mut self, + opcode: i64, + mode_first: Mode, + mode_second: Mode, + mode_third: Mode, + ) -> i64 { + let a = self.get_memory(1, mode_first); + let b = self.get_memory(2, mode_second); + + *self.get_mut_memory_ref(3, mode_third) = if opcode == 1 { a + b } else { a * b }; + 4 + } + + fn opcode_3_4(&mut self, opcode: i64, mode: Mode) -> i64 { + if opcode == 3 { + match self.get_next_input() { + Some(input) => { + *self.get_mut_memory_ref(1, mode) = input; + } + _ => {} + } + } else { + let output = self.get_memory(1, mode); + self.output.push(output); + }; + 2 + } + + fn opcode_5_6(&mut self, opcode: i64, mode_first: Mode, mode_second: Mode) -> i64 { + let a = self.get_memory(1, mode_first); + let b = self.get_memory(2, mode_second); + + if (opcode == 5 && a != 0) || (opcode == 6 && a == 0) { + b - self.pointer as i64 + } else { + 3 + } + } + + fn opcode_7_8( + &mut self, + opcode: i64, + mode_first: Mode, + mode_second: Mode, + mode_third: Mode, + ) -> i64 { + let a = self.get_memory(1, mode_first); + let b = self.get_memory(2, mode_second); + + *self.get_mut_memory_ref(3, mode_third) = + if (opcode == 7 && a < b) || (opcode == 8 && a == b) { + 1 + } else { + 0 + }; + 4 + } + + fn opcode_9(&mut self, mode: Mode) -> i64 { + let memory = self.get_memory(1, mode); + let relative_base = (self.relative_base as i64) + memory; + self.relative_base = relative_base as usize; + 2 + } + + pub fn run(&mut self) -> i64 { + self.pointer = 0; + self.halted = false; + self.memory = self.original_memory.clone(); + self.relative_base = 0; + self.output.clear(); + + while !self.halted { + self.eval() + } + + *self.output.clone().iter().last().unwrap_or(&0i64) + } + + fn eval(&mut self) { + let string = self.memory[self.pointer].to_string(); + let mut instuction = string.chars().rev(); + + let opcode = self.to_int(&instuction.next().unwrap()); + let opcode_padding = self.to_int(&instuction.next().unwrap_or('0')); + + let mode_first = self.mode(&instuction.next()); + let mode_second = self.mode(&instuction.next()); + let mode_third = self.mode(&instuction.next()); + + + if opcode == 9 && opcode_padding == 9 { + self.halted = true; + return; + } + + let next = match opcode { + 1 | 2 => self.opcode_1_2(opcode, mode_first, mode_second, mode_third), + 3 | 4 => self.opcode_3_4(opcode, mode_first), + 5 | 6 => self.opcode_5_6(opcode, mode_first, mode_second), + 7 | 8 => self.opcode_7_8(opcode, mode_first, mode_second, mode_third), + 9 => self.opcode_9(mode_first), + _ => panic!("[{}], opcode: {}", self.pointer, opcode), + }; + + self.pointer = ((self.pointer as i64) + next) as usize; + } +} + +pub fn exec(memory: &Vec, input: Option>) -> i64 { + let input_unwrapped = match input { + Some(input) => input.to_owned(), + None => vec![0], + }; + + let mut program = Program::new(memory); + program.input = input_unwrapped; + program.run() +} From 548ee58262deed77ec84aa1b9ca949fc6c650562 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Tue, 10 Dec 2019 12:09:02 +0100 Subject: [PATCH 22/42] feat: added part 1 of day 10 --- README.md | 1 + day_10/Cargo.toml | 14 ++++++ day_10/src/bin/main.rs | 102 +++++++++++++++++++++++++++++++++++++++++ day_10/src/lib.rs | 31 +++++++++++++ day_10/src/part_01.rs | 55 ++++++++++++++++++++++ day_10/src/point.rs | 14 ++++++ 6 files changed, 217 insertions(+) create mode 100644 day_10/Cargo.toml create mode 100644 day_10/src/bin/main.rs create mode 100644 day_10/src/lib.rs create mode 100644 day_10/src/part_01.rs create mode 100644 day_10/src/point.rs diff --git a/README.md b/README.md index 173256f..dff5559 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,4 @@ - [Day 7](https://github.com/ankjevel/adventofcode/tree/2019/day_07) 🌟 🌟 - [Day 8](https://github.com/ankjevel/adventofcode/tree/2019/day_08) 🌟 🌟 - [Day 9](https://github.com/ankjevel/adventofcode/tree/2019/day_09) 🌟 🌟 +- [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 diff --git a/day_10/Cargo.toml b/day_10/Cargo.toml new file mode 100644 index 0000000..a5eaad9 --- /dev/null +++ b/day_10/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "day_10" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +float-cmp = "0.6.0" + +[[bin]] +name = "day_10" +path = "src/bin/main.rs" diff --git a/day_10/src/bin/main.rs b/day_10/src/bin/main.rs new file mode 100644 index 0000000..81d4479 --- /dev/null +++ b/day_10/src/bin/main.rs @@ -0,0 +1,102 @@ +use ::day_10::{parse_input, part_01::main as part_01, to_points}; + +fn main() { + let input = to_points(&parse_input(include_str!("../../../input/day_10"))); + println!("part_01: {}", part_01(&input).0); +} + +#[cfg(test)] +#[allow(dead_code)] +mod tests { + use ::day_10::{parse_input, part_01::main as part_01, point::Point, to_points}; + + const EXAMPLE_01_00: &'static str = " + .#..# + ..... + ##### + ....# + ...x# + "; + + const EXAMPLE_01_01: &'static str = " + ......#.#. + #..#.#.... + ..#######. + .#.#.###.. + .#..#..... + ..#....#.# + #..#....#. + .##.#..### + ##...x..#. + .#....#### + "; + + const EXAMPLE_01_02: &'static str = " + #.#...#.#. + .###....#. + .x....#... + ##.#.#.#.# + ....#.#.#. + .##..###.# + ..#...##.. + ..##....## + ......#... + .####.###. + "; + + const EXAMPLE_01_03: &'static str = " + .#..#..### + ####.###.# + ....###.#. + ..###.x#.# + ##.##.#.#. + ....###..# + ..#.#..#.# + #..#.#.### + .##...##.# + .....#.#.. + "; + + const EXAMPLE_01_04: &'static str = " + .#..##.###...####### + ##.############..##. + .#.######.########.# + .###.#######.####.#. + #####.##.#.##.###.## + ..#####..#.######### + #################### + #.####....###.#.#.## + ##.################# + #####.##.###..####.. + ..######..##.####### + ####.##.####...##..# + .#####..#.######.### + ##...#.####x#####... + #.##########.####### + .####.#.###.###.#.## + ....##.##.###..##### + .#.#.###########.### + #.#.#.#####.####.### + ###.##.####.##.#..## + "; + + #[test] + fn it_gets_the_examples_on_part_01_right() { + let inputs: Vec> = vec![ + EXAMPLE_01_00, + EXAMPLE_01_01, + EXAMPLE_01_02, + EXAMPLE_01_03, + EXAMPLE_01_04, + ] + .into_iter() + .map(|example| to_points(&parse_input(&example))) + .collect(); + + assert_eq!(part_01(&inputs[0]), (8, Some(Point { x: 3, y: 4 }))); + assert_eq!(part_01(&inputs[1]), (33, Some(Point { x: 5, y: 8 }))); + assert_eq!(part_01(&inputs[2]), (35, Some(Point { x: 1, y: 2 }))); + assert_eq!(part_01(&inputs[3]), (41, Some(Point { x: 6, y: 3 }))); + assert_eq!(part_01(&inputs[4]), (210, Some(Point { x: 11, y: 13 }))); + } +} diff --git a/day_10/src/lib.rs b/day_10/src/lib.rs new file mode 100644 index 0000000..90f43c6 --- /dev/null +++ b/day_10/src/lib.rs @@ -0,0 +1,31 @@ +#[macro_use] +extern crate float_cmp; + +pub mod part_01; +pub mod point; + +pub type Input = Vec>; + +pub fn to_points(input: &Input) -> Vec { + let mut points = Vec::new(); + for (y, row) in input.into_iter().enumerate() { + for (x, item) in row.into_iter().enumerate() { + if item == &'.' { + continue; + } + + points.push(point::Point::from_usize(x, y)); + } + } + + points +} + +pub fn parse_input(string: &str) -> Input { + string + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|string| string.chars().collect()) + .collect() +} diff --git a/day_10/src/part_01.rs b/day_10/src/part_01.rs new file mode 100644 index 0000000..bd805de --- /dev/null +++ b/day_10/src/part_01.rs @@ -0,0 +1,55 @@ +use crate::point::Point; + +fn distance(p1: &Point, p2: &Point) -> f64 { + ((p2.x as f64 - p1.x as f64).powf(2f64) + (p2.y as f64 - p1.y as f64).powf(2f64)).sqrt() +} + +fn is_between(a: &Point, c: &Point, b: &Point) -> bool { + approx_eq!( + f64, + distance(&a, &c) + distance(&c, &b), + distance(&a, &b), + ulps = 2 + ) +} + +pub fn main(input: &Vec) -> (u32, Option) { + let mut max = 0; + let mut best_match = None; + + 'a: for a in input { + let mut new_max = 0; + let mut matches = Vec::new(); + + 'b: for b in input { + if b == a { + continue 'b; + } + + let mut intersected = false; + + 'c: for c in input { + if a == c || b == c { + continue 'c; + } + + if is_between(a, c, b) { + intersected = true; + break 'c; + } + } + + if !intersected { + matches.push(b.clone()); + new_max += 1; + } + } + + if new_max > max { + best_match = Some(a.clone()); + max = new_max; + } + } + + (max, best_match) +} diff --git a/day_10/src/point.rs b/day_10/src/point.rs new file mode 100644 index 0000000..e5cfb90 --- /dev/null +++ b/day_10/src/point.rs @@ -0,0 +1,14 @@ +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct Point { + pub x: u64, + pub y: u64, +} + +impl Point { + pub fn from_usize(x: usize, y: usize) -> Point { + Point { + x: x as u64, + y: y as u64, + } + } +} From d7e67dd79f26a2af6839169f59285bc4665195d9 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Tue, 10 Dec 2019 15:16:53 +0100 Subject: [PATCH 23/42] feat: completed day 10 ... hacky as hell... --- README.md | 2 +- day_10/src/angle.rs | 39 +++++++++++++++++++++++ day_10/src/bin/main.rs | 18 +++++++++-- day_10/src/lib.rs | 2 ++ day_10/src/part_01.rs | 4 +-- day_10/src/part_02.rs | 72 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 day_10/src/angle.rs create mode 100644 day_10/src/part_02.rs diff --git a/README.md b/README.md index dff5559..2bbc24a 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,4 @@ - [Day 7](https://github.com/ankjevel/adventofcode/tree/2019/day_07) 🌟 🌟 - [Day 8](https://github.com/ankjevel/adventofcode/tree/2019/day_08) 🌟 🌟 - [Day 9](https://github.com/ankjevel/adventofcode/tree/2019/day_09) 🌟 🌟 -- [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 +- [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 🌟 diff --git a/day_10/src/angle.rs b/day_10/src/angle.rs new file mode 100644 index 0000000..d189dc3 --- /dev/null +++ b/day_10/src/angle.rs @@ -0,0 +1,39 @@ +use std::cmp::{ + Eq, + Ordering::{self, Equal, Greater, Less}, +}; + +#[derive(Debug)] +pub struct Angle(f64); + +impl Angle { + pub fn new(input: &f64) -> Angle { + Angle(*input) + } +} + +impl PartialEq for Angle { + fn eq(&self, other: &Self) -> bool { + approx_eq!(f64, self.0, other.0, ulps = 2) + } +} + +impl Eq for Angle {} + +impl Ord for Angle { + fn cmp(&self, other: &Angle) -> Ordering { + if self.0 > other.0 { + Greater + } else if self.0 < other.0 { + Less + } else { + Equal + } + } +} + +impl PartialOrd for Angle { + fn partial_cmp(&self, other: &Angle) -> Option { + Some(self.cmp(other)) + } +} diff --git a/day_10/src/bin/main.rs b/day_10/src/bin/main.rs index 81d4479..fa22683 100644 --- a/day_10/src/bin/main.rs +++ b/day_10/src/bin/main.rs @@ -1,14 +1,18 @@ -use ::day_10::{parse_input, part_01::main as part_01, to_points}; +use ::day_10::{parse_input, part_01::main as part_01, part_02::main as part_02, to_points}; fn main() { let input = to_points(&parse_input(include_str!("../../../input/day_10"))); - println!("part_01: {}", part_01(&input).0); + let (result_part_01, input_for_part_02) = part_01(&input); + println!("part_01: {}", result_part_01); + println!("part_02: {}", part_02(&input, &input_for_part_02)); } #[cfg(test)] #[allow(dead_code)] mod tests { - use ::day_10::{parse_input, part_01::main as part_01, point::Point, to_points}; + use ::day_10::{ + parse_input, part_01::main as part_01, part_02::main as part_02, point::Point, to_points, + }; const EXAMPLE_01_00: &'static str = " .#..# @@ -99,4 +103,12 @@ mod tests { assert_eq!(part_01(&inputs[3]), (41, Some(Point { x: 6, y: 3 }))); assert_eq!(part_01(&inputs[4]), (210, Some(Point { x: 11, y: 13 }))); } + + #[test] + fn it_gets_the_example_on_part_02_right() { + let input = to_points(&parse_input(&EXAMPLE_01_04)); + let start = Some(Point { x: 11, y: 13 }); + + assert_eq!(part_02(&input, &start), 802); + } } diff --git a/day_10/src/lib.rs b/day_10/src/lib.rs index 90f43c6..58d4c6f 100644 --- a/day_10/src/lib.rs +++ b/day_10/src/lib.rs @@ -1,7 +1,9 @@ #[macro_use] extern crate float_cmp; +pub mod angle; pub mod part_01; +pub mod part_02; pub mod point; pub type Input = Vec>; diff --git a/day_10/src/part_01.rs b/day_10/src/part_01.rs index bd805de..9e9ab05 100644 --- a/day_10/src/part_01.rs +++ b/day_10/src/part_01.rs @@ -1,10 +1,10 @@ use crate::point::Point; -fn distance(p1: &Point, p2: &Point) -> f64 { +pub fn distance(p1: &Point, p2: &Point) -> f64 { ((p2.x as f64 - p1.x as f64).powf(2f64) + (p2.y as f64 - p1.y as f64).powf(2f64)).sqrt() } -fn is_between(a: &Point, c: &Point, b: &Point) -> bool { +pub fn is_between(a: &Point, c: &Point, b: &Point) -> bool { approx_eq!( f64, distance(&a, &c) + distance(&c, &b), diff --git a/day_10/src/part_02.rs b/day_10/src/part_02.rs new file mode 100644 index 0000000..94b4638 --- /dev/null +++ b/day_10/src/part_02.rs @@ -0,0 +1,72 @@ +use crate::{angle::Angle, part_01::is_between, point::Point}; + +use std::{ + cmp::Ordering::{Equal, Greater, Less}, + collections::BTreeMap, + f64::consts::PI, +}; + +type Map = BTreeMap>; + +fn to_map(input: &Vec, start: &Point) -> Map { + let mut map: Map = BTreeMap::new(); + + for point in input { + if point == start { + continue; + } + let ax = point.x as f64; + let ay = point.y as f64; + let bx = start.x as f64; + let by = start.y as f64; + let mut angle = (ay - by).atan2(ax - bx) * (180f64 / PI) + 90f64; + + if angle < 0f64 { + angle = 360f64 + angle; + } + + let reference = map.entry(Angle::new(&angle)).or_insert(Vec::new()); + reference.push(point.clone()); + reference.sort_by(|a, b| { + if is_between(start, a, b) { + Greater + } else if is_between(start, b, a) { + Less + } else { + Equal + } + }); + } + + map +} + +pub fn main(input: &Vec, maybe_start: &Option) -> u64 { + let start = maybe_start.unwrap_or_else(|| panic!("missing start position")); + let mut map = to_map(&input, &start); + let mut vec = Vec::new(); + + for (_, item) in &map { + vec.push(item.clone()); + } + + map.clear(); // freeeeeee! + let mut ordered = Vec::new(); + 'outer: loop { + 'inner: for x in vec.iter_mut() { + if ordered.len() >= 200 { + break 'outer; + } + + if x.len() == 0 { + continue 'inner; + } + + let this = x.into_iter().next().unwrap(); + ordered.push(*this); + } + break 'outer; + } + let last = ordered.into_iter().last().unwrap(); + (last.x * 100) + last.y +} From f99a1f2218da41721e6fd5aa15274456b0355fdf Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Wed, 11 Dec 2019 07:31:33 +0100 Subject: [PATCH 24/42] chore: scaffolding for day 11 --- day_10/Cargo.toml | 4 ---- day_10/src/{bin => }/main.rs | 2 +- day_11/Cargo.toml | 9 +++++++++ day_11/src/intcode.rs | 2 ++ day_11/src/lib.rs | 11 +++++++++++ day_11/src/main.rs | 11 +++++++++++ 6 files changed, 34 insertions(+), 5 deletions(-) rename day_10/src/{bin => }/main.rs (97%) create mode 100644 day_11/Cargo.toml create mode 100644 day_11/src/intcode.rs create mode 100644 day_11/src/lib.rs create mode 100644 day_11/src/main.rs diff --git a/day_10/Cargo.toml b/day_10/Cargo.toml index a5eaad9..c27226f 100644 --- a/day_10/Cargo.toml +++ b/day_10/Cargo.toml @@ -8,7 +8,3 @@ edition = "2018" [dependencies] float-cmp = "0.6.0" - -[[bin]] -name = "day_10" -path = "src/bin/main.rs" diff --git a/day_10/src/bin/main.rs b/day_10/src/main.rs similarity index 97% rename from day_10/src/bin/main.rs rename to day_10/src/main.rs index fa22683..87c98fd 100644 --- a/day_10/src/bin/main.rs +++ b/day_10/src/main.rs @@ -1,7 +1,7 @@ use ::day_10::{parse_input, part_01::main as part_01, part_02::main as part_02, to_points}; fn main() { - let input = to_points(&parse_input(include_str!("../../../input/day_10"))); + let input = to_points(&parse_input(include_str!("../../input/day_10"))); let (result_part_01, input_for_part_02) = part_01(&input); println!("part_01: {}", result_part_01); println!("part_02: {}", part_02(&input, &input_for_part_02)); diff --git a/day_11/Cargo.toml b/day_11/Cargo.toml new file mode 100644 index 0000000..572ca04 --- /dev/null +++ b/day_11/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day_11" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day_11/src/intcode.rs b/day_11/src/intcode.rs new file mode 100644 index 0000000..2de7916 --- /dev/null +++ b/day_11/src/intcode.rs @@ -0,0 +1,2 @@ +pub struct Program { +} diff --git a/day_11/src/lib.rs b/day_11/src/lib.rs new file mode 100644 index 0000000..e63892e --- /dev/null +++ b/day_11/src/lib.rs @@ -0,0 +1,11 @@ +pub fn parse_input(input: &str) -> Vec { + input + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .next() + .unwrap() + .split(',') + .map(|part| part.parse::().unwrap()) + .collect::>() +} \ No newline at end of file diff --git a/day_11/src/main.rs b/day_11/src/main.rs new file mode 100644 index 0000000..1b29971 --- /dev/null +++ b/day_11/src/main.rs @@ -0,0 +1,11 @@ +use ::day_11::{parse_input}; + +fn main() { + let input = parse_input(&include_str!("../../input/day_11")); + println!("{:?}", input); +} + +#[cfg(test)] +#[allow(dead_code)] +mod tests { +} From fa3c9a53eae8e035d1ccc9647ca849314b9e7fc7 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Thu, 12 Dec 2019 07:48:10 +0100 Subject: [PATCH 25/42] chore: had to update example on day 9 to handle channels --- day_09/src/lib.rs | 3 ++ day_09/src/main.rs | 53 ++++++++++++++++-------- day_09/src/program.rs | 74 ++++++++++++++++++++------------- day_11/Cargo.toml | 1 + day_11/src/direction.rs | 28 +++++++++++++ day_11/src/intcode.rs | 2 - day_11/src/lib.rs | 8 +++- day_11/src/main.rs | 25 ++++++++--- day_11/src/painting_robot.rs | 80 ++++++++++++++++++++++++++++++++++++ day_11/src/point.rs | 7 ++++ 10 files changed, 229 insertions(+), 52 deletions(-) create mode 100644 day_09/src/lib.rs create mode 100644 day_11/src/direction.rs delete mode 100644 day_11/src/intcode.rs create mode 100644 day_11/src/painting_robot.rs create mode 100644 day_11/src/point.rs diff --git a/day_09/src/lib.rs b/day_09/src/lib.rs new file mode 100644 index 0000000..fc62a68 --- /dev/null +++ b/day_09/src/lib.rs @@ -0,0 +1,3 @@ +extern crate day_05; + +pub mod program; diff --git a/day_09/src/main.rs b/day_09/src/main.rs index e70daff..924a78e 100644 --- a/day_09/src/main.rs +++ b/day_09/src/main.rs @@ -1,20 +1,17 @@ -extern crate day_05; - -mod program; - +use ::day_09::program::exec; use day_05::parse_input; -use program::exec; - fn main() { let input = parse_input(include_str!("../../input/day_09")); - println!("part_01, {:?}", exec(&input[0], Some(vec![1]))); - println!("part_02, {:?}", exec(&input[0], Some(vec![2]))); + println!("part_01, {:?}", exec(input[0].clone(), Some(vec![1]))); + println!("part_02, {:?}", exec(input[0].clone(), Some(vec![2]))); } #[cfg(test)] mod tests { - use super::*; + use ::day_09::program::{exec, Program}; + use day_05::parse_input; + use std::{sync::mpsc::channel, thread::spawn}; const EXAMPLES_ON_PART_01: &'static str = " 1102,34915192,34915192,7,4,7,99,0 @@ -22,22 +19,46 @@ mod tests { "; #[test] - #[ignore] fn it_gets_the_examples_right_on_part_01() { let input = parse_input(&EXAMPLES_ON_PART_01); - assert_eq!(exec(&input[1], None), 1219070632396864); - assert_eq!(exec(&input[2], None), 1125899906842624); + assert_eq!(exec(input[0].clone(), None), 1219070632396864); + assert_eq!(exec(input[1].clone(), None), 1125899906842624); } #[test] fn quine() { + let (b_sender, a_receiver) = channel(); + let (_, b_receiver) = channel(); + + let output_thread = spawn(move || { + let mut output = vec![]; + loop { + let new_output = match a_receiver.recv() { + Ok(val) => val, + _ => break, + }; + &output.push(new_output); + } + output.to_owned() + }); + let input = vec![ 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, ]; - let mut program = program::Program::new(&input); - program.input = vec![]; - assert_eq!(program.run(), 99); - assert_eq!(program.output, input.clone()); + + let thread_input = input.clone(); + let result = spawn(move || { + let mut program = Program::new(&thread_input); + program.new_input(b_receiver); + program.new_output(b_sender); + program.run() + }) + .join() + .unwrap(); + + assert_eq!(result, 99); + + assert_eq!(output_thread.join().unwrap(), input.clone()); } } diff --git a/day_09/src/program.rs b/day_09/src/program.rs index 411d97f..cc4132d 100644 --- a/day_09/src/program.rs +++ b/day_09/src/program.rs @@ -1,4 +1,9 @@ -use std::{iter::Iterator, option::Option}; +use std::{ + iter::Iterator, + option::Option, + sync::mpsc::{channel, Receiver, Sender}, + thread::spawn, +}; #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] enum Mode { @@ -12,29 +17,34 @@ pub struct Program { pointer: usize, relative_base: usize, halted: bool, - pub input: Vec, - pub output: Vec, + input: Receiver, + output: Sender, + output_value: i64, pub memory: Vec, } impl Program { pub fn new(memory: &Vec) -> Program { + let (output, input) = channel(); + Program { original_memory: memory.clone(), pointer: 0, relative_base: 0, - input: vec![0], + input, halted: false, memory: memory.clone(), - output: vec![], + output, + output_value: 0, } } - fn get_next_input(&mut self) -> Option { - match self.input.iter_mut().next() { - Some(input) => Some(*input), - _ => None, - } + pub fn new_input(&mut self, receiver: Receiver) { + self.input = receiver; + } + + pub fn new_output(&mut self, sender: Sender) { + self.output = sender; } fn get_index(&mut self, step: usize, mode: Mode) -> usize { @@ -108,15 +118,12 @@ impl Program { fn opcode_3_4(&mut self, opcode: i64, mode: Mode) -> i64 { if opcode == 3 { - match self.get_next_input() { - Some(input) => { - *self.get_mut_memory_ref(1, mode) = input; - } - _ => {} - } + let input = self.input.recv().unwrap_or(0); + *self.get_mut_memory_ref(1, mode) = input; } else { let output = self.get_memory(1, mode); - self.output.push(output); + self.output.send(output.to_owned()).unwrap(); + self.output_value = output; }; 2 } @@ -160,16 +167,16 @@ impl Program { pub fn run(&mut self) -> i64 { self.pointer = 0; + self.output_value = 0; self.halted = false; self.memory = self.original_memory.clone(); self.relative_base = 0; - self.output.clear(); while !self.halted { - self.eval() + self.eval(); } - *self.output.clone().iter().last().unwrap_or(&0i64) + self.output_value.to_owned() } fn eval(&mut self) { @@ -183,7 +190,6 @@ impl Program { let mode_second = self.mode(&instuction.next()); let mode_third = self.mode(&instuction.next()); - if opcode == 9 && opcode_padding == 9 { self.halted = true; return; @@ -202,13 +208,25 @@ impl Program { } } -pub fn exec(memory: &Vec, input: Option>) -> i64 { - let input_unwrapped = match input { - Some(input) => input.to_owned(), - None => vec![0], +pub fn exec(memory: Vec, output: Option>) -> i64 { + let (program_sender, _exec_reciever) = channel(); + let (exec_sender, program_receiver) = channel(); + + match output { + Some(vec) => { + vec.into_iter().for_each(|val| { + exec_sender.send(val).unwrap(); + }); + } + None => {} }; - let mut program = Program::new(memory); - program.input = input_unwrapped; - program.run() + let handle = spawn(move || { + let mut program = Program::new(&memory); + program.new_input(program_receiver); + program.new_output(program_sender); + program.run() + }); + + handle.join().unwrap() } diff --git a/day_11/Cargo.toml b/day_11/Cargo.toml index 572ca04..c98f988 100644 --- a/day_11/Cargo.toml +++ b/day_11/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +day_09 = { path = "../day_09" } diff --git a/day_11/src/direction.rs b/day_11/src/direction.rs new file mode 100644 index 0000000..bb84d2c --- /dev/null +++ b/day_11/src/direction.rs @@ -0,0 +1,28 @@ +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Dir { + Up, + Right, + Down, + Left, +} + +use Dir::*; + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct Direction(pub Dir); + +impl Direction { + pub fn new() -> Direction { + Direction(Up) + } + + pub fn turn(&mut self, turn: u8) { + self.0 = match (self.0, turn) { + (Up, 0) | (Down, 1) => Left, + (Right, 0) | (Left, 1) => Up, + (Down, 0) | (Up, 1) => Right, + (Left, 0) | (Right, 1) => Down, + _ => panic!("turn not covered"), + } + } +} diff --git a/day_11/src/intcode.rs b/day_11/src/intcode.rs deleted file mode 100644 index 2de7916..0000000 --- a/day_11/src/intcode.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub struct Program { -} diff --git a/day_11/src/lib.rs b/day_11/src/lib.rs index e63892e..0b6b80a 100644 --- a/day_11/src/lib.rs +++ b/day_11/src/lib.rs @@ -1,3 +1,9 @@ +extern crate day_09; + +pub mod direction; +pub mod painting_robot; +pub mod point; + pub fn parse_input(input: &str) -> Vec { input .lines() @@ -8,4 +14,4 @@ pub fn parse_input(input: &str) -> Vec { .split(',') .map(|part| part.parse::().unwrap()) .collect::>() -} \ No newline at end of file +} diff --git a/day_11/src/main.rs b/day_11/src/main.rs index 1b29971..ed42aa3 100644 --- a/day_11/src/main.rs +++ b/day_11/src/main.rs @@ -1,11 +1,26 @@ -use ::day_11::{parse_input}; +use ::day_11::{painting_robot::Robot, parse_input}; +use day_09::program::Program; +use std::{sync::mpsc::channel, thread::spawn}; fn main() { - let input = parse_input(&include_str!("../../input/day_11")); - println!("{:?}", input); + let (b_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + + let mut program = Program::new(&parse_input(&include_str!("../../input/day_11"))); + let mut robot = Robot::new(a_receiver, a_sender); + + spawn(move || { + program.new_input(b_receiver); + program.new_output(b_sender); + program.run(); + }); + + let part_01_output = spawn(move || robot.run()).join().unwrap(); + println!("part_01, {}", part_01_output); + // let mut robot = Robot::new(&instructions); + // println!("part_01: {:?}", robot.run()); } #[cfg(test)] #[allow(dead_code)] -mod tests { -} +mod tests {} diff --git a/day_11/src/painting_robot.rs b/day_11/src/painting_robot.rs new file mode 100644 index 0000000..65784f7 --- /dev/null +++ b/day_11/src/painting_robot.rs @@ -0,0 +1,80 @@ +use crate::direction::{Dir::*, Direction}; +use crate::point::Point; +use std::{ + collections::HashSet, + sync::mpsc::{Receiver, Sender}, +}; + +pub struct Robot { + position: Point, + direction: Direction, + input: Receiver, + output: Sender, + visited: HashSet, + whites: HashSet, +} + +impl Robot { + pub fn new(receiver: Receiver, sender: Sender) -> Robot { + let position = Point { x: 0, y: 0 }; + let mut visited = HashSet::new(); + let mut whites = HashSet::new(); + + visited.insert(position.clone()); + whites.insert(position.clone()); + + Robot { + input: receiver, + output: sender, + direction: Direction::new(), + position, + visited, + whites, + } + } + + fn move_position(&mut self) { + let x = self.position.x; + let y = self.position.y; + + self.position = match self.direction.0 { + Up => Point { x, y: y + 1 }, + Right => Point { x: x + 1, y }, + Down => Point { x, y: y - 1 }, + Left => Point { x: x - 1, y }, + } + } + + pub fn run(&mut self) -> usize { + loop { + let over_white_panel = self.whites.contains(&self.position); + self.output + .send(if over_white_panel { 1 } else { 0 }) + .unwrap(); + + let next_color = match self.input.recv() { + Ok(0) => 0u8, + Ok(1) => 1u8, + _ => break, + }; + + if next_color == 0 { + self.whites.remove(&self.position); + } else { + self.whites.insert(self.position.clone()); + } + + let next_position = match self.input.recv() { + Ok(0) => 0u8, + Ok(1) => 1u8, + _ => break, + }; + + self.direction.turn(next_position); + self.move_position(); + self.visited.insert(self.position.clone()); + } + + self.visited.len() + } +} diff --git a/day_11/src/point.rs b/day_11/src/point.rs new file mode 100644 index 0000000..8f488ce --- /dev/null +++ b/day_11/src/point.rs @@ -0,0 +1,7 @@ +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct Point { + pub x: i64, + pub y: i64, +} + +impl Point {} From 997e8fa1cf76b5221a1673d8fa7ea1c9f49dd315 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Thu, 12 Dec 2019 19:17:39 +0100 Subject: [PATCH 26/42] feat: added part 1 of day 11 --- day_11/src/main.rs | 67 +++++++++++++++++++++++++++++++----- day_11/src/painting_robot.rs | 10 ++++-- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/day_11/src/main.rs b/day_11/src/main.rs index ed42aa3..6ba9072 100644 --- a/day_11/src/main.rs +++ b/day_11/src/main.rs @@ -2,12 +2,12 @@ use ::day_11::{painting_robot::Robot, parse_input}; use day_09::program::Program; use std::{sync::mpsc::channel, thread::spawn}; -fn main() { +fn part_01(input: &Vec) -> usize { let (b_sender, a_receiver) = channel(); let (a_sender, b_receiver) = channel(); - let mut program = Program::new(&parse_input(&include_str!("../../input/day_11"))); - let mut robot = Robot::new(a_receiver, a_sender); + let mut program = Program::new(input); + let mut robot = Robot::new(a_receiver, a_sender, false); spawn(move || { program.new_input(b_receiver); @@ -15,12 +15,63 @@ fn main() { program.run(); }); - let part_01_output = spawn(move || robot.run()).join().unwrap(); - println!("part_01, {}", part_01_output); - // let mut robot = Robot::new(&instructions); - // println!("part_01: {:?}", robot.run()); + spawn(move || robot.run()).join().unwrap() +} + +fn main() { + let input = parse_input(&include_str!("../../input/day_11")); + println!("part_01: {:?}", part_01(&input)); } #[cfg(test)] #[allow(dead_code)] -mod tests {} +mod tests { + use super::*; + + #[test] + #[ignore] + fn gets_the_same_result_as_part_01() { + let (b_sender, a_receiver) = channel(); + let (a_sender, _b_receiver) = channel(); + + for input in vec![0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, -1] { + b_sender.send(input).unwrap() + } + + let mut robot = Robot::new(a_receiver, a_sender, false); + + let result = spawn(move || robot.run()).join().unwrap(); + + assert_eq!(result, 6); + } + + #[test] + fn it_does_not_count_the_same_spot_twice() { + let (b_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + + let output_thread = spawn(move || { + let mut output = vec![]; + loop { + let new_output = match b_receiver.recv() { + Ok(val) => val, + _ => break, + }; + &output.push(new_output); + } + output.to_owned() + }); + + for input in vec![0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, -1] { + b_sender.send(input).unwrap() + } + + let mut robot = Robot::new(a_receiver, a_sender, false); + + let result = spawn(move || robot.run()).join().unwrap(); + + assert_eq!(output_thread.join().unwrap(), vec![0, 0, 0, 0, 0, 0, 0]); + + assert_eq!(result, 6); + } +} diff --git a/day_11/src/painting_robot.rs b/day_11/src/painting_robot.rs index 65784f7..10f7b0e 100644 --- a/day_11/src/painting_robot.rs +++ b/day_11/src/painting_robot.rs @@ -15,13 +15,16 @@ pub struct Robot { } impl Robot { - pub fn new(receiver: Receiver, sender: Sender) -> Robot { + pub fn new(receiver: Receiver, sender: Sender, start_on_white: bool) -> Robot { let position = Point { x: 0, y: 0 }; let mut visited = HashSet::new(); let mut whites = HashSet::new(); visited.insert(position.clone()); - whites.insert(position.clone()); + + if start_on_white { + whites.insert(position.clone()); + } Robot { input: receiver, @@ -64,6 +67,8 @@ impl Robot { self.whites.insert(self.position.clone()); } + self.visited.insert(self.position.clone()); + let next_position = match self.input.recv() { Ok(0) => 0u8, Ok(1) => 1u8, @@ -72,7 +77,6 @@ impl Robot { self.direction.turn(next_position); self.move_position(); - self.visited.insert(self.position.clone()); } self.visited.len() From d4fb7171bb41799912f2ecd4d537b702f8e9a2be Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Thu, 12 Dec 2019 20:44:31 +0100 Subject: [PATCH 27/42] feat: completed part 2 of day 11 --- README.md | 1 + day_11/src/main.rs | 44 +++++++++++++++++------------- day_11/src/painting_robot.rs | 52 ++++++++++++++++++++++++++++++++++++ day_11/src/point.rs | 34 +++++++++++++++++++++++ 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 2bbc24a..e3f8441 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,4 @@ - [Day 8](https://github.com/ankjevel/adventofcode/tree/2019/day_08) 🌟 🌟 - [Day 9](https://github.com/ankjevel/adventofcode/tree/2019/day_09) 🌟 🌟 - [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 🌟 +- [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟 diff --git a/day_11/src/main.rs b/day_11/src/main.rs index 6ba9072..aaf0f22 100644 --- a/day_11/src/main.rs +++ b/day_11/src/main.rs @@ -18,9 +18,32 @@ fn part_01(input: &Vec) -> usize { spawn(move || robot.run()).join().unwrap() } +fn part_02(input: &Vec) { + let (b_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + + let mut program = Program::new(input); + + spawn(move || { + program.new_input(b_receiver); + program.new_output(b_sender); + program.run(); + }); + + spawn(move || { + let mut robot = Robot::new(a_receiver, a_sender, true); + robot.run(); + robot.print() + }) + .join() + .unwrap(); +} + fn main() { let input = parse_input(&include_str!("../../input/day_11")); println!("part_01: {:?}", part_01(&input)); + println!("part_02:"); + part_02(&input); } #[cfg(test)] @@ -29,7 +52,6 @@ mod tests { use super::*; #[test] - #[ignore] fn gets_the_same_result_as_part_01() { let (b_sender, a_receiver) = channel(); let (a_sender, _b_receiver) = channel(); @@ -48,21 +70,9 @@ mod tests { #[test] fn it_does_not_count_the_same_spot_twice() { let (b_sender, a_receiver) = channel(); - let (a_sender, b_receiver) = channel(); - - let output_thread = spawn(move || { - let mut output = vec![]; - loop { - let new_output = match b_receiver.recv() { - Ok(val) => val, - _ => break, - }; - &output.push(new_output); - } - output.to_owned() - }); + let (a_sender, _b_receiver) = channel(); - for input in vec![0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, -1] { + for input in vec![1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1] { b_sender.send(input).unwrap() } @@ -70,8 +80,6 @@ mod tests { let result = spawn(move || robot.run()).join().unwrap(); - assert_eq!(output_thread.join().unwrap(), vec![0, 0, 0, 0, 0, 0, 0]); - - assert_eq!(result, 6); + assert_eq!(result, 4); } } diff --git a/day_11/src/painting_robot.rs b/day_11/src/painting_robot.rs index 10f7b0e..79b428d 100644 --- a/day_11/src/painting_robot.rs +++ b/day_11/src/painting_robot.rs @@ -5,6 +5,22 @@ use std::{ sync::mpsc::{Receiver, Sender}, }; +fn get_min_y(a: &Point, b: &Point) -> i64 { + if a.y < b.y { + a.y.clone() + } else { + b.y.clone() + } +} + +fn get_min_x(a: &Point, b: &Point) -> i64 { + if a.x < b.x { + a.x.clone() + } else { + b.x.clone() + } +} + pub struct Robot { position: Point, direction: Direction, @@ -48,6 +64,42 @@ impl Robot { } } + pub fn print(&mut self) { + let mut output = self.whites.clone().into_iter().collect::>(); + + output.sort(); + + let mut iter = output.clone().into_iter(); + let mut width = iter + .clone() + .fold(0, |sum, point| if point.x > sum { point.x } else { sum }); + let top_left = iter.next().unwrap(); + let bottom_right = iter.last().unwrap(); + let min_x = get_min_x(&top_left, &bottom_right); + let min_y = get_min_y(&top_left, &bottom_right); + width = width - min_x; + let height = if top_left.y > bottom_right.y { + top_left.y - bottom_right.y + } else { + bottom_right.y - top_left.y + }; + + let mut grid = vec![vec![' '; (width + 1) as usize]; (height + 1) as usize]; + + for item in output { + let y = (item.y - min_y) as usize; + let x = (item.x - min_x) as usize; + if let Some(elem) = grid.get_mut(y) { + elem.insert(x, '#'); + } + } + + println!("\n"); + for row in grid.into_iter().rev() { + println!("{}", row.into_iter().collect::()) + } + } + pub fn run(&mut self) -> usize { loop { let over_white_panel = self.whites.contains(&self.position); diff --git a/day_11/src/point.rs b/day_11/src/point.rs index 8f488ce..e7d69a4 100644 --- a/day_11/src/point.rs +++ b/day_11/src/point.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering::{self, Equal, Greater, Less}; + #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] pub struct Point { pub x: i64, @@ -5,3 +7,35 @@ pub struct Point { } impl Point {} + +impl Ord for Point { + fn cmp(&self, other: &Point) -> Ordering { + if self.y == other.y { + if self.x < other.x { + Less + } else if self.x > other.x { + Greater + } else { + Equal + } + } else if self.y < other.y { + Less + } else if self.y > other.y { + Greater + } else { + if self.x < other.x { + Less + } else if self.x > other.x { + Greater + } else { + Equal + } + } + } +} + +impl PartialOrd for Point { + fn partial_cmp(&self, other: &Point) -> Option { + Some(self.cmp(other)) + } +} From 2ae1afeb9a42d4cf580474e5bc525baafb9b94ae Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 13 Dec 2019 11:01:24 +0100 Subject: [PATCH 28/42] feat: completed day 12 --- README.md | 1 + day_12/Cargo.toml | 10 ++++ day_12/src/lib.rs | 88 +++++++++++++++++++++++++++++ day_12/src/main.rs | 135 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 234 insertions(+) create mode 100644 day_12/Cargo.toml create mode 100644 day_12/src/lib.rs create mode 100644 day_12/src/main.rs diff --git a/README.md b/README.md index e3f8441..216961f 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,4 @@ - [Day 9](https://github.com/ankjevel/adventofcode/tree/2019/day_09) 🌟 🌟 - [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 🌟 - [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟 +- [Day 12](https://github.com/ankjevel/adventofcode/tree/2019/day_12) 🌟 🌟 diff --git a/day_12/Cargo.toml b/day_12/Cargo.toml new file mode 100644 index 0000000..10e6383 --- /dev/null +++ b/day_12/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day_12" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +num-integer = "0.1.41" diff --git a/day_12/src/lib.rs b/day_12/src/lib.rs new file mode 100644 index 0000000..db6b1fd --- /dev/null +++ b/day_12/src/lib.rs @@ -0,0 +1,88 @@ +extern crate num_integer; + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub struct Moon { + pub position: (i64, i64, i64), + pub velocity: (i64, i64, i64), +} + +impl Moon { + pub fn new(input: Vec) -> Moon { + let mut iter = input.into_iter(); + + let x = iter.next().unwrap(); + let y = iter.next().unwrap(); + let z = iter.next().unwrap(); + + Moon { + position: (x, y, z), + velocity: (0, 0, 0), + } + } + + pub fn total_energy(&self) -> i64 { + let (x, y, z) = self.position; + let (dx, dy, dz) = self.velocity; + + let pot = x.abs() + y.abs() + z.abs(); + let kin = dx.abs() + dy.abs() + dz.abs(); + + pot * kin + } + + pub fn gravity(&self, compared: &Moon) -> (i64, i64, i64) { + let (ax, ay, az) = self.position; + let (bx, by, bz) = compared.position; + + (gravity(ax, bx), gravity(ay, by), gravity(az, bz)) + } +} + +pub fn gravity(a: i64, b: i64) -> i64 { + if a > b { + -1 + } else if b > a { + 1 + } else { + 0 + } +} + +pub fn new_moon(moon: &Moon, energy: &(i64, i64, i64)) -> Moon { + let (ddx, ddy, ddz) = energy; + + let (dx, dy, dz) = moon.velocity; + let (dx, dy, dz) = (dx + ddx, dy + ddy, dz + ddz); + + let (x, y, z) = moon.position; + let (x, y, z) = (x + dx, y + dy, z + dz); + + Moon { + position: (x, y, z), + velocity: (dx, dy, dz), + } +} + +pub fn parse_input(input: &str) -> Vec { + input + .lines() + .map(str::trim) + .filter(|string| !string.is_empty()) + .map(|part| { + part.split(',') + .map(str::trim) + .map(str::to_owned) + .map(|s| { + s.replace('>', "") + .replace('<', "") + .split('=') + .last() + .unwrap() + .parse::() + .unwrap() + }) + .collect() + }) + .map(Moon::new) + .collect() +} diff --git a/day_12/src/main.rs b/day_12/src/main.rs new file mode 100644 index 0000000..7a0afab --- /dev/null +++ b/day_12/src/main.rs @@ -0,0 +1,135 @@ +use ::day_12::{gravity, new_moon, parse_input, Moon}; +use num_integer::lcm; +use std::mem::replace; + +fn part_01(input: &Vec, steps: usize) -> i64 { + let mut moons = input.clone(); + let mut new_moons = vec![]; + for _ in 0..steps { + for (i, moon) in moons.iter().enumerate() { + let mut ddx = 0; + let mut ddy = 0; + let mut ddz = 0; + for (j, other) in moons.iter().enumerate() { + if i == j { + continue; + } + let (x, y, z) = moon.gravity(&other); + ddx += x; + ddy += y; + ddz += z; + } + new_moons.push(new_moon(&moon, &(ddx, ddy, ddz))) + } + moons = replace(&mut new_moons, vec![]); + } + moons.iter().map(Moon::total_energy).sum() +} + +type SimplifiedMoon = (i64, i64); + +fn part_02(input: &Vec) -> u128 { + let to_id = |input: &SimplifiedMoon| -> String { + "pos=".to_string() + &input.0.to_string() + &",vel=" + &input.1.to_string() + }; + + let to_hash = |input: Vec| -> String { + input.iter().map(to_id).collect::>().join("|") + }; + + let run_simulation = |input: Vec| -> u128 { + let mut moons = input.clone(); + let mut new_moons = vec![]; + let mut steps = 0; + + let initial_state = to_hash(input.clone()); + + 'outer: loop { + steps += 1; + + for (i, moon) in moons.iter().enumerate() { + let mut energy = 0; + for (j, other) in moons.iter().enumerate() { + if i == j { + continue; + } + energy += gravity(moon.0, other.0); + } + let (position, velocity) = moon; + let velocity = velocity + energy; + let position = position + velocity; + new_moons.push((position.to_owned(), velocity.to_owned())) + } + + if to_hash(new_moons.clone()) == initial_state { + break 'outer; + }; + + moons = replace(&mut new_moons, vec![]); + } + + steps + }; + + let x = run_simulation( + input + .clone() + .iter() + .map(|moon| (moon.position.0, 0)) + .collect(), + ); + let y = run_simulation( + input + .clone() + .iter() + .map(|moon| (moon.position.1, 0)) + .collect(), + ); + let z = run_simulation( + input + .clone() + .iter() + .map(|moon| (moon.position.2, 0)) + .collect(), + ); + + lcm(lcm(x, y), z) +} + +fn main() { + let input = parse_input(&include_str!("../../input/day_12")); + println!("part_01: {}", part_01(&input, 1_000)); + println!("part_02: {}", part_02(&input)); +} + +#[cfg(test)] +#[allow(dead_code)] +mod tests { + use super::*; + + const EXAMPLE_DATA_01: &'static str = " + + + + + "; + + const EXAMPLE_DATA_02: &'static str = " + + + + + "; + + #[test] + fn it_gets_the_examples_on_part_01_right() { + assert_eq!(part_01(&parse_input(&EXAMPLE_DATA_01), 10), 179); + assert_eq!(part_01(&parse_input(&EXAMPLE_DATA_02), 100), 1940); + } + + #[test] + fn it_gets_the_examples_on_part_02_right() { + assert_eq!(part_02(&parse_input(&EXAMPLE_DATA_01)), 2772); + assert_eq!(part_02(&parse_input(&EXAMPLE_DATA_02)), 4686774924); + } +} From 6a4bb4be2185f96eeceb03556b3b757cf0a47e6e Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 13 Dec 2019 11:36:38 +0100 Subject: [PATCH 29/42] feat: scaffolding for day 13 --- day_13/Cargo.toml | 10 ++++++++++ day_13/src/lib.rs | 41 +++++++++++++++++++++++++++++++++++++++++ day_13/src/main.rs | 24 ++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 day_13/Cargo.toml create mode 100644 day_13/src/lib.rs create mode 100644 day_13/src/main.rs diff --git a/day_13/Cargo.toml b/day_13/Cargo.toml new file mode 100644 index 0000000..606e25d --- /dev/null +++ b/day_13/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day_13" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +day_09 = { path = "../day_09" } diff --git a/day_13/src/lib.rs b/day_13/src/lib.rs new file mode 100644 index 0000000..c30bb2d --- /dev/null +++ b/day_13/src/lib.rs @@ -0,0 +1,41 @@ +extern crate day_09; + +use day_09::program::Program; +use std::{sync::mpsc::channel, thread::spawn}; + +pub fn parse_input(input: &str) -> Vec { + input + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .next() + .unwrap() + .split(',') + .map(|part| part.parse::().unwrap()) + .collect::>() +} + +pub fn get_instructions(input: &Vec) -> Vec { + let (b_sender, a_receiver) = channel(); + let (_a_sender, b_receiver) = channel(); + + let instructions = spawn(move || { + let mut output = Vec::new(); + loop { + match a_receiver.recv() { + Ok(instruction) => output.push(instruction), + _ => break, + } + } + output + }); + + let mut program = Program::new(input); + spawn(move || { + program.new_input(b_receiver); + program.new_output(b_sender); + program.run(); + }); + + instructions.join().unwrap() +} diff --git a/day_13/src/main.rs b/day_13/src/main.rs new file mode 100644 index 0000000..8444b47 --- /dev/null +++ b/day_13/src/main.rs @@ -0,0 +1,24 @@ +use ::day_13::{get_instructions, parse_input}; + +fn part_01(input: &Vec) { + let instructions = get_instructions(input); + + let chunked: Vec<(i64, i64, i64)> = instructions + .chunks(3) + .into_iter() + .map(|instructions| { + let mut iter = instructions.into_iter(); + let x = iter.next().unwrap(); + let y = iter.next().unwrap(); + let id = iter.next().unwrap(); + (x.to_owned(), y.to_owned(), id.to_owned()) + }) + .collect::>(); + + println!("chunked: {:?}", chunked); +} + +fn main() { + let input = parse_input(&include_str!("../../input/day_13")); + part_01(&input); +} From 4a482eb328ef13ebec643f3ef2bec3f23e9125a7 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 13 Dec 2019 12:06:43 +0100 Subject: [PATCH 30/42] feat: completed part 1 --- README.md | 1 + day_13/src/main.rs | 87 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 216961f..ad29709 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,4 @@ - [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 🌟 - [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟 - [Day 12](https://github.com/ankjevel/adventofcode/tree/2019/day_12) 🌟 🌟 +- [Day 13](https://github.com/ankjevel/adventofcode/tree/2019/day_13) 🌟 diff --git a/day_13/src/main.rs b/day_13/src/main.rs index 8444b47..8efa402 100644 --- a/day_13/src/main.rs +++ b/day_13/src/main.rs @@ -1,9 +1,82 @@ use ::day_13::{get_instructions, parse_input}; -fn part_01(input: &Vec) { +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +enum Tile { + Empty, + Wall, + Block, + HorizontalPaddle, + Ball, +} + +use Tile::*; + +impl Tile { + pub fn from(input: &i64) -> Tile { + match input { + 0 => Empty, + 1 => Wall, + 2 => Block, + 3 => HorizontalPaddle, + 4 => Ball, + _ => panic!("enum not defined {}", input), + } + } +} + +fn print(input: &Vec) { + let instructions = get_instructions(input); + + let chunked: Vec<(usize, usize, Tile)> = instructions + .chunks(3) + .into_iter() + .map(|instructions| { + let mut iter = instructions.into_iter(); + let x = iter.next().unwrap(); + let y = iter.next().unwrap(); + let id = iter.next().unwrap(); + (x.to_owned() as usize, y.to_owned() as usize, Tile::from(id)) + }) + .collect::>(); + + let max_x = &chunked + .iter() + .fold(0, |prev, curr| if prev < curr.0 { curr.0 } else { prev }); + + let max_y = &chunked + .iter() + .fold(0, |prev, curr| if prev < curr.1 { curr.1 } else { prev }); + + let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize]; + + for (x, y, tile) in chunked { + if tile == Empty { + continue; + } + + if let Some(elem) = grid.get_mut(y) { + elem.insert( + x, + match tile { + Wall => '#', + Block => '◻', + HorizontalPaddle => '=', + Ball => 'o', + _ => ' ', + }, + ); + } + } + + for row in grid.into_iter() { + println!("{}", row.into_iter().collect::()) + } +} + +fn part_01(input: &Vec) -> usize { let instructions = get_instructions(input); - let chunked: Vec<(i64, i64, i64)> = instructions + let chunked: Vec<(usize, usize, Tile)> = instructions .chunks(3) .into_iter() .map(|instructions| { @@ -11,14 +84,18 @@ fn part_01(input: &Vec) { let x = iter.next().unwrap(); let y = iter.next().unwrap(); let id = iter.next().unwrap(); - (x.to_owned(), y.to_owned(), id.to_owned()) + (x.to_owned() as usize, y.to_owned() as usize, Tile::from(id)) }) .collect::>(); - println!("chunked: {:?}", chunked); + chunked.iter().fold( + 0, + |acc, (_x, _y, tile)| if tile == &Block { acc + 1 } else { acc }, + ) } fn main() { let input = parse_input(&include_str!("../../input/day_13")); - part_01(&input); + println!("part_01: {}", part_01(&input)); + print(&input); } From c046dc8b8e7008861d94112a86793b146d3c91b8 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 13 Dec 2019 12:14:26 +0100 Subject: [PATCH 31/42] chore: moved lib-related code to ... lib --- day_13/src/lib.rs | 38 ++++++++++++++++++++++++++ day_13/src/main.rs | 67 +++++----------------------------------------- 2 files changed, 45 insertions(+), 60 deletions(-) diff --git a/day_13/src/lib.rs b/day_13/src/lib.rs index c30bb2d..0cd16f2 100644 --- a/day_13/src/lib.rs +++ b/day_13/src/lib.rs @@ -3,6 +3,30 @@ extern crate day_09; use day_09::program::Program; use std::{sync::mpsc::channel, thread::spawn}; +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Tile { + Empty, + Wall, + Block, + HorizontalPaddle, + Ball, +} + +use Tile::*; + +impl Tile { + pub fn from(input: &i64) -> Tile { + match input { + 0 => Empty, + 1 => Wall, + 2 => Block, + 3 => HorizontalPaddle, + 4 => Ball, + _ => panic!("enum not defined {}", input), + } + } +} + pub fn parse_input(input: &str) -> Vec { input .lines() @@ -39,3 +63,17 @@ pub fn get_instructions(input: &Vec) -> Vec { instructions.join().unwrap() } + +pub fn into_chunks(input: &Vec) -> Vec<(usize, usize, Tile)> { + input + .chunks(3) + .into_iter() + .map(|instructions| { + let mut iter = instructions.into_iter(); + let x = iter.next().unwrap(); + let y = iter.next().unwrap(); + let id = iter.next().unwrap(); + (x.to_owned() as usize, y.to_owned() as usize, Tile::from(id)) + }) + .collect::>() +} diff --git a/day_13/src/main.rs b/day_13/src/main.rs index 8efa402..fa343dc 100644 --- a/day_13/src/main.rs +++ b/day_13/src/main.rs @@ -1,55 +1,15 @@ -use ::day_13::{get_instructions, parse_input}; - -#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] -enum Tile { - Empty, - Wall, - Block, - HorizontalPaddle, - Ball, -} - -use Tile::*; - -impl Tile { - pub fn from(input: &i64) -> Tile { - match input { - 0 => Empty, - 1 => Wall, - 2 => Block, - 3 => HorizontalPaddle, - 4 => Ball, - _ => panic!("enum not defined {}", input), - } - } -} +use ::day_13::{get_instructions, into_chunks, parse_input, Tile::*}; fn print(input: &Vec) { - let instructions = get_instructions(input); - - let chunked: Vec<(usize, usize, Tile)> = instructions - .chunks(3) - .into_iter() - .map(|instructions| { - let mut iter = instructions.into_iter(); - let x = iter.next().unwrap(); - let y = iter.next().unwrap(); - let id = iter.next().unwrap(); - (x.to_owned() as usize, y.to_owned() as usize, Tile::from(id)) - }) - .collect::>(); - - let max_x = &chunked + let instructions = into_chunks(&get_instructions(input)); + let max_x = &instructions .iter() .fold(0, |prev, curr| if prev < curr.0 { curr.0 } else { prev }); - - let max_y = &chunked + let max_y = &instructions .iter() .fold(0, |prev, curr| if prev < curr.1 { curr.1 } else { prev }); - let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize]; - - for (x, y, tile) in chunked { + for (x, y, tile) in instructions { if tile == Empty { continue; } @@ -74,21 +34,8 @@ fn print(input: &Vec) { } fn part_01(input: &Vec) -> usize { - let instructions = get_instructions(input); - - let chunked: Vec<(usize, usize, Tile)> = instructions - .chunks(3) - .into_iter() - .map(|instructions| { - let mut iter = instructions.into_iter(); - let x = iter.next().unwrap(); - let y = iter.next().unwrap(); - let id = iter.next().unwrap(); - (x.to_owned() as usize, y.to_owned() as usize, Tile::from(id)) - }) - .collect::>(); - - chunked.iter().fold( + let instructions = into_chunks(&get_instructions(input)); + instructions.iter().fold( 0, |acc, (_x, _y, tile)| if tile == &Block { acc + 1 } else { acc }, ) From e44b6addbb4dd92a4d989ce2b8ed91114f2e726e Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 13 Dec 2019 20:58:43 +0100 Subject: [PATCH 32/42] feat: completed day 13 --- day_13/Cargo.toml | 1 + day_13/src/game.rs | 203 +++++++++++++++++++++++++++++++++++++++++++++ day_13/src/lib.rs | 9 +- day_13/src/main.rs | 62 ++++++-------- 4 files changed, 238 insertions(+), 37 deletions(-) create mode 100644 day_13/src/game.rs diff --git a/day_13/Cargo.toml b/day_13/Cargo.toml index 606e25d..b5654d6 100644 --- a/day_13/Cargo.toml +++ b/day_13/Cargo.toml @@ -8,3 +8,4 @@ edition = "2018" [dependencies] day_09 = { path = "../day_09" } +termion = "1.5.4" diff --git a/day_13/src/game.rs b/day_13/src/game.rs new file mode 100644 index 0000000..ef83c77 --- /dev/null +++ b/day_13/src/game.rs @@ -0,0 +1,203 @@ +use crate::Tile::{self, *}; +use std::{ + collections::HashMap, + sync::mpsc::{Receiver, Sender}, + time::Duration, +}; +use termion::{clear::All, cursor::Restore}; + +fn to_tuple(input: &[i64]) -> (i64, i64, i64) { + let mut iter = input.into_iter(); + let x = iter.next().unwrap(); + let y = iter.next().unwrap(); + let item = iter.next().unwrap(); + + (x.to_owned(), y.to_owned(), item.to_owned()) +} + +fn parse_instructions(input: &Vec) -> (Vec<(usize, usize, Tile)>, Option) { + let mut score = None; + + let instructions = input + .clone() + .chunks(3) + .into_iter() + .filter(|instruction| { + let (x, y, id) = to_tuple(instruction); + let new_score = x == -1 && y == 0; + if new_score { + score = Some(id.clone() as u32); + } + !new_score + }) + .map(|instruction| { + let (x, y, id) = to_tuple(instruction); + let tile = Tile::from(&id); + + (x as usize, y as usize, tile) + }) + .collect::>(); + + (instructions, score) +} + +pub struct Game { + input: Receiver, + output: Sender, + instructions: Vec<(usize, usize, Tile)>, + grid: HashMap<(usize, usize), Tile>, + score: u32, + iterations: u32, +} + +impl Game { + pub fn new(receiver: Receiver, sender: Sender) -> Game { + Game { + input: receiver, + output: sender, + score: 0, + iterations: 0, + grid: HashMap::new(), + instructions: vec![], + } + } + + fn print(&mut self) { + let instructions = self.instructions.clone(); + let max_x = instructions + .iter() + .fold(0, |prev, curr| if prev < curr.0 { curr.0 } else { prev }); + let max_y = instructions + .iter() + .fold(0, |prev, curr| if prev < curr.1 { curr.1 } else { prev }); + let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize]; + + for x in 0..=max_x { + if let Some(elem) = grid.get_mut(0) { + elem[x] = '#'; + } + } + + for (x, y, tile) in self.instructions.clone() { + if tile == Empty { + continue; + } + + if let Some(elem) = grid.get_mut(y) { + elem[x] = match tile { + Wall => '#', + Block => '◻', + HorizontalPaddle => '=', + Ball => 'o', + _ => ' ', + }; + } + } + + print!("{}{}", All, Restore); + println!("score: {}, iterations: {}", self.score, self.iterations); + for row in grid { + println!("{}", row.clone().iter().collect::()); + } + } + + fn add_initial_data(&mut self, input: Vec) { + let (instructions, score) = parse_instructions(&input); + + if let Some(score) = score { + self.score = score + }; + + for (x, y, item) in instructions.clone() { + let grid = self.grid.entry((x, y)).or_insert(Empty); + *grid = item; + } + + self.instructions = instructions.clone(); + } + + fn update_data(&mut self, input: Vec) { + let (instructions, score) = parse_instructions(&input); + + if let Some(score) = score { + self.score = score + }; + + for (x, y, item) in instructions.clone() { + let grid = self.grid.entry((x, y)).or_insert(Empty); + *grid = item; + } + + let mut instructions = vec![]; + for ((x, y), item) in self.grid.clone().iter() { + instructions.push((x.to_owned(), y.to_owned(), item.to_owned())); + } + + self.instructions.clear(); + self.instructions = instructions; + } + + fn get_paddle_position(&mut self) -> i64 { + let instructions = self.instructions.clone(); + let paddle = HorizontalPaddle; + let paddle = instructions + .iter() + .fold(0, |acc, curr| if curr.2 == paddle { curr.0 } else { acc }); + + let ball = instructions + .iter() + .fold(0, |acc, curr| if curr.2 == Ball { curr.0 } else { acc }); + + if paddle > ball { + -1 + } else if paddle < ball { + 1 + } else { + 0 + } + } + + pub fn blocks_left(&mut self) -> i64 { + self.instructions.iter().fold( + 0, + |acc, (_x, _y, tile)| if tile == &Block { acc + 1 } else { acc }, + ) + } + + pub fn run(&mut self) -> u32 { + let mut first_run = true; + 'main_loop: loop { + let mut current_input = vec![]; + 'collect_loop: loop { + let curr = match self.input.recv_timeout(Duration::from_millis(25)) { + Ok(x) => x, + _ => break 'collect_loop, + }; + + current_input.push(curr.clone()); + } + + if first_run { + self.add_initial_data(current_input.clone()); + first_run = false; + } else { + self.update_data(current_input.clone()); + } + + self.print(); + + if self.blocks_left() <= 0 { + break; + } + + let position = self.get_paddle_position(); + match self.output.send(position) { + _ => {} + }; + + self.iterations += 1; + } + + self.score.to_owned() + } +} diff --git a/day_13/src/lib.rs b/day_13/src/lib.rs index 0cd16f2..bd46ba7 100644 --- a/day_13/src/lib.rs +++ b/day_13/src/lib.rs @@ -1,4 +1,7 @@ extern crate day_09; +extern crate termion; + +pub mod game; use day_09::program::Program; use std::{sync::mpsc::channel, thread::spawn}; @@ -73,7 +76,11 @@ pub fn into_chunks(input: &Vec) -> Vec<(usize, usize, Tile)> { let x = iter.next().unwrap(); let y = iter.next().unwrap(); let id = iter.next().unwrap(); - (x.to_owned() as usize, y.to_owned() as usize, Tile::from(id)) + ( + x.to_owned() as usize, + y.to_owned() as usize, + Tile::from(&id), + ) }) .collect::>() } diff --git a/day_13/src/main.rs b/day_13/src/main.rs index fa343dc..03833da 100644 --- a/day_13/src/main.rs +++ b/day_13/src/main.rs @@ -1,37 +1,6 @@ -use ::day_13::{get_instructions, into_chunks, parse_input, Tile::*}; - -fn print(input: &Vec) { - let instructions = into_chunks(&get_instructions(input)); - let max_x = &instructions - .iter() - .fold(0, |prev, curr| if prev < curr.0 { curr.0 } else { prev }); - let max_y = &instructions - .iter() - .fold(0, |prev, curr| if prev < curr.1 { curr.1 } else { prev }); - let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize]; - for (x, y, tile) in instructions { - if tile == Empty { - continue; - } - - if let Some(elem) = grid.get_mut(y) { - elem.insert( - x, - match tile { - Wall => '#', - Block => '◻', - HorizontalPaddle => '=', - Ball => 'o', - _ => ' ', - }, - ); - } - } - - for row in grid.into_iter() { - println!("{}", row.into_iter().collect::()) - } -} +use ::day_13::{game::Game, get_instructions, into_chunks, parse_input, Tile::*}; +use day_09::program::Program; +use std::{sync::mpsc::channel, thread::spawn}; fn part_01(input: &Vec) -> usize { let instructions = into_chunks(&get_instructions(input)); @@ -41,8 +10,29 @@ fn part_01(input: &Vec) -> usize { ) } +fn part_02(input: &Vec) -> u32 { + let mut code = input.clone(); + code[0] = 2; + + let (b_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + + let mut program = Program::new(&code); + + program.new_input(b_receiver); + program.new_output(b_sender); + + spawn(move || program.run()); + spawn(move || Game::new(a_receiver, a_sender).run()) + .join() + .unwrap() +} + fn main() { let input = parse_input(&include_str!("../../input/day_13")); - println!("part_01: {}", part_01(&input)); - print(&input); + let part_01_output = part_01(&input); + let part_02_output = part_02(&input); + + println!("part_01: {}", part_01_output); + println!("part_02: {}", part_02_output) } From 5129ab52a7a9cff7b0a8c08796d3edf4a7f98911 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 13 Dec 2019 21:14:13 +0100 Subject: [PATCH 33/42] chore: added the missing star! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad29709..82c3a23 100644 --- a/README.md +++ b/README.md @@ -15,4 +15,4 @@ - [Day 10](https://github.com/ankjevel/adventofcode/tree/2019/day_10) 🌟 🌟 - [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟 - [Day 12](https://github.com/ankjevel/adventofcode/tree/2019/day_12) 🌟 🌟 -- [Day 13](https://github.com/ankjevel/adventofcode/tree/2019/day_13) 🌟 +- [Day 13](https://github.com/ankjevel/adventofcode/tree/2019/day_13) 🌟 🌟 From 21e1676f5cfa06ebdf997796bcfaf5b4adb8b75f Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sat, 14 Dec 2019 15:39:10 +0100 Subject: [PATCH 34/42] feat: scaffolding for day 14 --- day_14/Cargo.toml | 9 +++ day_14/src/lib.rs | 31 ++++++++++ day_14/src/main.rs | 140 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 day_14/Cargo.toml create mode 100644 day_14/src/lib.rs create mode 100644 day_14/src/main.rs diff --git a/day_14/Cargo.toml b/day_14/Cargo.toml new file mode 100644 index 0000000..07f90d3 --- /dev/null +++ b/day_14/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day_14" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day_14/src/lib.rs b/day_14/src/lib.rs new file mode 100644 index 0000000..7500880 --- /dev/null +++ b/day_14/src/lib.rs @@ -0,0 +1,31 @@ +pub type Item = (String, u8); + +fn split(input: String) -> Item { + let mut iter = input.split(" ").map(str::trim).map(str::to_owned); + let quantity = iter.next().unwrap(); + let chemical = iter.next().unwrap(); + (chemical.to_owned(), quantity.parse().unwrap()) +} + +pub fn parse_input(input: &str) -> Vec<(Item, Vec)> { + input + .lines() + .map(str::trim) + .filter(|string| !string.is_empty()) + .map(|part| { + let mut iter = part.split("=>").map(str::trim); + + let input_chemicals = iter.next().unwrap(); + let output_chemical = split(iter.next().unwrap().to_owned()); + + let input_chemicals = input_chemicals + .split(", ") + .map(str::trim) + .map(str::to_owned) + .map(split) + .collect(); + + (output_chemical, input_chemicals) + }) + .collect() +} diff --git a/day_14/src/main.rs b/day_14/src/main.rs new file mode 100644 index 0000000..3e1cbb5 --- /dev/null +++ b/day_14/src/main.rs @@ -0,0 +1,140 @@ +use ::day_14::{parse_input, Item}; +use std::collections::{HashMap, LinkedList}; + +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +struct Output { + pub quantity: u8, + pub required: Vec, +} + +fn to_map(input: &Vec<(Item, Vec)>) -> HashMap { + let mut map = HashMap::new(); + + for (key, value) in input { + map.insert( + key.0.to_owned(), + Output { + quantity: key.1, + required: value.to_owned(), + }, + ); + } + + map +} + +fn get_requirements(map: &HashMap) -> Vec> { + let fuel = &map.get("FUEL").unwrap(); + let mut paths = vec![]; + for item in &fuel.required { + let mut req = LinkedList::new(); + req.push_front((item.clone(), vec![item.0.to_owned()])); + while req.len() > 0 { + if let Some(((key, _value), tree)) = req.pop_back() { + match map.get(&key) { + Some(item) => { + for required in &item.required { + let mut tree = tree.clone(); + if !tree.contains(&key) { + tree.insert(0, key.to_owned()); + } + if !tree.contains(&required.0) { + tree.insert(0, required.0.to_owned()); + } + req.push_back((required.clone(), tree.to_owned())); + } + } + None => paths.push(tree.clone()), + }; + }; + } + } + + paths +} + +fn part_01(input: &Vec<(Item, Vec)>) -> u32 { + let map = to_map(input); + let requirements = get_requirements(&map); + + for req in requirements { + println!("{:?}", req); + } + 0 +} + +fn main() { + let input = parse_input(include_str!("../../input/day_14")); + println!("part_01: {}", part_01(&input)); +} + +#[cfg(test)] +#[allow(dead_code, unused_imports)] +mod tests { + use super::*; + + const EXAMPLE_01: &'static str = " + 9 ORE => 2 A + 8 ORE => 3 B + 7 ORE => 5 C + 3 A, 4 B => 1 AB + 5 B, 7 C => 1 BC + 4 C, 1 A => 1 CA + 2 AB, 3 BC, 4 CA => 1 FUEL + "; + + const EXAMPLE_02: &'static str = " + 157 ORE => 5 NZVS + 165 ORE => 6 DCFZ + 44 XJWVT, 5 KHKGT, 1 QDVJ, 29 NZVS, 9 GPVTF, 48 HKGWZ => 1 FUEL + 12 HKGWZ, 1 GPVTF, 8 PSHF => 9 QDVJ + 179 ORE => 7 PSHF + 177 ORE => 5 HKGWZ + 7 DCFZ, 7 PSHF => 2 XJWVT + 165 ORE => 2 GPVTF + 3 DCFZ, 7 NZVS, 5 HKGWZ, 10 PSHF => 8 KHKGT + "; + + const EXAMPLE_03: &'static str = " + 2 VPVL, 7 FWMGM, 2 CXFTF, 11 MNCFX => 1 STKFG + 17 NVRVD, 3 JNWZP => 8 VPVL + 53 STKFG, 6 MNCFX, 46 VJHF, 81 HVMC, 68 CXFTF, 25 GNMV => 1 FUEL + 22 VJHF, 37 MNCFX => 5 FWMGM + 139 ORE => 4 NVRVD + 144 ORE => 7 JNWZP + 5 MNCFX, 7 RFSQX, 2 FWMGM, 2 VPVL, 19 CXFTF => 3 HVMC + 5 VJHF, 7 MNCFX, 9 VPVL, 37 CXFTF => 6 GNMV + 145 ORE => 6 MNCFX + 1 NVRVD => 8 CXFTF + 1 VJHF, 6 MNCFX => 4 RFSQX + 176 ORE => 6 VJHF + "; + + const EXAMPLE_04: &'static str = " + 171 ORE => 8 CNZTR + 7 ZLQW, 3 BMBT, 9 XCVML, 26 XMNCP, 1 WPTQ, 2 MZWV, 1 RJRHP => 4 PLWSL + 114 ORE => 4 BHXH + 14 VRPVC => 6 BMBT + 6 BHXH, 18 KTJDG, 12 WPTQ, 7 PLWSL, 31 FHTLT, 37 ZDVW => 1 FUEL + 6 WPTQ, 2 BMBT, 8 ZLQW, 18 KTJDG, 1 XMNCP, 6 MZWV, 1 RJRHP => 6 FHTLT + 15 XDBXC, 2 LTCX, 1 VRPVC => 6 ZLQW + 13 WPTQ, 10 LTCX, 3 RJRHP, 14 XMNCP, 2 MZWV, 1 ZLQW => 1 ZDVW + 5 BMBT => 4 WPTQ + 189 ORE => 9 KTJDG + 1 MZWV, 17 XDBXC, 3 XCVML => 2 XMNCP + 12 VRPVC, 27 CNZTR => 2 XDBXC + 15 KTJDG, 12 BHXH => 5 XCVML + 3 BHXH, 2 VRPVC => 7 MZWV + 121 ORE => 7 VRPVC + 7 XCVML => 6 RJRHP + 5 BHXH, 4 VRPVC => 5 LTCX + "; + + #[test] + fn it_gets_same_same_results_as_the_first_examples() { + assert_eq!(part_01(&parse_input(&EXAMPLE_01)), 165); + assert_eq!(part_01(&parse_input(&EXAMPLE_02)), 13312); + assert_eq!(part_01(&parse_input(&EXAMPLE_03)), 180697); + assert_eq!(part_01(&parse_input(&EXAMPLE_04)), 2210736); + } +} From df4c97cb7881afb204329e11b39d1939bc1ede61 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sun, 15 Dec 2019 22:52:25 +0100 Subject: [PATCH 35/42] feat: completed day 14 --- day_14/src/lib.rs | 22 ++++++++- day_14/src/main.rs | 109 ++++++++++++++++++++++++--------------------- 2 files changed, 78 insertions(+), 53 deletions(-) diff --git a/day_14/src/lib.rs b/day_14/src/lib.rs index 7500880..392f1bc 100644 --- a/day_14/src/lib.rs +++ b/day_14/src/lib.rs @@ -1,4 +1,6 @@ -pub type Item = (String, u8); +use std::collections::HashMap; + +pub type Item = (String, i64); fn split(input: String) -> Item { let mut iter = input.split(" ").map(str::trim).map(str::to_owned); @@ -29,3 +31,21 @@ pub fn parse_input(input: &str) -> Vec<(Item, Vec)> { }) .collect() } + +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +pub struct Output { + pub quantity: i64, + pub required: Vec, +} + +pub fn to_map(input: &Vec<(Item, Vec)>) -> HashMap { + let mut map = HashMap::new(); + + for (key, value) in input { + let (key, quantity) = (key.0.to_owned(), key.1.to_owned()); + let required = value.clone(); + map.insert(key, Output { quantity, required }); + } + + map +} diff --git a/day_14/src/main.rs b/day_14/src/main.rs index 3e1cbb5..429fd6b 100644 --- a/day_14/src/main.rs +++ b/day_14/src/main.rs @@ -1,71 +1,69 @@ -use ::day_14::{parse_input, Item}; -use std::collections::{HashMap, LinkedList}; +use ::day_14::{parse_input, to_map, Item, Output}; +use std::{collections::HashMap, mem::replace}; -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -struct Output { - pub quantity: u8, - pub required: Vec, -} +fn get_requirements(reactions: &HashMap, quantity: i64) -> i64 { + let mut reserves: HashMap = HashMap::new(); + let mut required = HashMap::new(); + required.insert("FUEL".to_owned(), quantity.to_owned()); -fn to_map(input: &Vec<(Item, Vec)>) -> HashMap { - let mut map = HashMap::new(); - - for (key, value) in input { - map.insert( - key.0.to_owned(), - Output { - quantity: key.1, - required: value.to_owned(), - }, - ); - } + while required.len() != 1 || !required.contains_key("ORE") { + let mut new_rec = HashMap::new(); - map -} + for (chemical, quantity) in required.clone() { + if chemical == "ORE" { + *new_rec.entry("ORE".to_owned()).or_insert(0) += quantity.to_owned(); + continue; + } + + let quantity = quantity as f64; + let reaction = reactions.get(&chemical).unwrap(); + let reaction_quantity = reaction.quantity.to_owned() as f64; + let reserve_ref = reserves.entry(chemical.to_owned()).or_insert(0); + let reserve = reserve_ref.to_owned() as f64; + let reaction_count = (quantity - reserve) / reaction_quantity; + let reaction_count = reaction_count.ceil() as f64; -fn get_requirements(map: &HashMap) -> Vec> { - let fuel = &map.get("FUEL").unwrap(); - let mut paths = vec![]; - for item in &fuel.required { - let mut req = LinkedList::new(); - req.push_front((item.clone(), vec![item.0.to_owned()])); - while req.len() > 0 { - if let Some(((key, _value), tree)) = req.pop_back() { - match map.get(&key) { - Some(item) => { - for required in &item.required { - let mut tree = tree.clone(); - if !tree.contains(&key) { - tree.insert(0, key.to_owned()); - } - if !tree.contains(&required.0) { - tree.insert(0, required.0.to_owned()); - } - req.push_back((required.clone(), tree.to_owned())); - } - } - None => paths.push(tree.clone()), - }; - }; + for (ingredient, amount) in &reaction.required { + let ingredient_ref = new_rec.entry(ingredient.to_owned()).or_insert(0); + let ingredient_pre = ingredient_ref.to_owned() as f64; + let amount = amount.to_owned() as f64; + + *ingredient_ref = (ingredient_pre + reaction_count * amount) as i64; + } + + *reserve_ref = (reserve + reaction_count * reaction_quantity - quantity).ceil() as i64; } + + required = replace(&mut new_rec, HashMap::new()); } - paths + required.entry("ORE".to_owned()).or_insert(0).to_owned() } -fn part_01(input: &Vec<(Item, Vec)>) -> u32 { - let map = to_map(input); - let requirements = get_requirements(&map); +type Input = Vec<(Item, Vec)>; - for req in requirements { - println!("{:?}", req); +fn part_01(input: &Input) -> i64 { + get_requirements(&to_map(input), 1) +} + +fn part_02(input: &Input) -> i64 { + let map = to_map(input); + let total_ore: i64 = 1_000_000_000_000; + let mut new_estimate = ((total_ore as f64) / (get_requirements(&map, 1) as f64)).floor() as i64; + let mut estimate = 0; + while new_estimate > estimate { + estimate = new_estimate.to_owned(); + let needed = get_requirements(&map, estimate.to_owned()); + new_estimate = ((estimate as f64) * (total_ore as f64) / (needed as f64)).floor() as i64; } - 0 + + estimate } fn main() { let input = parse_input(include_str!("../../input/day_14")); println!("part_01: {}", part_01(&input)); + println!("part_02: {:?}", part_02(&input)); } #[cfg(test)] @@ -137,4 +135,11 @@ mod tests { assert_eq!(part_01(&parse_input(&EXAMPLE_03)), 180697); assert_eq!(part_01(&parse_input(&EXAMPLE_04)), 2210736); } + + #[test] + fn it_gets_same_same_results_as_the_second_part() { + assert_eq!(part_02(&parse_input(&EXAMPLE_02)), 82892753); + assert_eq!(part_02(&parse_input(&EXAMPLE_03)), 5586022); + assert_eq!(part_02(&parse_input(&EXAMPLE_04)), 460664); + } } From 124972eb5237ea83de6994b6a34540a09fd768f2 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 16 Dec 2019 10:59:04 +0100 Subject: [PATCH 36/42] feat: trying to solve part 1 --- day_15/Cargo.toml | 13 ++ day_15/src/enums.rs | 67 +++++++++++ day_15/src/lib.rs | 24 ++++ day_15/src/main.rs | 24 ++++ day_15/src/paths.rs | 125 +++++++++++++++++++ day_15/src/repair_droid.rs | 241 +++++++++++++++++++++++++++++++++++++ 6 files changed, 494 insertions(+) create mode 100644 day_15/Cargo.toml create mode 100644 day_15/src/enums.rs create mode 100644 day_15/src/lib.rs create mode 100644 day_15/src/main.rs create mode 100644 day_15/src/paths.rs create mode 100644 day_15/src/repair_droid.rs diff --git a/day_15/Cargo.toml b/day_15/Cargo.toml new file mode 100644 index 0000000..0a9d216 --- /dev/null +++ b/day_15/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "day_15" +version = "0.1.0" +authors = ["Dennis Pettersson "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +day_09 = { path = "../day_09" } +termion = "1.5.4" +float-cmp = "0.6.0" +rand = "0.7.2" diff --git a/day_15/src/enums.rs b/day_15/src/enums.rs new file mode 100644 index 0000000..52f7e4c --- /dev/null +++ b/day_15/src/enums.rs @@ -0,0 +1,67 @@ +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Direction { + Up = 1, + Down = 2, + Left = 3, + Right = 4, +} + +use Direction::{Down, Left, Right, Up}; + +impl Direction { + pub fn new(input: i64) -> Direction { + println!("input: {:>}", input); + match input { + 1 => Up, + 2 => Down, + 3 => Left, + _ => Right, + } + } + + pub fn dir(input: Direction) -> i64 { + match input { + Up => 1, + Down => 2, + Left => 3, + Right => 4, + } + } + + pub fn turn(self) -> Direction { + match self { + Up => Right, + Right => Down, + Down => Left, + Left => Up, + } + } +} + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Status { + Wall = 0, + Moved = 1, + MovedAndOnOxygen = 2, +} + +use Status::{Moved, MovedAndOnOxygen, Wall}; + +impl Status { + pub fn new(input: i64) -> Status { + match input { + 0 => Wall, + 1 => Moved, + 2 => MovedAndOnOxygen, + _ => panic!("{} not known", input), + } + } +} + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] +pub enum Tile { + Current, + Unknown, + Wall, + Visited, +} diff --git a/day_15/src/lib.rs b/day_15/src/lib.rs new file mode 100644 index 0000000..6537a63 --- /dev/null +++ b/day_15/src/lib.rs @@ -0,0 +1,24 @@ +#[macro_use] +extern crate float_cmp; + +extern crate day_09; +extern crate rand; +extern crate termion; + +pub type Point = (i64, i64); + +pub mod enums; +pub mod paths; +pub mod repair_droid; + +pub fn parse_input(input: &str) -> Vec { + input + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .next() + .unwrap() + .split(',') + .map(|part| part.parse::().unwrap()) + .collect::>() +} diff --git a/day_15/src/main.rs b/day_15/src/main.rs new file mode 100644 index 0000000..94473fa --- /dev/null +++ b/day_15/src/main.rs @@ -0,0 +1,24 @@ +use ::day_15::{parse_input, repair_droid::RepairDroid}; +use day_09::program::Program; +use std::{sync::mpsc::channel, thread::spawn}; + +fn main() { + let input = parse_input(&include_str!("../../input/day_15")); + + println!("{:?}", part_01(&input)); +} + +fn part_01(input: &Vec) { + let (b_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + + let mut program = Program::new(&input); + + program.new_input(b_receiver); + program.new_output(b_sender); + + spawn(move || program.run()); + spawn(move || RepairDroid::new(a_receiver, a_sender).run()) + .join() + .unwrap() +} diff --git a/day_15/src/paths.rs b/day_15/src/paths.rs new file mode 100644 index 0000000..413dbf7 --- /dev/null +++ b/day_15/src/paths.rs @@ -0,0 +1,125 @@ +use crate::enums::Tile; +use crate::Point; +use std::collections::{BinaryHeap, HashMap}; + +fn distance(p1: &Point, p2: &Point) -> f64 { + ((p2.0 as f64 - p1.0 as f64).powf(2f64) + (p2.1 as f64 - p1.1 as f64).powf(2f64)).sqrt() +} + +#[allow(dead_code)] +fn is_between(a: &Point, c: &Point, b: &Point) -> bool { + approx_eq!( + f64, + distance(&a, &c) + distance(&c, &b), + distance(&a, &b), + ulps = 2 + ) +} + +type Map = HashMap; + +pub fn best_match(input: &Map, position: &Point, visited: &Vec) -> Option> { + let available = input + .clone() + .iter() + .filter(|(pos, tile)| { + (tile == &&Tile::Unknown || tile == &&Tile::Visited) && !visited.contains(pos) + }) + .map(|(pos, _tile)| pos.to_owned()) + .collect::>(); + + if available.len() <= 0 { + return None; + } + + let mut steps = vec![]; + + for current in available.clone() { + let path = match find_path(&input, position.to_owned(), current.to_owned()) { + Some(path) => path.to_owned(), + None => continue, + }; + if path.len() > steps.len() { + steps = path.to_owned(); + } + } + + if steps.len() == 0 { + None + } else { + Some(steps.to_owned()) + } +} + +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] +struct State { + cost: isize, + point: Point, +} + +pub fn find_path(map: &Map, start: Point, goal: Point) -> Option> { + let adjacent = |point: &Point| -> Vec { + let mut vec = Vec::new(); + + for (x, y) in vec![(0, 1), (1, 0), (-1, 0), (0, -1)] { + let new_pos = (point.0 + x, point.1 + y); + if let Some(tile) = map.get(&new_pos) { + if tile != &Tile::Wall { + vec.push(new_pos.to_owned()); + } + }; + } + + vec + }; + + let can_move = |point: &Point| -> bool { + match map.get(&point) { + Some(tile) => tile != &Tile::Wall, + None => false, + } + }; + + let mut frontier = BinaryHeap::new(); + frontier.push(State { + cost: 0, + point: start, + }); + + let mut came_from = HashMap::new(); + came_from.insert(start, None); + + while frontier.len() != 0 { + let current = frontier.pop(); + if current.unwrap().point == goal { + break; + } + for next_point in adjacent(¤t.unwrap().point) { + if !came_from.contains_key(&next_point) && can_move(&next_point) { + frontier.push(State { + point: next_point, + cost: distance(&goal, &next_point) as isize, + }); + came_from.insert(next_point, current.map(|a| a.point)); + } + } + } + + let mut current = goal; + let mut path = vec![current]; + + while current != start { + if let Some(c) = came_from.get(¤t) { + if let Some(c) = *c { + current = c; + path.push(current); + } else { + return None; + } + } else { + return None; + } + } + + Some(path) +} diff --git a/day_15/src/repair_droid.rs b/day_15/src/repair_droid.rs new file mode 100644 index 0000000..151eeb4 --- /dev/null +++ b/day_15/src/repair_droid.rs @@ -0,0 +1,241 @@ +use crate::enums::{ + Direction::{self, Down, Left, Right, Up}, + Status::{self, MovedAndOnOxygen, Wall}, + Tile, +}; +use crate::paths; +use rand::{ + self, + distributions::{Distribution, Uniform}, +}; +use std::{ + collections::HashMap, + sync::mpsc::{Receiver, Sender}, + thread::sleep, + time::Duration, +}; +use termion::{clear::All, cursor::Restore}; + +type Point = (i64, i64); + +pub struct RepairDroid { + input: Receiver, + output: Sender, + grid: HashMap, + position: Point, + direction: Direction, + iterations: u64, + steps: Vec, + visited: Vec, +} + +impl RepairDroid { + pub fn new(receiver: Receiver, sender: Sender) -> RepairDroid { + let mut grid = HashMap::new(); + grid.insert((0, 0), Tile::Current); + + vec![(0, 1), (1, 0), (-1, 0), (0, -1)] + .iter() + .for_each(|pos| { + grid.insert(pos.to_owned(), Tile::Unknown); + }); + + RepairDroid { + input: receiver, + output: sender, + grid, + position: (0, 0), + steps: vec![Up], + visited: vec![(0, -1)], + direction: Up, + iterations: 0, + } + } + + fn get_position(&mut self, direction: Direction) -> Point { + let (x, y) = self.position.clone(); + match direction { + Up => (x, y - 1), + Right => (x + 1, y), + Down => (x, y + 1), + Left => (x - 1, y), + } + } + + fn get_grid(&mut self) -> (i64, i64, i64, i64) { + let mut max_x = 0; + let mut max_y = 0; + let mut min_x = 0; + let mut min_y = 0; + + for ((x, y), _tile) in self.grid.clone() { + if x > max_x { + max_x = x.to_owned(); + } + if x < min_x { + min_x = x.to_owned(); + } + if y > max_y { + max_y = y.to_owned(); + } + if y < min_y { + min_y = y.to_owned(); + } + } + + let x_padding = 0 - min_x; + let y_padding = 2 - min_y; + + (max_x + x_padding, x_padding, max_y + y_padding, y_padding) + } + + fn print(&mut self) { + let (max_x, x_padding, max_y, y_padding) = self.get_grid(); + + print!("{}{}", All, Restore); + println!("iterations: {}", self.iterations); + + let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize]; + + for ((x, y), tile) in self.grid.clone() { + if tile == Tile::Unknown { + continue; + } + + let x = (x + x_padding) as usize; + let y = (y + y_padding) as usize; + + if let Some(elem) = grid.get_mut(y) { + elem[x] = match tile { + Tile::Current => 'D', + Tile::Wall => '#', + Tile::Visited => '.', + _ => ' ', + }; + } + } + + for row in grid { + println!("{}", row.clone().iter().collect::()); + } + } + + fn set_direction_of_closest_unknown(&mut self) { + if let Some(steps) = paths::best_match(&self.grid, &self.position, &self.visited) { + let iter = steps.iter(); + let mut steps = Vec::new(); + let mut prev = self.position.to_owned(); + for (x, y) in iter.rev() { + if x == &self.position.0 && y == &self.position.1 { + continue; + } + let direction = if x == &prev.0 { + if y < &prev.1 { + Up + } else { + Down + } + } else { + if x < &prev.0 { + Left + } else { + Right + } + }; + + steps.push(direction.to_owned()); + prev = (x.to_owned(), y.to_owned()); + } + + self.steps = steps.to_owned(); + } else { + println!("no path found :("); + } + } + + fn new_last_goal(&mut self, direction: Option) { + if let Some(direction) = direction { + let point = self.get_position(direction.to_owned()); + self.visited.push(point.to_owned()) + } + } + + fn next_step(&mut self) -> Option { + let mut steps = self.steps.clone().into_iter(); + + let new_last_goal = self.steps.len() == 1; + + let next = steps.next(); + + if new_last_goal { + self.new_last_goal(next); + } + + self.steps = steps.collect(); + + next + } + + fn next_direction(&mut self) -> i64 { + self.direction = match &self.next_step() { + Some(dir) => dir.to_owned(), + _ => { + let mut rng = rand::thread_rng(); + let range = Uniform::from(1..=4); + let dir = range.sample(&mut rng); + Direction::new(dir) + } + }; + + Direction::dir(self.direction) + } + + fn move_droid(&mut self) -> Status { + let next_direction = self.next_direction(); + + self.output.send(next_direction.to_owned()).unwrap(); + + let status = match self.input.recv() { + Ok(curr) => Status::new(curr), + Err(error) => panic!("error: {}", error), + }; + + match status { + Wall => { + let wall_position = self.get_position(self.direction); + self.grid.insert(wall_position, Tile::Wall); + self.set_direction_of_closest_unknown(); + } + _ => { + self.grid.insert(self.position.clone(), Tile::Visited); + self.position = self.get_position(self.direction); + self.grid.insert(self.position.clone(), Tile::Current); + + vec![(0, 1), (1, 0), (-1, 0), (0, -1)] + .iter() + .for_each(|(x, y)| { + let pos = self.position; + let pos = (pos.0 + x, pos.1 + y).to_owned(); + + if !self.grid.contains_key(&pos) { + self.grid.insert(pos.to_owned(), Tile::Unknown); + } + }); + + if self.steps.len() == 0 { + self.set_direction_of_closest_unknown(); + } + } + }; + + status + } + + pub fn run(&mut self) { + while self.move_droid() != MovedAndOnOxygen { + sleep(Duration::from_millis(60)); + self.iterations += 1; + self.print(); + } + } +} From e2dcdcde5828612d144fa7c4982ab3be5d0bdaef Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 16 Dec 2019 11:01:03 +0100 Subject: [PATCH 37/42] feat: trying to solve part 1 --- day_15/src/paths.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/day_15/src/paths.rs b/day_15/src/paths.rs index 413dbf7..62ee8ad 100644 --- a/day_15/src/paths.rs +++ b/day_15/src/paths.rs @@ -39,7 +39,8 @@ pub fn best_match(input: &Map, position: &Point, visited: &Vec) -> Option Some(path) => path.to_owned(), None => continue, }; - if path.len() > steps.len() { + + if path.len() < steps.len() { steps = path.to_owned(); } } From 918ba5aceb1b9e7ffd19138b4ba5e2d024796b70 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 16 Dec 2019 17:32:35 +0100 Subject: [PATCH 38/42] feat: still not done with day 15... --- day_15/src/enums.rs | 1 - day_15/src/main.rs | 2 +- day_15/src/paths.rs | 116 +++++++++++++++++++++++++++++++------ day_15/src/repair_droid.rs | 75 ++++++++++++++++++++---- 4 files changed, 162 insertions(+), 32 deletions(-) diff --git a/day_15/src/enums.rs b/day_15/src/enums.rs index 52f7e4c..ed81f65 100644 --- a/day_15/src/enums.rs +++ b/day_15/src/enums.rs @@ -10,7 +10,6 @@ use Direction::{Down, Left, Right, Up}; impl Direction { pub fn new(input: i64) -> Direction { - println!("input: {:>}", input); match input { 1 => Up, 2 => Down, diff --git a/day_15/src/main.rs b/day_15/src/main.rs index 94473fa..bfcd4c8 100644 --- a/day_15/src/main.rs +++ b/day_15/src/main.rs @@ -8,7 +8,7 @@ fn main() { println!("{:?}", part_01(&input)); } -fn part_01(input: &Vec) { +fn part_01(input: &Vec) -> usize { let (b_sender, a_receiver) = channel(); let (a_sender, b_receiver) = channel(); diff --git a/day_15/src/paths.rs b/day_15/src/paths.rs index 62ee8ad..c64ff8e 100644 --- a/day_15/src/paths.rs +++ b/day_15/src/paths.rs @@ -16,21 +16,60 @@ fn is_between(a: &Point, c: &Point, b: &Point) -> bool { ) } +#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] +struct State { + cost: isize, + point: Point, +} + type Map = HashMap; pub fn best_match(input: &Map, position: &Point, visited: &Vec) -> Option> { - let available = input - .clone() - .iter() - .filter(|(pos, tile)| { - (tile == &&Tile::Unknown || tile == &&Tile::Visited) && !visited.contains(pos) - }) - .map(|(pos, _tile)| pos.to_owned()) - .collect::>(); - - if available.len() <= 0 { - return None; - } + let within_range = || -> Option> { + let get_closest = |range: usize| -> Option> { + let input = input + .clone() + .iter() + .filter(|(pos, tile)| { + (tile == &&Tile::Unknown || tile == &&Tile::Visited) && !visited.contains(pos) + }) + .filter(|(pos, _title)| { + let x = ((position.0 as f64) - (pos.0 as f64)).abs() as usize; + let y = ((position.1 as f64) - (pos.1 as f64)).abs() as usize; + + x <= range && y <= range + }) + .map(|(pos, _tile)| pos.to_owned()) + .collect::>(); + + if input.len() <= 0 { + None + } else { + Some(input.to_owned()) + } + }; + + let mut range = 0; + let mut result = None; + + loop { + if let Some(res) = get_closest(range) { + result = Some(res); + break; + } + range += 1; + if range >= input.len() { + break; + } + } + + result + }; + + let available = match within_range() { + Some(res) => res.to_owned(), + None => return None, + }; let mut steps = vec![]; @@ -40,7 +79,7 @@ pub fn best_match(input: &Map, position: &Point, visited: &Vec) -> Option None => continue, }; - if path.len() < steps.len() { + if steps.len() == 0 || path.len() < steps.len() { steps = path.to_owned(); } } @@ -52,12 +91,6 @@ pub fn best_match(input: &Map, position: &Point, visited: &Vec) -> Option } } -#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, Ord, PartialOrd)] -struct State { - cost: isize, - point: Point, -} - pub fn find_path(map: &Map, start: Point, goal: Point) -> Option> { let adjacent = |point: &Point| -> Vec { let mut vec = Vec::new(); @@ -124,3 +157,48 @@ pub fn find_path(map: &Map, start: Point, goal: Point) -> Option> { Some(path) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_goes_around_the_maze() { + let mut map = HashMap::new(); + + let c = Tile::Current; + let v = Tile::Visited; + let w = Tile::Wall; + + let positions = vec![ + vec![w, w, w, w, w], // [(0,0), (1,0), (2,0), (3,0), (4,0)] + vec![w, v, v, v, w], // [(0,1), (1,1), (2,1), (3,1), (4,1)] + vec![w, v, w, c, w], // [(0,2), (1,2), (2,2), (3,2), (4,2)] + vec![w, v, w, w, w], // [(0,3), (1,3), (2,3), (3,3), (4,3)] + vec![w, v, v, v, w], // [(0,4), (1,4), (2,4), (3,4), (4,4)] + vec![w, w, w, w, w], // [(0,5), (1,5), (2,5), (3,5), (4,5)] + ]; + + for (y, row) in positions.iter().enumerate() { + for (x, tile) in row.iter().enumerate() { + let (x, y) = (x.to_owned() as i64, y.to_owned() as i64); + map.insert((x, y), tile.to_owned()); + } + } + + assert_eq!( + find_path(&map, (3, 2), (3, 4)), + Some(vec![ + (3, 4), + (2, 4), + (1, 4), + (1, 3), + (1, 2), + (1, 1), + (2, 1), + (3, 1), + (3, 2) + ]) + ); + } +} diff --git a/day_15/src/repair_droid.rs b/day_15/src/repair_droid.rs index 151eeb4..729ad89 100644 --- a/day_15/src/repair_droid.rs +++ b/day_15/src/repair_droid.rs @@ -22,6 +22,8 @@ pub struct RepairDroid { input: Receiver, output: Sender, grid: HashMap, + end: Option, + end_route: Option>, position: Point, direction: Direction, iterations: u64, @@ -49,6 +51,8 @@ impl RepairDroid { visited: vec![(0, -1)], direction: Up, iterations: 0, + end: None, + end_route: None, } } @@ -102,19 +106,48 @@ impl RepairDroid { continue; } + let start = x == 0 && y == 0; + let end = !self.end.is_none() && self.end.unwrap() == (x, y); + let x = (x + x_padding) as usize; let y = (y + y_padding) as usize; if let Some(elem) = grid.get_mut(y) { - elem[x] = match tile { - Tile::Current => 'D', - Tile::Wall => '#', - Tile::Visited => '.', - _ => ' ', + elem[x] = if start { + '☆' + } else if end { + '★' + } else { + match tile { + Tile::Current => 'D', + Tile::Wall => '#', + Tile::Visited => '.', + _ => ' ', + } }; } } + if let Some(vec) = &self.end_route { + for (x, y) in vec { + let (x, y) = (x.to_owned(), y.to_owned()); + let start = x == 0 && y == 0; + let end = self.end.unwrap() == (x, y); + let x = (x + x_padding) as usize; + let y = (y + y_padding) as usize; + + if let Some(elem) = grid.get_mut(y) { + elem[x] = if start { + '☆' + } else if end { + '★' + } else { + 'x' + }; + } + } + } + for row in grid { println!("{}", row.clone().iter().collect::()); } @@ -129,6 +162,7 @@ impl RepairDroid { if x == &self.position.0 && y == &self.position.1 { continue; } + let direction = if x == &prev.0 { if y < &prev.1 { Up @@ -190,7 +224,7 @@ impl RepairDroid { Direction::dir(self.direction) } - fn move_droid(&mut self) -> Status { + fn move_droid(&mut self) -> bool { let next_direction = self.next_direction(); self.output.send(next_direction.to_owned()).unwrap(); @@ -200,6 +234,10 @@ impl RepairDroid { Err(error) => panic!("error: {}", error), }; + if status == MovedAndOnOxygen { + self.end = Some(self.position.clone()); + } + match status { Wall => { let wall_position = self.get_position(self.direction); @@ -210,7 +248,6 @@ impl RepairDroid { self.grid.insert(self.position.clone(), Tile::Visited); self.position = self.get_position(self.direction); self.grid.insert(self.position.clone(), Tile::Current); - vec![(0, 1), (1, 0), (-1, 0), (0, -1)] .iter() .for_each(|(x, y)| { @@ -228,14 +265,30 @@ impl RepairDroid { } }; - status + let unknown_left = self.grid.iter().fold(0, |acc, curr| { + if curr.1 == &Tile::Unknown { + acc + 1 + } else { + acc + } + }); + + unknown_left == 0 } - pub fn run(&mut self) { - while self.move_droid() != MovedAndOnOxygen { - sleep(Duration::from_millis(60)); + pub fn run(&mut self) -> usize { + while !self.move_droid() { + sleep(Duration::from_millis(10)); self.iterations += 1; self.print(); } + + if let Some(result) = paths::find_path(&self.grid.to_owned(), (0, 0), self.end.unwrap()) { + self.end_route = Some(result.to_owned()); + self.print(); + result.len() + } else { + 0 + } } } From 11ec7231699716b10e29effacb525c79c08b79aa Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Mon, 16 Dec 2019 20:02:58 +0100 Subject: [PATCH 39/42] feat: added a generic version of the intcode-program-executor --- day_09/src/program.rs | 16 ++++++++++++++++ day_15/src/main.rs | 21 +++++---------------- day_15/src/repair_droid.rs | 12 ++++++------ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/day_09/src/program.rs b/day_09/src/program.rs index cc4132d..ad6fedd 100644 --- a/day_09/src/program.rs +++ b/day_09/src/program.rs @@ -230,3 +230,19 @@ pub fn exec(memory: Vec, output: Option>) -> i64 { handle.join().unwrap() } + +pub fn run(input: &Vec, fun: F) -> T +where + F: Fn(Receiver, Sender) -> T, +{ + let (b_sender, a_receiver) = channel(); + let (a_sender, b_receiver) = channel(); + + let mut program = Program::new(input); + + program.new_input(b_receiver); + program.new_output(b_sender); + + spawn(move || program.run()); + spawn(move || fun(a_receiver, a_sender)).join().unwrap() +} diff --git a/day_15/src/main.rs b/day_15/src/main.rs index bfcd4c8..4cab608 100644 --- a/day_15/src/main.rs +++ b/day_15/src/main.rs @@ -1,24 +1,13 @@ use ::day_15::{parse_input, repair_droid::RepairDroid}; -use day_09::program::Program; -use std::{sync::mpsc::channel, thread::spawn}; +use day_09::program::run; fn main() { let input = parse_input(&include_str!("../../input/day_15")); - - println!("{:?}", part_01(&input)); + println!("part_01: {}", part_01(&input)); } fn part_01(input: &Vec) -> usize { - let (b_sender, a_receiver) = channel(); - let (a_sender, b_receiver) = channel(); - - let mut program = Program::new(&input); - - program.new_input(b_receiver); - program.new_output(b_sender); - - spawn(move || program.run()); - spawn(move || RepairDroid::new(a_receiver, a_sender).run()) - .join() - .unwrap() + run(&input, |reciever, sender| -> usize { + RepairDroid::new(reciever, sender).run() + }) } diff --git a/day_15/src/repair_droid.rs b/day_15/src/repair_droid.rs index 729ad89..392adf9 100644 --- a/day_15/src/repair_droid.rs +++ b/day_15/src/repair_droid.rs @@ -114,12 +114,12 @@ impl RepairDroid { if let Some(elem) = grid.get_mut(y) { elem[x] = if start { - '☆' + 'S' } else if end { - '★' + 'E' } else { match tile { - Tile::Current => 'D', + Tile::Current => 'C', Tile::Wall => '#', Tile::Visited => '.', _ => ' ', @@ -138,11 +138,11 @@ impl RepairDroid { if let Some(elem) = grid.get_mut(y) { elem[x] = if start { - '☆' + 'S' } else if end { - '★' + 'E' } else { - 'x' + ' ' }; } } From 466adb0bb2e2d8495560daffb4d09c420f2cf3ba Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Tue, 17 Dec 2019 10:28:28 +0100 Subject: [PATCH 40/42] feat: preparations for part 2 --- day_09/src/program.rs | 38 +++++------ day_13/src/game.rs | 8 ++- day_15/src/enums.rs | 11 ++++ day_15/src/main.rs | 5 +- day_15/src/repair_droid.rs | 125 ++++++++++++++++++++++++++++--------- 5 files changed, 131 insertions(+), 56 deletions(-) diff --git a/day_09/src/program.rs b/day_09/src/program.rs index ad6fedd..f5e75b2 100644 --- a/day_09/src/program.rs +++ b/day_09/src/program.rs @@ -165,20 +165,6 @@ impl Program { 2 } - pub fn run(&mut self) -> i64 { - self.pointer = 0; - self.output_value = 0; - self.halted = false; - self.memory = self.original_memory.clone(); - self.relative_base = 0; - - while !self.halted { - self.eval(); - } - - self.output_value.to_owned() - } - fn eval(&mut self) { let string = self.memory[self.pointer].to_string(); let mut instuction = string.chars().rev(); @@ -206,19 +192,29 @@ impl Program { self.pointer = ((self.pointer as i64) + next) as usize; } + + pub fn run(&mut self) -> i64 { + self.pointer = 0; + self.output_value = 0; + self.halted = false; + self.memory = self.original_memory.clone(); + self.relative_base = 0; + + while !self.halted { + self.eval(); + } + + self.output_value.to_owned() + } } pub fn exec(memory: Vec, output: Option>) -> i64 { let (program_sender, _exec_reciever) = channel(); let (exec_sender, program_receiver) = channel(); - match output { - Some(vec) => { - vec.into_iter().for_each(|val| { - exec_sender.send(val).unwrap(); - }); - } - None => {} + if let Some(vec) = output { + vec.into_iter() + .for_each(|val| exec_sender.send(val).unwrap()) }; let handle = spawn(move || { diff --git a/day_13/src/game.rs b/day_13/src/game.rs index ef83c77..e3358cc 100644 --- a/day_13/src/game.rs +++ b/day_13/src/game.rs @@ -2,6 +2,7 @@ use crate::Tile::{self, *}; use std::{ collections::HashMap, sync::mpsc::{Receiver, Sender}, + thread::sleep, time::Duration, }; use termion::{clear::All, cursor::Restore}; @@ -85,8 +86,8 @@ impl Game { if let Some(elem) = grid.get_mut(y) { elem[x] = match tile { - Wall => '#', - Block => '◻', + Wall => '░', + Block => '▓', HorizontalPaddle => '=', Ball => 'o', _ => ' ', @@ -169,7 +170,7 @@ impl Game { 'main_loop: loop { let mut current_input = vec![]; 'collect_loop: loop { - let curr = match self.input.recv_timeout(Duration::from_millis(25)) { + let curr = match self.input.recv_timeout(Duration::from_millis(5)) { Ok(x) => x, _ => break 'collect_loop, }; @@ -196,6 +197,7 @@ impl Game { }; self.iterations += 1; + sleep(Duration::from_millis(50)) } self.score.to_owned() diff --git a/day_15/src/enums.rs b/day_15/src/enums.rs index ed81f65..e9609e5 100644 --- a/day_15/src/enums.rs +++ b/day_15/src/enums.rs @@ -63,4 +63,15 @@ pub enum Tile { Unknown, Wall, Visited, + Oxygen, +} + +impl Tile { + pub fn new(input: &str) -> Tile { + match input { + "0" => Tile::Wall, + "1" => Tile::Visited, + _ => Tile::Oxygen, + } + } } diff --git a/day_15/src/main.rs b/day_15/src/main.rs index 4cab608..575881f 100644 --- a/day_15/src/main.rs +++ b/day_15/src/main.rs @@ -3,11 +3,8 @@ use day_09::program::run; fn main() { let input = parse_input(&include_str!("../../input/day_15")); - println!("part_01: {}", part_01(&input)); -} -fn part_01(input: &Vec) -> usize { run(&input, |reciever, sender| -> usize { RepairDroid::new(reciever, sender).run() - }) + }); } diff --git a/day_15/src/repair_droid.rs b/day_15/src/repair_droid.rs index 392adf9..7403c35 100644 --- a/day_15/src/repair_droid.rs +++ b/day_15/src/repair_droid.rs @@ -31,27 +31,59 @@ pub struct RepairDroid { visited: Vec, } +fn test() -> Vec<(i64, i64, Tile)> { + include_str!("../../input/day_15_part_02") + .lines() + .map(|string| string.trim()) + .filter(|string| !string.is_empty()) + .map(|row| { + let mut split = row.split(' '); + + let x = split.next().unwrap(); + let y = split.next().unwrap(); + let tile = split.next().unwrap(); + + ( + x.parse::().unwrap(), + y.parse::().unwrap(), + Tile::new(tile), + ) + }) + .collect() +} + impl RepairDroid { pub fn new(receiver: Receiver, sender: Sender) -> RepairDroid { + include_str!("../../input/day_15_part_02"); + let mut grid = HashMap::new(); - grid.insert((0, 0), Tile::Current); + // grid.insert((0, 0), Tile::Current); - vec![(0, 1), (1, 0), (-1, 0), (0, -1)] - .iter() - .for_each(|pos| { - grid.insert(pos.to_owned(), Tile::Unknown); - }); + for (x, y, tile) in test() { + grid.insert((x.to_owned(), y.to_owned()), tile.to_owned()); + } + + // vec![(0, 1), (1, 0), (-1, 0), (0, -1)] + // .iter() + // .for_each(|pos| { + // grid.insert(pos.to_owned(), Tile::Unknown); + // }); RepairDroid { input: receiver, output: sender, grid, position: (0, 0), - steps: vec![Up], - visited: vec![(0, -1)], + + // steps: vec![Up], + // visited: vec![(0, -1)], + steps: vec![], + visited: vec![], + direction: Up, - iterations: 0, - end: None, + // iterations: 0, + iterations: 3536, + end: Some((-13, -18)), end_route: None, } } @@ -88,25 +120,26 @@ impl RepairDroid { } let x_padding = 0 - min_x; - let y_padding = 2 - min_y; + let y_padding = 0 - min_y; (max_x + x_padding, x_padding, max_y + y_padding, y_padding) } - fn print(&mut self) { + fn print(&mut self, print_oxygen: bool) { let (max_x, x_padding, max_y, y_padding) = self.get_grid(); print!("{}{}", All, Restore); println!("iterations: {}", self.iterations); - let mut grid = vec![vec![' '; (max_x + 1) as usize]; (max_y + 1) as usize]; + let mut grid = vec![vec!['⍰'; (max_x + 1) as usize]; (max_y + 1) as usize]; + let reached_end = !self.end_route.is_none(); for ((x, y), tile) in self.grid.clone() { if tile == Tile::Unknown { continue; } - let start = x == 0 && y == 0; + let start = !print_oxygen && x == 0 && y == 0; let end = !self.end.is_none() && self.end.unwrap() == (x, y); let x = (x + x_padding) as usize; @@ -119,10 +152,17 @@ impl RepairDroid { 'E' } else { match tile { - Tile::Current => 'C', - Tile::Wall => '#', - Tile::Visited => '.', - _ => ' ', + Tile::Current => { + if reached_end { + '▓' + } else { + 'D' + } + } + Tile::Wall => '░', + Tile::Visited => '▓', + Tile::Oxygen => '▒', + _ => '⍰', } }; } @@ -142,7 +182,7 @@ impl RepairDroid { } else if end { 'E' } else { - ' ' + '▒' }; } } @@ -276,19 +316,48 @@ impl RepairDroid { unknown_left == 0 } + fn part_01(&mut self) { + if let Some(result) = paths::find_path(&self.grid.to_owned(), (0, 0), self.end.unwrap()) { + self.end_route = Some(result.to_owned()); + self.print(false); + + println!("part_01: {}", result.len()); + + sleep(Duration::from_secs(10)); + } + } + + fn part_02(&mut self) { + let oxygen = self.end.unwrap().to_owned(); + self.position = oxygen.to_owned(); + + self.end = None; + self.end_route = None; + + self.grid + .clone() + .into_iter() + .filter(|(_pos, tile)| tile != &Tile::Wall && tile != &Tile::Visited) + .for_each(|(pos, _tile)| { + *self.grid.get_mut(&pos).unwrap() = Tile::Visited; + }); + + *self.grid.get_mut(&oxygen).unwrap() = Tile::Oxygen; + + self.print(true); + } + pub fn run(&mut self) -> usize { while !self.move_droid() { - sleep(Duration::from_millis(10)); + // sleep(Duration::from_millis(10)); self.iterations += 1; - self.print(); + self.print(false); } - if let Some(result) = paths::find_path(&self.grid.to_owned(), (0, 0), self.end.unwrap()) { - self.end_route = Some(result.to_owned()); - self.print(); - result.len() - } else { - 0 - } + self.part_01(); + sleep(Duration::from_secs(5)); + self.part_02(); + + 0 } } From 79b2cefa4679658d17a7827c3a52e5a9d622f7f7 Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Fri, 20 Dec 2019 16:11:00 +0100 Subject: [PATCH 41/42] feat: just wanted to complete day 15 --- README.md | 2 ++ day_15/src/paths.rs | 37 +++++++++++++++++------ day_15/src/repair_droid.rs | 62 ++++++++++++++++++++++++++------------ 3 files changed, 71 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 82c3a23..07da6e7 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,5 @@ - [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟 - [Day 12](https://github.com/ankjevel/adventofcode/tree/2019/day_12) 🌟 🌟 - [Day 13](https://github.com/ankjevel/adventofcode/tree/2019/day_13) 🌟 🌟 +- [Day 14](https://github.com/ankjevel/adventofcode/tree/2019/day_14) +- [Day 15](https://github.com/ankjevel/adventofcode/tree/2019/day_15) diff --git a/day_15/src/paths.rs b/day_15/src/paths.rs index c64ff8e..55d0e70 100644 --- a/day_15/src/paths.rs +++ b/day_15/src/paths.rs @@ -1,6 +1,6 @@ use crate::enums::Tile; use crate::Point; -use std::collections::{BinaryHeap, HashMap}; +use std::collections::{BinaryHeap, HashMap, HashSet}; fn distance(p1: &Point, p2: &Point) -> f64 { ((p2.0 as f64 - p1.0 as f64).powf(2f64) + (p2.1 as f64 - p1.1 as f64).powf(2f64)).sqrt() @@ -91,22 +91,39 @@ pub fn best_match(input: &Map, position: &Point, visited: &Vec) -> Option } } -pub fn find_path(map: &Map, start: Point, goal: Point) -> Option> { - let adjacent = |point: &Point| -> Vec { - let mut vec = Vec::new(); +pub fn adjacent(map: &Map, point: &Point) -> Vec { + let mut vec = Vec::new(); + + for (x, y) in vec![(0, 1), (1, 0), (-1, 0), (0, -1)] { + let new_pos = (point.0 + x, point.1 + y); + if let Some(tile) = map.get(&new_pos) { + if tile != &Tile::Wall { + vec.push(new_pos.to_owned()); + } + }; + } + + vec +} +pub fn find_leafs(map: &Map, current: &Vec) -> Vec { + let mut new_leafs: HashSet = HashSet::new(); + + for point in current { for (x, y) in vec![(0, 1), (1, 0), (-1, 0), (0, -1)] { let new_pos = (point.0 + x, point.1 + y); if let Some(tile) = map.get(&new_pos) { - if tile != &Tile::Wall { - vec.push(new_pos.to_owned()); + if tile == &Tile::Visited { + new_leafs.insert(new_pos.to_owned()); } - }; + } } + } - vec - }; + new_leafs.into_iter().collect::>() +} +pub fn find_path(map: &Map, start: Point, goal: Point) -> Option> { let can_move = |point: &Point| -> bool { match map.get(&point) { Some(tile) => tile != &Tile::Wall, @@ -128,7 +145,7 @@ pub fn find_path(map: &Map, start: Point, goal: Point) -> Option> { if current.unwrap().point == goal { break; } - for next_point in adjacent(¤t.unwrap().point) { + for next_point in adjacent(map, ¤t.unwrap().point) { if !came_from.contains_key(&next_point) && can_move(&next_point) { frontier.push(State { point: next_point, diff --git a/day_15/src/repair_droid.rs b/day_15/src/repair_droid.rs index 7403c35..beece1c 100644 --- a/day_15/src/repair_droid.rs +++ b/day_15/src/repair_droid.rs @@ -10,6 +10,7 @@ use rand::{ }; use std::{ collections::HashMap, + mem::replace, sync::mpsc::{Receiver, Sender}, thread::sleep, time::Duration, @@ -54,20 +55,20 @@ fn test() -> Vec<(i64, i64, Tile)> { impl RepairDroid { pub fn new(receiver: Receiver, sender: Sender) -> RepairDroid { - include_str!("../../input/day_15_part_02"); + // include_str!("../../input/day_15_part_02"); let mut grid = HashMap::new(); - // grid.insert((0, 0), Tile::Current); + grid.insert((0, 0), Tile::Current); - for (x, y, tile) in test() { - grid.insert((x.to_owned(), y.to_owned()), tile.to_owned()); - } + // for (x, y, tile) in test() { + // grid.insert((x.to_owned(), y.to_owned()), tile.to_owned()); + // } - // vec![(0, 1), (1, 0), (-1, 0), (0, -1)] - // .iter() - // .for_each(|pos| { - // grid.insert(pos.to_owned(), Tile::Unknown); - // }); + vec![(0, 1), (1, 0), (-1, 0), (0, -1)] + .iter() + .for_each(|pos| { + grid.insert(pos.to_owned(), Tile::Unknown); + }); RepairDroid { input: receiver, @@ -75,15 +76,15 @@ impl RepairDroid { grid, position: (0, 0), - // steps: vec![Up], - // visited: vec![(0, -1)], - steps: vec![], - visited: vec![], - + steps: vec![Up], + visited: vec![(0, -1)], + // steps: vec![], + // visited: vec![], direction: Up, - // iterations: 0, - iterations: 3536, - end: Some((-13, -18)), + iterations: 0, + // iterations: 3536, + end: None, + // end: Some((-13, -18)), end_route: None, } } @@ -345,17 +346,38 @@ impl RepairDroid { *self.grid.get_mut(&oxygen).unwrap() = Tile::Oxygen; self.print(true); + + let mut leafs = vec![oxygen.to_owned()]; + self.iterations = 0; + loop { + self.iterations += 1; + let mut new_leafs = paths::find_leafs(&self.grid.to_owned(), &leafs); + if new_leafs.len() == 0 { + break; + } + + for point in &new_leafs { + *self.grid.get_mut(&point).unwrap() = Tile::Oxygen; + } + + self.print(true); + + sleep(Duration::from_millis(40)); + + leafs = replace(&mut new_leafs, vec![]); + } + + println!("part_02: {}", self.iterations); } pub fn run(&mut self) -> usize { while !self.move_droid() { - // sleep(Duration::from_millis(10)); + sleep(Duration::from_millis(10)); self.iterations += 1; self.print(false); } self.part_01(); - sleep(Duration::from_secs(5)); self.part_02(); 0 From 535faaf8901f67b4d34f41f6c8e265c03158a0fd Mon Sep 17 00:00:00 2001 From: Dennis Pettersson Date: Sat, 5 Dec 2020 12:56:16 +0100 Subject: [PATCH 42/42] fix: rewrote history and ended up with a broken state --- .gitignore | 5 + README.md | 13 +- input/day_01 | 100 +++ input/day_02 | 1 + input/day_03 | 2 + input/day_04 | 1 + input/day_05 | 1 + input/day_06 | 1869 ++++++++++++++++++++++++++++++++++++++++++++++++++ input/day_07 | 1 + input/day_08 | 1 + input/day_09 | 1 + input/day_10 | 36 + input/day_11 | 1 + input/day_12 | 4 + input/day_13 | 1 + input/day_14 | 59 ++ input/day_15 | 1 + 17 files changed, 2095 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 input/day_01 create mode 100644 input/day_02 create mode 100644 input/day_03 create mode 100644 input/day_04 create mode 100644 input/day_05 create mode 100644 input/day_06 create mode 100644 input/day_07 create mode 100644 input/day_08 create mode 100644 input/day_09 create mode 100644 input/day_10 create mode 100644 input/day_11 create mode 100644 input/day_12 create mode 100644 input/day_13 create mode 100644 input/day_14 create mode 100644 input/day_15 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..695a16a --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +debug/ +target/ + +**/*.rs.bk +*/Cargo.lock diff --git a/README.md b/README.md index 07da6e7..2e57ad7 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,14 @@ - [Day 11](https://github.com/ankjevel/adventofcode/tree/2019/day_11) 🌟 🌟 - [Day 12](https://github.com/ankjevel/adventofcode/tree/2019/day_12) 🌟 🌟 - [Day 13](https://github.com/ankjevel/adventofcode/tree/2019/day_13) 🌟 🌟 -- [Day 14](https://github.com/ankjevel/adventofcode/tree/2019/day_14) -- [Day 15](https://github.com/ankjevel/adventofcode/tree/2019/day_15) +- [Day 14](https://github.com/ankjevel/adventofcode/tree/2019/day_14) 🌟 🌟 +- [Day 15](https://github.com/ankjevel/adventofcode/tree/2019/day_15) 🌟 🌟 +- [Day 16](#) +- [Day 17](#) +- [Day 18](#) +- [Day 19](#) +- [Day 20](#) +- [Day 21](#) +- [Day 22](#) +- [Day 23](#) +- [Day 24](#) diff --git a/input/day_01 b/input/day_01 new file mode 100644 index 0000000..4b8b699 --- /dev/null +++ b/input/day_01 @@ -0,0 +1,100 @@ +67931 +140303 +100800 +69347 +113036 +127599 +55139 +99718 +110237 +94677 +91616 +61413 +97141 +147045 +80317 +85634 +128437 +110968 +98512 +126502 +59518 +50056 +51086 +76184 +108467 +68365 +147143 +108928 +116226 +66485 +51628 +135307 +137996 +97127 +81613 +75879 +125516 +94620 +143558 +132034 +54931 +92674 +53882 +127867 +131491 +62407 +64241 +71360 +56144 +90334 +134159 +75906 +73796 +117579 +86488 +148313 +75021 +97415 +120250 +79846 +86608 +120340 +85784 +129891 +138462 +52790 +89129 +113506 +120093 +137375 +146849 +54732 +56648 +85853 +64955 +146544 +117935 +139159 +142617 +128819 +82180 +76478 +74373 +110449 +75714 +83893 +135584 +86978 +99137 +75541 +122106 +146599 +86589 +130870 +84015 +84593 +67129 +131571 +147694 +118053 diff --git a/input/day_02 b/input/day_02 new file mode 100644 index 0000000..aed4846 --- /dev/null +++ b/input/day_02 @@ -0,0 +1 @@ +1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,6,1,19,1,19,9,23,1,23,9,27,1,10,27,31,1,13,31,35,1,35,10,39,2,39,9,43,1,43,13,47,1,5,47,51,1,6,51,55,1,13,55,59,1,59,6,63,1,63,10,67,2,67,6,71,1,71,5,75,2,75,10,79,1,79,6,83,1,83,5,87,1,87,6,91,1,91,13,95,1,95,6,99,2,99,10,103,1,103,6,107,2,6,107,111,1,13,111,115,2,115,10,119,1,119,5,123,2,10,123,127,2,127,9,131,1,5,131,135,2,10,135,139,2,139,9,143,1,143,2,147,1,5,147,0,99,2,0,14,0 diff --git a/input/day_03 b/input/day_03 new file mode 100644 index 0000000..88bb814 --- /dev/null +++ b/input/day_03 @@ -0,0 +1,2 @@ +R990,U475,L435,D978,L801,D835,L377,D836,L157,D84,R329,D342,R931,D522,L724,U891,L508,U274,L146,U844,R686,D441,R192,U992,L781,D119,R436,D286,R787,D85,L801,U417,R619,D710,R42,U261,R296,U697,L354,D843,R613,U880,R789,D134,R636,D738,L939,D459,L338,D905,R811,D950,L44,U992,R845,U771,L563,D76,L69,U839,L57,D311,L615,D931,L437,D201,L879,D1,R978,U415,R548,D398,L560,D112,L894,D668,L708,D104,R622,D768,R901,D746,L793,D26,R357,U216,L216,D33,L653,U782,R989,U678,L7,D649,R860,D281,L988,U362,L525,U652,R620,D376,L983,U759,R828,D669,L297,U207,R68,U77,R255,U269,L661,U310,L309,D490,L55,U471,R260,D912,R691,D62,L63,D581,L289,D366,L862,D360,L485,U946,R937,D470,L792,D614,R936,D963,R611,D151,R908,D195,R615,U768,L166,D314,R640,U47,L161,U872,R50,U694,L917,D149,L92,U244,L337,U479,R755,U746,L196,D759,L936,U61,L744,D774,R53,U439,L185,D504,R769,D696,L285,D396,R791,U21,L35,D877,L9,U398,R447,U101,R590,U862,L351,D210,L935,U938,R131,U758,R99,U192,L20,U142,L946,D981,R998,U214,R174,U710,L719,D879,L411,U839,L381,U924,L221,D397,R380,U715,R139,D367,R253,D973,L9,U624,L426,D885,R200,U940,R214,D75,R717,D2,R578,U161,R421,U326,L561,U311,L701,U259,R836,D920,R35,D432,R610,D63,R664,D39,L119,D47,L605,D228,L364,D14,L226,D365,R796,D233,R476,U145,L926,D907,R681,U267,R844,U735,L948,U344,L629,U31,L383,U694,L666,U158,R841,D27,L150,D950,L335,U275,L184,D157,R504,D602,R605,D185,L215,D420,R700,U809,L139,D937,L248,U693,L56,U92,L914,U743,R445,U417,L504,U23,R332,U865,R747,D553,R595,U845,R693,U915,R81 +L1004,U406,L974,D745,R504,D705,R430,D726,R839,D550,L913,D584,R109,U148,L866,U664,R341,U449,L626,D492,R716,U596,L977,D987,L47,U612,L478,U928,L66,D752,R665,U415,R543,U887,R315,D866,R227,D615,R478,U180,R255,D316,L955,U657,R752,U561,R786,U7,R918,D755,R506,U131,L875,D849,R823,D755,L604,U944,R186,D326,L172,U993,L259,D765,R427,D193,R663,U470,L294,D437,R645,U10,L926,D814,L536,D598,R886,D290,L226,U156,R754,D105,L604,D136,L883,U87,R839,D807,R724,U184,L746,D79,R474,U186,R727,U9,L69,U565,R459,D852,R61,U370,L890,D439,L431,U846,R460,U358,R51,D407,R55,U179,L385,D652,R193,D52,L569,U980,L185,U813,R636,D275,L585,U590,R215,U947,R851,D127,L249,U954,L884,D235,R3,U735,R994,D883,L386,D506,L963,D751,L989,U733,L221,U890,L711,D32,L74,U437,L700,D977,L49,U478,R438,D27,R945,D670,L230,U863,L616,U461,R267,D25,L646,D681,R426,D918,L791,U712,L730,U715,L67,U359,R915,D524,L722,U374,L582,U529,L802,D865,L596,D5,R323,U235,R405,D62,R304,U996,L939,U420,L62,D299,R802,D803,L376,U430,L810,D334,L67,U395,L818,U953,L817,D411,L225,U383,R247,D234,L430,U315,L418,U254,L964,D372,R979,D301,R577,U440,R924,D220,L121,D785,L609,U20,R861,U288,R388,D410,L278,D748,L800,U755,L919,D985,L785,U676,R916,D528,L507,D469,L582,D8,L900,U512,L764,D124,L10,U567,L379,D231,R841,D244,R479,U145,L769,D845,R651,U712,L920,U791,R95,D958,L608,D755,R967,U855,R563,D921,L37,U699,L944,U718,R959,D195,L922,U726,R378,U258,R340,D62,L555,D135,L690,U269,L273,D851,L60,D851,R1,D315,R117,D855,L275,D288,R25,U503,R569,D596,L823,U687,L450 diff --git a/input/day_04 b/input/day_04 new file mode 100644 index 0000000..32fdd49 --- /dev/null +++ b/input/day_04 @@ -0,0 +1 @@ +347312-805915 diff --git a/input/day_05 b/input/day_05 new file mode 100644 index 0000000..15411a8 --- /dev/null +++ b/input/day_05 @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1102,72,20,224,1001,224,-1440,224,4,224,102,8,223,223,1001,224,5,224,1,224,223,223,1002,147,33,224,101,-3036,224,224,4,224,102,8,223,223,1001,224,5,224,1,224,223,223,1102,32,90,225,101,65,87,224,101,-85,224,224,4,224,1002,223,8,223,101,4,224,224,1,223,224,223,1102,33,92,225,1102,20,52,225,1101,76,89,225,1,117,122,224,101,-78,224,224,4,224,102,8,223,223,101,1,224,224,1,223,224,223,1102,54,22,225,1102,5,24,225,102,50,84,224,101,-4600,224,224,4,224,1002,223,8,223,101,3,224,224,1,223,224,223,1102,92,64,225,1101,42,83,224,101,-125,224,224,4,224,102,8,223,223,101,5,224,224,1,224,223,223,2,58,195,224,1001,224,-6840,224,4,224,102,8,223,223,101,1,224,224,1,223,224,223,1101,76,48,225,1001,92,65,224,1001,224,-154,224,4,224,1002,223,8,223,101,5,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,677,226,224,1002,223,2,223,1005,224,329,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,344,1001,223,1,223,1107,226,226,224,1002,223,2,223,1006,224,359,1001,223,1,223,8,226,226,224,1002,223,2,223,1006,224,374,101,1,223,223,108,226,226,224,102,2,223,223,1005,224,389,1001,223,1,223,1008,226,226,224,1002,223,2,223,1005,224,404,101,1,223,223,1107,226,677,224,1002,223,2,223,1006,224,419,101,1,223,223,1008,226,677,224,1002,223,2,223,1006,224,434,101,1,223,223,108,677,677,224,1002,223,2,223,1006,224,449,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,464,1001,223,1,223,107,677,677,224,102,2,223,223,1005,224,479,101,1,223,223,7,226,677,224,1002,223,2,223,1006,224,494,1001,223,1,223,7,677,677,224,102,2,223,223,1006,224,509,101,1,223,223,107,226,677,224,1002,223,2,223,1006,224,524,1001,223,1,223,1007,226,226,224,102,2,223,223,1006,224,539,1001,223,1,223,108,677,226,224,102,2,223,223,1005,224,554,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,569,101,1,223,223,8,677,226,224,102,2,223,223,1006,224,584,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,599,1001,223,1,223,1007,677,226,224,1002,223,2,223,1005,224,614,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,629,101,1,223,223,1108,677,677,224,1002,223,2,223,1005,224,644,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,659,101,1,223,223,107,226,226,224,102,2,223,223,1005,224,674,101,1,223,223,4,223,99,226 diff --git a/input/day_06 b/input/day_06 new file mode 100644 index 0000000..9aff252 --- /dev/null +++ b/input/day_06 @@ -0,0 +1,1869 @@ +XV5)LZ5 +6JC)7ZG +NCW)VDZ +CPM)N4Z +3PZ)4D6 +3TT)QPK +G1T)FD5 +S43)3G7 +26J)ZMX +GTS)G9S +1GM)9ZN +WCW)XTJ +9B7)NTZ +QDH)P9B +FN2)6NB +8XB)H8X +638)2KM +R42)M9X +GX7)TGJ +HB4)6SC +9RP)62K +W69)787 +T5M)H81 +M1C)KF5 +Z8D)F1Y +F53)N8J +BKJ)KYJ +N9B)SHB +QNJ)BST +CD1)RVG +TBD)Q68 +XL4)VSV +Y84)L1C +Q26)HGL +JWN)42N +MXF)XT6 +T5L)JCX +2ZH)PQJ +QJR)GWG +KDY)5Y3 +WCS)BRL +3K7)JX3 +CHC)MCZ +WFT)GBX +7NN)QVT +JJY)RRG +C9W)CS6 +CR2)J1Y +GQR)X9Q +WSX)3KX +DCV)GQR +1Z8)MC2 +XJP)WQC +N1C)MY4 +J75)4CW +Y35)RR1 +K3D)XWG +VWV)LXN +P18)RSW +RX1)5P9 +DMP)XNR +FNG)H83 +DVW)B2Q +JJ4)BL4 +428)TLP +N74)6TQ +RSX)45D +NM2)1JD +RSX)2LL +M9X)PWW +W2J)DQ9 +DCW)WKP +Q3B)FMY +RPD)Y7X +NZ6)4PV +NM4)SGJ +BBD)WWV +XN6)9QQ +WPZ)WJ9 +ST4)T72 +NDQ)XJ9 +P5G)G3N +5VY)CNC +GQG)SSB +M7R)8QN +NR8)DQJ +KSW)Z8S +42B)JBM +BTV)985 +N7N)SGC +GW9)6Q8 +73H)FSQ +8GR)176 +RWL)XCH +M3Z)RZ1 +1ZV)6BV +6MW)TCW +2HF)6JJ +47B)8R6 +1TX)DSQ +55J)GL3 +99Y)D27 +CD6)PCP +VW8)JNV +FNK)Q3B +HWB)948 +3CT)XP3 +684)RK3 +TDG)4GH +DZZ)NCW +GR2)BJX +N2M)9GR +331)FGR +HDQ)K74 +QC2)12V +5TP)344 +QPN)4WD +QJG)TWS +15P)9NX +4CV)WLD +XGN)C88 +1Y6)7LB +Z32)TNV +G2V)QNQ +673)YPW +22J)628 +G46)7PK +JN8)KZK +4CW)PJS +DMY)QXC +7LB)L7S +LQ9)X8N +C3T)VWL +BZ8)M2F +XQ3)QKV +89K)4YJ +9BB)KV4 +X8N)1PJ +PZT)98P +C88)YSP +LDV)T39 +1ZQ)SND +TJJ)YKM +7N4)8V8 +BBD)S66 +5MF)2X2 +GWW)LTH +KQK)KPG +FNV)HWD +SMJ)HWZ +M41)2W1 +W1G)C5D +X79)P3C +4KT)N5Q +7BS)BWR +CLX)DCW +C1T)Q7C +4K5)Y84 +63K)H8L +PRZ)8JW +LNM)8HG +N4Z)GKB +7DX)C1F +BJX)LX3 +NWL)LK5 +LGW)ZXN +XV7)W6H +XBH)44C +376)1LQ +HQL)9BB +PX2)3KS +VHC)XP9 +4YZ)3XD +SVN)2T8 +G8Z)ZP3 +YXP)H6D +4C6)MLH +BST)QV3 +RXP)CBM +M9X)WCW +5PJ)W3R +98P)PXC +MB3)TDG +J4L)GJM +6BV)59Y +CNC)7P1 +Q7V)1H5 +3WF)65H +MK1)SM4 +6JJ)YSV +JFL)HC5 +6G7)1LD +4GY)G9V +B1Q)WCV +3QY)K7W +TSC)KDY +SQS)1WB +LV2)2SC +FNV)4QX +M2W)47Y +Z8S)PQ9 +VSY)S88 +6TD)CP7 +DCD)4CT +3NQ)R39 +6D5)YZC +QFC)DDG +XTJ)9SX +SYH)Y8J +KZ9)V3D +32H)DD7 +W9V)YP3 +HQ1)RYK +XHR)1TD +7VD)4S5 +H81)PQR +838)D9H +JGT)R7V +2MX)FTS +1TD)CKB +V2Z)F53 +7XL)563 +SM4)J3M +DMP)Z9S +J3G)6JC +MWB)VPM +NTS)V21 +2LG)97S +9W9)CS9 +HLB)M2L +WJ3)DTH +G3S)5BD +2YJ)PPH +ZXK)HXX +VFR)G3L +1JK)L36 +TVV)4GY +4HY)F1F +JBM)XZ1 +BL4)X1D +NF8)9KV +SXX)PYS +HPD)HBH +RMF)HHZ +4HK)5G8 +XZX)1ZV +MCB)3YW +LP4)JMQ +WDL)JWB +757)B3C +MQX)8TY +HMN)HV1 +J18)SKS +LXJ)B41 +ZGV)JVM +DC1)3K5 +QMC)SVQ +VB9)2Z4 +WHT)BKM +CDK)MS5 +SLQ)ZRZ +7FL)GR2 +9T2)K81 +2T8)RX1 +DGR)PMG +DGP)R3M +NC8)WTV +LK5)4XF +132)QBZ +D79)19N +B4D)1FM +53B)HLN +HS1)RCM +LQQ)CV3 +HJW)RB8 +LC7)BFM +28Q)QLG +CS9)G22 +Q98)GX7 +P9B)N1C +JNR)VHW +NVK)W4N +V5R)HB4 +D89)5P6 +YQ3)LB9 +RSW)Q6W +QM5)9XS +TQM)3TT +BV8)WCS +9HZ)HMP +4LX)XN6 +FGR)7Q1 +V9F)G1Z +GBX)718 +2HR)SLL +PZB)LGP +PBC)32W +5JZ)N3Y +TZ9)2S1 +CNF)4YS +T21)PKL +4H2)XGN +6SB)2HW +R1V)LQB +DCT)NKZ +XTB)98Z +CRZ)4LX +8W7)JQQ +C8M)92K +3YW)YBY +C76)42B +R3M)FXF +2VF)C12 +P1T)B4H +ZP3)NM6 +KJB)JTN +DTB)WMD +RS8)2BX +GCB)5HK +4WD)F2T +BZB)8NK +NBK)SGD +QV3)KXN +WVG)4HY +KRN)3VW +M4Q)J75 +STH)T8Q +GNV)5VY +366)ZMV +41V)PBC +MHQ)3N4 +KVB)312 +K7Z)YYJ +HBF)11M +F2Q)17H +2YZ)QV6 +THG)5WF +S8B)V5H +LY5)MQM +TVK)FD6 +72F)QMQ +LCT)HBZ +LGZ)DLC +RQ6)CPW +V9J)Y5Y +4LK)WN1 +F2Y)F8D +WQR)RMZ +Z42)JZ3 +QNQ)29B +F1W)CFT +T3J)13Q +6NB)HVY +G64)88J +DD7)W3G +CXY)CNF +FD5)9C2 +8QH)FCS +4K5)KZ9 +C12)NTS +PJJ)298 +9G7)5BF +HYT)GHC +CVT)QKK +PX2)LC7 +VN8)8DZ +LT5)TYL +12Z)RMY +GRY)DRD +G6R)RDJ +864)ZT9 +DKD)N74 +L74)SWF +2B6)4LK +8V8)CLB +45K)LL9 +YBY)JF4 +Q9Q)55M +78F)6RM +HYN)7TH +7QN)HP9 +TB2)ZZM +39D)T5W +C5P)LGW +DLD)RSX +9RZ)HPC +7TL)9T1 +Y3S)CRZ +DTH)35N +FD7)K3D +YNK)FNB +G1P)758 +68M)BQ8 +YMP)VW8 +PJZ)PJQ +JJY)Y6B +MD4)XNT +4CS)SS5 +2X2)B52 +2TR)XL4 +H8X)C4N +SV5)TL5 +CGN)QM5 +MXZ)GSX +Z8K)JT2 +738)MR5 +2ZS)4F6 +QSD)NRM +Q48)N1T +4SH)99Y +3VW)M3Z +62K)HYN +XTQ)9VX +1FS)KF2 +9VL)K71 +XVB)7FL +QHN)DSL +Y6B)KRC +SNJ)X8C +ZDL)DPL +2TR)3FH +CP7)TG1 +3K7)L7K +KQK)MK1 +53H)MY9 +7FW)S5B +QL9)LF8 +4FG)MJY +FMY)6VK +G3Z)HDQ +T39)BD9 +R6B)YFS +HCX)72F +QKP)RF9 +N1C)462 +9RM)B1Q +TLP)7QN +QSW)Q72 +NH3)253 +4TG)DCT +Z4K)GV9 +4YS)689 +KSQ)P2S +SV7)Z81 +D2J)73K +RSY)FG7 +5PR)66Q +QY8)HYT +Z52)VBB +3P3)7CQ +GWD)3PZ +GH6)RRF +YQ2)YSL +TQM)F6N +TWT)R8N +YYJ)X86 +LDV)362 +TV5)S99 +JTN)VHC +42N)BX1 +LMV)XQ3 +Z27)Y1V +DWK)RTT +64J)3CT +VWV)RF3 +NLV)1L3 +M4Y)JB3 +JGL)LR3 +F4T)LK7 +CD6)CR2 +167)7LW +ZMV)4D3 +ZCY)X62 +G3N)VSY +3SC)W6C +N3Y)4KT +V3D)HRV +QGH)KLP +XV7)JZ8 +YR4)CBG +L6B)N1V +628)STY +YQX)FLG +4RR)NKX +L7K)SVN +VBQ)SLK +H3Z)BGN +5P6)NY3 +G7X)2NG +M1C)7JS +658)2HR +QVN)4HK +6D4)NGS +XNV)GH6 +DKJ)1CT +PCP)JSF +DRN)YOU +88J)QVN +Q4W)658 +LGP)FQG +SWF)DYZ +DRD)PSB +G8Z)HTG +LVD)HWB +D3D)63H +S94)FKM +26M)RQ6 +Y7X)89R +CPY)BZB +4WQ)1ZQ +XNR)XGT +221)8W7 +T53)KP7 +3K3)RLH +FR7)8ZB +QG8)KRN +G1Z)2ZS +GD9)455 +9SX)3NC +WTV)9T2 +D61)F1L +VSJ)2SB +M8D)7VD +CV3)TVK +TVX)VJV +7P1)28Q +69P)DLZ +VYR)83M +VQS)3Y8 +W34)LV2 +Z9S)6KV +PFV)GHF +YKB)CXY +8NK)GL1 +NWF)KJB +SXP)JNL +JCY)DFT +SKS)W7D +P19)BJC +MW3)WPW +SPV)HVT +S5T)KVN +3HW)C92 +6HZ)W74 +1JD)K41 +CFT)WSS +61T)27F +4GH)Z8K +D27)7H9 +78F)TV5 +HFX)NWP +RHS)DQL +819)4V3 +RGW)738 +Q4Y)T21 +RRF)248 +MK7)D9X +55F)QFS +8M8)NM2 +J4X)LFH +B1J)T6K +4F6)PZT +WN1)9WR +VXM)3K7 +7RC)NW1 +TF2)9CM +59Y)6WQ +G7T)BF5 +Z4Q)JKJ +ZCD)LT5 +2QP)MRX +6TM)D79 +14T)KBG +RHS)9KD +7JS)Z4Q +XVN)B1D +Y7X)17K +DRD)Q9Q +3MH)BXK +TCW)9TC +9R4)NBY +7ZG)B4M +PPH)3LC +9KD)VRQ +91T)KSX +FS2)3S9 +2WF)TWT +PQJ)FQT +8D8)ZGV +1ZV)FN2 +4TB)LDQ +JDY)6N8 +35N)756 +WPZ)V5R +HYH)QK8 +JCS)JL9 +1Z8)MPR +JPN)8W4 +34C)85G +FNG)F35 +B3T)819 +PLQ)138 +VBJ)JTC +JB3)FS1 +62X)LM8 +FZP)4SH +1P7)LNM +JZP)56P +1QR)SQS +VRQ)LMV +WZG)7B1 +KPG)N3V +4C6)VQS +JQQ)MDR +YCZ)69P +RB8)9H5 +23R)9JW +7XH)WRC +JZ3)TYF +5SG)1CH +JNV)HCX +312)QJG +4T1)NS1 +64L)N1L +6NK)LC1 +4WQ)FN6 +BKF)68D +GB4)K95 +HX7)JPN +W2M)6QS +JSG)91T +TP2)CWM +NP1)S94 +3Y8)KWK +2NM)ZJ5 +CBG)JC6 +KJB)ZPJ +XPM)TF2 +BR7)L7C +SHB)PY2 +PMG)F33 +2F1)Z36 +SS5)9K7 +73F)PL9 +6TH)9LP +9MY)WHF +63W)Q98 +YSP)DY7 +4WD)Z3C +VCV)FNF +QSW)PJZ +PV4)9VL +NY1)H37 +D81)NRC +XYM)GP4 +JX4)LKF +K81)FG6 +HMD)W34 +DYZ)8KY +DY7)6WF +8GC)ZDL +WSS)X88 +DVV)R1B +BB7)1DN +3NC)7S4 +C12)TNS +L2H)14T +Y3P)92P +W58)44W +MCB)YPZ +XQZ)DJH +KQZ)MN2 +9WR)KCD +2JM)D5L +5Z7)9B7 +QKY)MV1 +K41)QKY +VTF)BQ9 +NDZ)QNJ +BGN)PJJ +P77)6YV +HT2)YWK +PPJ)CQX +H83)QSD +VSV)Z8D +LXN)QG8 +R87)3DM +W6H)ZGN +MKN)GD9 +3J7)1V9 +7FW)GQZ +63H)WV5 +1PJ)5HM +S88)SQ6 +XCH)PXL +MSH)ZMH +RR1)XJ8 +NTH)67R +BWD)F1S +JF8)9G7 +DYL)TNX +W34)NVK +8K3)53B +75S)DVW +4QX)3DS +RSW)HQ1 +3HS)F2Q +B4H)DX6 +6JX)HQL +SV5)ZFX +KJ1)WJ6 +89R)84D +FJB)QYY +K5S)55J +F3G)WY8 +1CP)JTF +WT9)LF9 +9TC)N8L +FBP)R5D +57B)D61 +XSG)3WX +675)WHT +B33)VYR +K2H)3PN +8ZB)SLB +C1F)LLG +3PN)5FH +QKP)HL9 +G9S)3QY +ZQF)F4T +FXM)517 +L74)2HK +V31)QJ3 +DDG)PY6 +3YW)6XG +CXD)TBD +K8W)J6H +BX1)VS9 +LVJ)331 +B3J)4TY +3S9)FRD +CZ9)QD7 +718)SMJ +53G)S8B +LR3)W2M +FRG)32P +VBB)23R +JM7)JY4 +3GM)HLB +8HG)BCY +CLV)WKS +CFB)MW3 +8KY)FQM +3N4)SD9 +C3T)DZZ +75P)Z8Q +MP2)VTS +CW7)PZD +GSV)TJJ +5G8)WPZ +45D)RGW +VXC)2YG +GLD)Y35 +L7C)P18 +PSB)PFS +QPM)6R2 +1NB)BKF +787)754 +KRC)B4D +N5Q)DGP +718)B5P +44C)ST4 +XVY)45K +WPB)VSB +PKL)1WV +7DG)37F +QF5)QRB +QC2)MK7 +KPZ)3SC +8M2)LXX +VPZ)45M +V5M)34C +JMQ)ZB6 +B4M)G18 +D6Y)DYT +LFD)B9S +R84)72H +XP4)L74 +H37)BDG +ZTS)NBK +QKC)G3K +7W1)FV4 +16P)M37 +ZSC)XJL +B1D)VBJ +RW8)5X5 +4D2)54L +212)WZG +NY3)TB2 +LR3)6D4 +KYJ)Z52 +9CM)98M +RDB)LHB +W48)V9J +69X)ZFL +45M)NV5 +54Q)QK1 +P18)B38 +QPD)1WG +4DX)9HZ +JC6)598 +LHT)8XB +WKY)VMF +RDV)PMX +XLJ)LRG +MPR)N15 +C9Z)FKC +LZ5)C2K +MW5)TFF +FV4)9BW +2RJ)K8W +9GR)18Y +1LD)JGG +82Z)HKD +7JS)4HT +7NC)CXB +2VZ)YL1 +PQR)JWN +HZP)SV5 +212)42H +QGD)J6P +D5L)6NK +XP7)6TM +18Y)D48 +4TX)4NG +NZJ)ZSC +WGD)QWY +NX4)66X +2MG)BCF +PSV)FVJ +GD7)QC2 +DLZ)542 +2W1)DRN +1WB)P6H +KTF)H5W +Y8J)9ZH +JWB)PYW +1DN)ZG6 +4MX)TSC +5BF)PYB +SLL)KSW +RGR)4CS +9T1)T26 +7H9)3SR +BRP)TD9 +B73)C5P +BXK)VN8 +4KT)6X5 +B65)BTV +N88)2V5 +P2F)6SB +PYW)QTV +MJY)684 +JSF)P77 +LP4)P4J +LKF)RNH +SSB)3VB +D75)F2D +SD9)HDZ +S46)1L7 +QYY)638 +XJJ)HJT +R5D)Y72 +TXH)VN5 +WLD)HT2 +DLC)36P +WS3)XLF +HKD)V9F +CKB)2YZ +57X)RX9 +YKM)DTB +4PR)G27 +T5W)55F +PZD)JGT +4CT)8FR +HL9)W5B +HWD)MW5 +XT6)2ZH +BQH)9C8 +MY9)HV8 +X5S)RDN +VSB)16C +X86)3HW +84D)26M +MS5)M1C +6X5)NWF +9XS)L8X +8R5)DXZ +3KX)6B7 +S99)VWV +5PV)D89 +FTS)8GR +STY)9QL +Z4L)6KM +ZN3)Z27 +9G5)9F4 +7YP)167 +KF2)PX2 +72L)M4Y +BSL)424 +Q7C)M4Q +9GP)FJB +SG6)NP1 +SVQ)QKC +J3D)X5P +KFR)RR8 +216)HMD +KXN)93W +Y8V)QGD +Y8V)PV4 +248)LVD +WFP)G1T +NKZ)SNJ +CX5)PSV +QWD)THG +J6P)C1T +HV8)PMQ +SGJ)MD4 +K3D)4Q2 +6R2)Z32 +KH9)72L +9QQ)JR3 +B9P)4T7 +RNH)154 +6HQ)BRP +HP9)WPB +HGG)7DG +27F)VSJ +LW1)NWL +GD7)LW1 +LWN)6TH +9L1)TLR +V7Q)3G5 +5P9)J3D +B3N)XQT +S59)5QP +JR3)BW2 +2KM)R2V +6KM)FNG +6Q8)H2B +CHD)RRQ +4S5)7FY +289)MWB +73H)Y3P +HYW)TXH +X6L)XZX +6YV)2YJ +ZFL)4T6 +MM1)JX4 +63K)6D5 +P8G)Z9J +NBY)Z4L +DCT)LPH +STQ)ZPT +MCZ)VPZ +KSX)YNK +T6K)26J +WWV)216 +LJW)Y3S +W7D)VWC +4SH)8MM +NBY)6TD +5HM)KQ9 +XP9)MQX +YSL)3Y4 +NL2)DYL +19L)8K3 +RZ1)9VC +QVX)WVR +9F4)Q3F +2K5)N4X +RF3)NHN +WRC)G1G +P8R)7TL +XJ8)K6F +5CZ)281 +B2Q)DG5 +5YC)XK3 +92K)DWK +9ZH)YTR +VWC)FQP +BFM)B65 +Z9F)PDP +8FR)6G7 +RDN)CHD +XP3)RGR +WVR)MMB +7LB)5MB +789)XCW +V3L)19X +689)2NM +7DR)GLL +RDV)Z4K +HBH)F2Y +HW4)B4W +Z81)P8G +XZ1)VYN +T26)KDJ +RCM)P2F +F1Y)TCT +T8D)V2B +HV1)QPD +KL3)CRS +WY8)R42 +9VX)675 +6KN)LQQ +LHF)NY1 +98Z)2VN +3KG)JZP +HHZ)2T6 +Q44)5JZ +4HT)QF5 +9C2)FH4 +KFR)W9V +L7G)4Y2 +GHC)L2H +26J)YR4 +D9Z)XP4 +CRS)8MG +J9B)P91 +J1C)8KQ +CCR)M6M +B52)PQC +HLN)RSY +QHM)G64 +BWR)47B +G1G)8GC +X6L)3TF +FSG)7NN +LF8)7FW +WMD)WQQ +45K)2MG +MMB)JJ4 +3DS)XVN +M2L)2X4 +ZYF)4JR +MV2)Y4C +PDP)JGN +GWG)M2W +XQT)DC1 +6QS)C28 +KRT)DMY +NS1)L5X +FY4)SK4 +ZPJ)HWH +R39)PPQ +J67)KNT +DZ6)W48 +626)DGK +4T7)VLZ +HTJ)GLD +PXL)PRZ +DCW)WHP +TDG)RDV +GF6)F7V +49C)DZ6 +3YR)5PR +M8N)64L +WHK)62X +1WV)788 +ZPT)4MX +NV5)58L +9WY)8K9 +ZT9)D6Y +MKN)S43 +Q65)Z73 +QPL)XVY +X7B)NDQ +153)BDX +R2V)395 +YWK)N34 +ZMX)GX4 +3DJ)X11 +RHM)2VZ +P3N)366 +ZRZ)6JX +559)662 +WZ4)C8M +KC4)VQC +FS1)B3J +72H)YWP +H8L)TP2 +QK9)XXQ +PL6)6PM +32W)P8R +YSV)4TX +PY2)VD5 +LHB)4PR +R1B)J4L +36B)9NC +FXF)4K5 +QPK)C3T +VYN)VSW +4NG)J65 +BZ8)LWN +P5G)HJW +2Z7)BX4 +BSK)16V +S7S)9YQ +TNS)5SG +B3C)QK9 +KQ9)9L1 +VLZ)7Q7 +4PP)F1W +2NG)F8R +JH3)63W +87R)KMF +YPW)YGC +F1L)BBD +QLG)NH3 +S1H)K7Z +F2D)DN4 +WJ9)BMS +P7C)5YC +428)HBF +2HK)75P +7S4)RT8 +D48)PL4 +B73)B5R +9L7)1JK +3G5)P7C +B8P)BB7 +6G7)K2H +598)V3L +QBZ)BR7 +GQ5)HYW +RLH)DCD +BD9)CMV +N34)J18 +3V7)KFR +6N8)4J3 +J6H)QHN +JGG)F6G +WJ6)X5S +KSJ)D81 +662)VCV +4XT)B1J +JWB)SXX +XN6)XLJ +LFH)TFP +RT8)Y5D +QKY)LY5 +PYB)FD7 +F1F)WDL +CWM)RL5 +RR8)C8B +18B)PWN +F35)3HS +B9S)7D4 +5BD)X79 +TGJ)9HF +NNJ)235 +DTH)NDS +GLL)CPY +138)RXP +X9Q)LHF +WNV)DF5 +19N)46N +QKV)BYV +7TH)JNR +GL3)288 +66Q)YYR +SK4)4VH +QNJ)XQZ +7CC)278 +BDG)T8D +WBM)YMW +NCW)RHM +2V7)YGW +PYB)XSG +RX9)YMP +BCY)J1N +JZ8)5CZ +362)QVX +517)QPM +K74)3WF +G9V)MHQ +Z8Q)CJ2 +69M)54X +STB)CHC +VSW)GWD +CMV)XTB +17H)XNF +CXG)HNZ +HNR)LVJ +S5B)QJR +Z73)6MM +WQT)7QR +P6H)VHY +BZ4)B33 +NM6)DKD +9KV)419 +235)G2V +K71)6MW +T8Q)Y62 +68B)Q3S +8MG)68B +FSQ)3GM +4XF)WJD +FG6)36B +DYZ)XDF +BX4)XV7 +77F)WQR +JTC)HTJ +YZC)MVQ +LM8)2B6 +ZB6)SXP +PXC)5TP +F6G)5FM +G18)4WQ +R4M)HFX +HMP)2QP +Q1L)2RJ +QRB)9G5 +YJZ)STB +3FH)3K3 +356)DKJ +5GR)27Y +BNQ)NC3 +36P)G7T +YN2)HYX +P76)39D +PJS)YQX +C76)C1P +27Y)65Z +HVY)37H +462)16P +N8L)Q44 +FQM)BWD +54L)DQH +455)P1T +5GF)6JL +JWR)WFT +FG7)H2M +DBT)J9B +Q72)6KN +756)BNQ +MQG)HNR +HDV)VGH +FKM)MXF +6PM)V7Q +HPC)QWD +G5M)Z1T +FRD)8ZS +ZPH)7TK +KV4)NLS +7QR)7NF +RL5)JH3 +CPS)1HR +BDX)B8P +ZB6)XVB +CS6)YXP +W6C)C42 +STY)ZXK +WXD)2TR +KNT)J76 +XQ8)GQG +1HR)D75 +MLH)56K +PFS)X2B +FVB)W7K +6YQ)82Z +RK3)XFT +NRM)SG6 +9QL)VTF +9TC)61T +6RM)5GG +8MM)H3Z +SGC)KZ3 +7Q1)Z71 +HGL)FXD +B69)4XT +N1L)YQ2 +QV6)YCH +K3N)KNV +68D)BSL +Y4C)HPL +VDZ)WXD +C5B)6SR +PMQ)NVZ +M35)NSK +B4W)QCQ +6FC)1GM +7TS)N9B +FN6)BKJ +9H5)QL9 +KDJ)DCV +LPH)W1G +BQ9)SD1 +4Q2)KSQ +6WF)4YZ +M1W)5GF +HYT)WVG +HDZ)VBQ +DZ6)VSS +YTR)428 +T72)R8V +F1S)C8R +1FD)4ZK +41J)626 +658)6CN +HZ6)FNK +FKM)1Z8 +6KV)NZJ +F33)DJ1 +XTB)TSF +NXV)RYS +F1F)5MF +YGW)2Z7 +MC2)CCR +3YR)GSV +XQK)XP7 +M97)PL6 +1CP)9ZP +N8J)C9W +GQZ)L6B +HV1)SYH +9VC)VZP +QD7)5GC +X2B)VT1 +92P)T5L +XCW)WKY +MY4)3J7 +MGN)3VL +K7W)8R5 +HWH)BT3 +4PV)9R4 +FVJ)5BJ +5MB)18B +F8R)7RC +MGN)N88 +1CH)ZPC +X88)YN2 +Y8J)7C2 +1H5)R53 +BMJ)SV7 +LLG)G7X +9LP)M97 +ZDL)B6H +5WZ)MV2 +RVG)442 +W3R)CCX +73K)L33 +17K)HGG +LC7)GNV +Q27)Q1L +2HC)V2Z +HXX)KC4 +6WQ)JCL +T92)M8D +KNV)6FC +T9B)559 +RKY)DBT +RRG)LRM +DSQ)PCQ +KF5)6YQ +R8N)FXM +JL9)KQK +RCK)3P3 +8W4)XBP +TNL)XYM +4NG)Q26 +JX3)Q27 +GX4)8QH +GTC)GD7 +LMV)XQK +YZ8)2MX +YL1)PFV +VHW)WT9 +S99)58S +13Q)NDZ +LHB)LHT +FQT)S59 +DX6)RWL +288)MP2 +2LL)4H2 +ZPC)GTC +HLN)4RR +22J)9MY +FH4)19L +NF3)KRT +JCL)DGR +GSX)FSG +TG1)X7B +NHN)S46 +FZP)P5G +S66)XTQ +WQC)G1P +XNT)QSX +V14)673 +TLR)B9P +2YP)ZPH +FKC)VFR +56K)QHM +B9W)133 +TNV)P2L +9NX)F98 +8KQ)5VP +5PH)FY4 +6VK)S1H +ZZM)M7R +PLQ)MXZ +GFY)RW8 +758)78F +FQ1)JCY +WV5)W58 +F3G)XPM +GLX)GL5 +LQB)7BS +Z55)GQ5 +THN)KH9 +5GG)V31 +G1P)FR3 +XFC)K5S +HQ5)XBH +HJT)FRG +VSJ)MB3 +VHY)FQ1 +VL1)RDB +L33)1NB +M6M)LXJ +BCF)J67 +6WT)B69 +FQT)R6B +L3S)HS1 +VSS)C5B +9FD)G5M +P2L)GCB +L5X)1VY +26X)5Z7 +4D6)LWG +8DZ)WT6 +XWG)V72 +QJ7)M1Z +58S)HMN +HJR)QY8 +L7S)ZYF +MR5)5PV +C8B)WFP +QK8)1TX +J12)2V7 +J76)RS8 +6MV)WJ3 +16C)HLY +4TY)73H +H6D)XQ8 +4JR)MX5 +M37)Q65 +W74)XX9 +TK5)49S +B6H)BZ4 +F6N)BKV +JF8)ZTS +WBS)4LS +LTH)J42 +JNL)6WT +GL1)5Q3 +XJL)KVB +YMW)MM1 +9HF)356 +5QP)7XH +K95)KJ1 +QWY)8W6 +KPN)J1C +RRQ)XNV +419)XMQ +YYR)9RZ +1CT)KLZ +8XQ)V5M +XGT)ZN3 +WZ4)G8Z +YWP)3MS +93W)18V +7FY)M8N +TFP)NM4 +FR3)7N4 +JGN)NF3 +JDY)1P7 +M17)WS3 +SLQ)RVW +DQJ)XR9 +FNF)89K +YKH)KKH +K6F)RPD +J75)9GP +2X9)DLD +6CN)7W1 +7TK)MGN +2SC)3KG +BMS)MQG +ZFX)53H +Z3C)LT3 +VDN)GRY +6JL)9Z9 +7NF)PML +14T)WSX +1V9)N7N +N3V)HPD +F53)PPJ +DQ9)TNL +JPH)1FL +L1C)WBS +RMY)BMJ +MV1)1CP +4GY)8M8 +CGN)4GC +7B1)26V +8QN)JSG +VQC)XRT +J1N)MKN +PYS)289 +7Z9)HDV +SJB)4C6 +LX3)HX7 +94G)R1P +DY7)D6W +3FH)2RV +XKS)WHK +FNB)6L2 +K6Y)NK7 +BYV)Z9F +QBZ)FVB +C5B)73F +6SC)DMP +B5R)K3N +BKV)YKB +VW8)1FD +PWN)QPL +DG5)BQH +1MD)YCZ +KWK)CZ9 +JY5)NX4 +F2T)8QR +RYS)KF3 +LRM)M1W +LXX)CD1 +98M)J4X +D6Y)M17 +97S)BSK +X11)2X9 +WKP)57B +CCX)221 +GJM)T5M +LT9)7YP +RVW)FZP +62K)CLV +3VL)QQK +3XD)HQ5 +W3R)QFC +8JW)32H +KCD)2HC +SND)9FD +4PR)D3D +Q68)77F +56P)87R +SD1)RHS +COM)2WF +Q53)HBT +ZJ5)68M +4VH)VDN +Z36)2QN +FD6)R96 +NWP)HZP +4T6)LGZ +QTV)GF6 +S2P)HZ6 +XFC)S8R +2V5)QDH +PPQ)CD6 +Z71)YKH +RYK)864 +VMF)MZQ +KZK)KTF +KZK)XKS +SLK)WBM +HWZ)CX5 +N1L)2HF +54X)JWR +TYF)YY5 +3DM)264 +FLG)FBP +D2J)376 +2RV)JPH +PMX)12Z +CLB)7TS +CNC)RCK +281)8M2 +2SB)R4M +KF3)1RN +B38)4FG +GV9)XV5 +33M)676 +QGN)HS2 +7D4)GFY +4CT)STK +N15)R1V +29B)Q4W +DXZ)BV8 +563)GLX +XDF)GRS +1LQ)TK5 +BPW)C93 +KP7)GLH +2X2)F24 +YTR)LT9 +MN2)NNP +W7K)TF6 +DGK)KPN +D6W)PVB +67R)3DJ +TB6)NLV +MDR)PLQ +C92)3NQ +F8D)1P3 +4ZK)T9B +347)JJY +XNF)6HQ +QKK)63K +B4H)HYH +TCT)GFD +CPW)5MK +BQ8)789 +SGD)R84 +CBM)7XL +NKX)4TB +9K7)GTS +VWL)3V7 +M1Z)7DX +XXQ)W69 +676)Z55 +1NP)GW9 +HYX)Q7V +YY5)5WZ +7PK)Q12 +2VN)GWW +NC3)SXB +H5W)V14 +PQC)CPM +JVM)RZL +WQQ)R87 +YQ2)JCS +3SR)MF9 +RPG)BZ8 +L36)CDK +6WT)KSJ +QSX)9RM +STK)JM7 +DPL)CXG +8DZ)FNV +R96)7NC +C5D)SAN +1FM)4T1 +FXD)KCT +K7W)347 +C1P)FS2 +C8R)Y4D +F35)Q4Y +3Y4)Q53 +WHF)212 +RMZ)TVV +DKM)Y8V +395)C76 +65Z)JF8 +4LS)CFB +BJC)132 +P4J)WDH +QQK)LCT +TWS)LP4 +Q6W)XJJ +GRS)JDY +1WG)G46 +PCQ)X9P +12Z)41J +JF4)LXM +F98)2LG +DQH)15P +DTB)9L7 +6XG)8D8 +TKW)2JM +X5P)M35 +154)CGN +7LW)KRQ +KCT)57X +9BW)QGN +GHF)D2J +Y72)HW4 +4V3)LFD +ZXN)T3J +W5B)L7G +NP1)JGL +6L2)J3G +6B7)NTH +DFT)DKM +GP4)HXH +FQP)THN +XQ3)QPN +H2M)ZCD +37H)1RM +MQM)BDT +Y5Y)PZB +WT6)B3N +R7V)MSH +2T8)T53 +3WX)WZ4 +WHP)69M +YFS)NF8 +G3K)4TG +V2B)3YR +5HM)CLX +5HK)75S +HC5)SLQ +55M)KPZ +KKH)4CV +B65)SJB +TFF)1Y6 +5Q3)HJR +MVQ)MCB +12V)757 +YQX)V73 +9C8)JN8 +DYT)5PH +C8M)69X +VGH)S5T +TNX)CXD +XK3)TVX +1L3)7RX +662)B3T +RTT)KQZ +21H)RMF +ZQF)2YP +8ZS)7DR +X8C)GY8 +HNZ)JPZ +133)1NP +PJJ)CPS +18V)RPG +9NC)STQ +J1Y)3MH +6SR)B73 +HPL)41V +YMW)BPW +RDJ)KN3 +LXM)P76 +42H)9W9 +CCD)W8T +176)S7S +B41)G6R +KLZ)P19 +SQ6)XFC +TF6)H89 +2FV)8DB +4Y2)4D2 +JTF)TKW +LDQ)X6L +LT3)T3K +QK1)GB4 +W4N)7Z9 +BKM)7CC +65H)S2P +8K9)YJZ +253)9WY +KVN)4PP +2Z4)F3G +C93)KTW +5FM)QSW +F24)4DX +T3K)NR8 +3G7)RKY +V73)6MV +BT3)2F1 +HLY)CCD +GLH)94G +2CZ)W2J +NSK)NC8 +V5H)M41 +19X)NXV +QMQ)54Q +LRG)Q48 +7CQ)YB2 +TSF)8XQ +FCS)2VF +16V)VXC +HBZ)WGD +VJV)JY5 +XRT)J2X +424)5GR +SXB)XJP +BJC)5PJ +SND)49C +LC1)8Y7 +FR7)L6J +H2M)XHR +BW2)C9Z +2HW)185 +TYL)2K5 +15P)6HZ +LK7)YZ8 +JPZ)NNJ +NGS)G3S +GL5)QVR +DJH)NZ6 +GKB)9S3 +JCX)Z42 +P2S)T92 +9ZN)ZCY +PY6)DVV +YP3)W5Z +11M)WQT +PQ9)G3Z +2S1)SPV +CQX)ZQF +YPZ)LQ9 +VRQ)TZ9 +GY8)26X +985)YQ3 +9ZP)9RP +9JW)VL1 +4MX)33M +L6J)L3S +KBG)P3N +G22)RPQ +948)1FS +3KS)CW7 +WCV)WNV +LB9)KL3 +BDT)21H +Q53)VB9 +HCV)2CZ +7RX)TQM +4GC)LDV +PL9)N2M +1VY)NL2 +R96)153 +37F)53G +VT1)KF4 +61T)838 +HBT)R4N +H81)TB6 +1FL)FR7 +J65)D9Z +8Y7)22J +KZ3)JFL +W5B)B9W +G27)QJ7 +V72)1MD +5G8)J12 +T39)STH +6JL)HCV +SK4)K6Y +Z1T)2FV +PPJ)LJW +JKJ)64J +47Y)QGH +N1V)CVT +PJQ)TWQ +26V)QMC +5Y3)1QR +F1W)VXM +49S)QKP diff --git a/input/day_07 b/input/day_07 new file mode 100644 index 0000000..d16f8ef --- /dev/null +++ b/input/day_07 @@ -0,0 +1 @@ +3,8,1001,8,10,8,105,1,0,0,21,38,47,64,89,110,191,272,353,434,99999,3,9,101,4,9,9,102,3,9,9,101,5,9,9,4,9,99,3,9,1002,9,5,9,4,9,99,3,9,101,2,9,9,102,5,9,9,1001,9,5,9,4,9,99,3,9,1001,9,5,9,102,4,9,9,1001,9,5,9,1002,9,2,9,1001,9,3,9,4,9,99,3,9,102,2,9,9,101,4,9,9,1002,9,4,9,1001,9,4,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,99 diff --git a/input/day_08 b/input/day_08 new file mode 100644 index 0000000..2346e26 --- /dev/null +++ b/input/day_08 @@ -0,0 +1 @@ +222222222222222222221202222222222122222220222222222222222222222222220020220211022202212200200222202022222202222222222222122221220220212222222222222222222222222222222222222202222222222222222220222222222222222222222222221020220201022202212211220222212022222212222222222222122222220221212222222222222222222222222222222222220202222222222022222221222222222221222222222222222220220200122212212221202222222022222222222222222222022221221221202222222222222222222222222222222222221202222222222122222222202222222221222222222222220220222200222222212222200222222022222212222222222222022222220221222222222222222222221222222222222222221202222222222122222220210222222222222222222222221122221220122212212200212222212022222222222222222222222222022222202222222222222222221222222222222222222222222222222122222222211222222222222222222222222121220221122212202222220222202022222202222222222222222220221222212222222222222222222222222222222222222222222222222122222222202222222221222222222222221120222222222222202212222222202222222202222222222222022220220220222222222222222122222221222222222222222202222222222022222220211222222222222222222222221020221212222222222220200222212022222212222222222222022220022220202222222222222222222220222222222221220222222222222222222220221222222220222222222222222121222202122222212202200222222222222202222222222222022222122221202222222222222122221222222222222222220212222222222222222222210222222222222222222222222121221222022212201222202222202122222222222222222222022222022222212222222222222222222222222222222222220222222222222022222221210222222222222222222222220220221200022202200222202222222022222202222222222222122220021222212222222222222122222222222222222220220222222222222222222222222222222220222222222222221022221220022222221221211222212022222222222222222222122220021221222222222222221022221222222222222220221212222222222122222222220222222222222222222222221220221212022222201201202222222222222212222222222222222222021222202222222222220222221220222222222222221202222222222222222221201222202222222122222222220121220211022222210202221222222222222212222222222222022220022220202222222222221222220220222222222220220222222222222022222222212222212221222022222222222120221222122222201200220222212012222202222222222222222220121210222222222222222222221222222222222222221202222222222222222221212222202222222222222222222221222201222212222210222222202212222202222222222222122221220220212222222222221222220220222222222220220222222222222122222220212222212220212222222222221121221222222202202200212222212102222202222222222222222220022211222222222222220022222222222222222221222222222222222122222220220222222220222022222222221222221210122212220220201222202022222212222222222222022220221222212122222222222222222220222222222222221212022222222022222222202222222220212022222222221121222202222212211200202222202112222222222222222222022221122200222222222222220222220220222222222222220202022222222022222220210222212020222222222222220120221200222222200222201222202122222212222222222222022222221202212222222222220122221220222222222222221202122222222122222220212220212020212222222222222022220212222202202211202222222222222222222222222222022222021221212122222222220122221221222222222222221202122222222022222222222222212220202122222222221022220220222212222202211222222022222222222222222222222220221211212022222222221122220222222222222222222222022222222222222221202222212220202122222202220221220201022222221211200222212212222222222222212222122221221201202122222222222222220220222222222220221202022222222022222222220221212021222222222222222121221202022222211221221222212002202202222222202222220220201211202122222222222022221222222222222220220202122222222022222221210221212220202122222222220020220211222222222220200222222012202212222222202222121220221211222222222222221122221222222222222221221212022222222122222222211220222121202122222202222221221202122202222201212222222102222222222222222222121220022221202022222222220022220222222222222221221212022222222222222220202221202222202122222212221120221221122202202220201222222202222212222222212222122221101202212222222222221222220222222222222221222202022222222122222222220221212222212022222202222021220212122202200210202221202202222202221222202222020221020212212022222222221022221222222222222222221222022222222222222222212221202222202222222202220220222212122202211222220222222012002202220222222222021222110202212122222222221122220221222222222222122212022222222122222221210222222221202022222212221222220210222202200220212221212012212212221222222222020222121220012222222222220222220220222222222220121212222222222222222222202221212222222222222202221022221210122202220222221222202222112202222222202222220221220220222122222222222022222220222222222221122202122222200222222221200220222220222122222202221221220201022202222210202221222112122202222222222222120221210222002122222222220122220221222222222221022202222220222222222220220221202220212122222222222120222200222202212200221220202002122222221222202222222222000220202222222222221222221222222222222220220212022222222022222220201220212220212122222122221021222202022212202220222221222202112202222222212222122221200222112022222222220122222220222222222222021212222220222022222222202220212122202222222212220222221212222211202210200220202112212212220222212202120221002211102022221222221122221221222222222220020202022222202022222221222222202122202122222202221120220220122201210222202221202122102222121222202212120222122202112122220222221122220221222222222221120222022222220122222220201220212221222022220122220121222212222201221202201220212122022212221222222222122120111221102122220222220222222222222222222221121212222220222021222221220222202020202022220112221122220202222220201220222220022012122212020222202222020120112212222222220222221022221221222222202222021212122222201122222220222220222222212122221022222122221202122200200201202221112222102212120222212212020122000200022222221222220122222221222222212221222202222222112022222222200221212220222122220002222122220221002220220212202222002002112202121222222202120220002210112122222222220122221221222222212220122222222222022020222221002220212120212222220012220021222211102200202211212220122002002212122222222212221122100200002022221222220022221221222222202221121212022222101222222221220221202020212222222212221020220201102221220222201221002012102212121222222222020220202212222122221222221222220222222222202220022202022222010222222221112220202220222222201002221220221210022222211222220222122002022212021222222202221021002220212222222222221022222222222222222222220202222220202022222221020221202222202222222012220120222200012220200222210221102102122212220222202212020220111220012222221222222122220221222222202220221212022221201122222220202222222020202022220122220022222211202202222211220221002012022222220222212212120020002210202222221222222122222221222222222221121212022221011120222220121220202021202122222112220120221201012200222200222221202102022202121222212212120021120220112122222222221022221220222222212221222212222221100121222222102220222021222122212122221220222200002222200221202221202002022222021222222202022220121221112122221222202022221222222222222221122222022221120122222222010220222120222022211122221120222212222211211202211222012012022202022222202212022022110211102022221222212222222220222222212221022212122220012022222220210221212021202222201002220220220222122220221211202220122122122212020222202212021221212202122022221222212222210220222222222222122222222220021222222221211221202220222022201012221020222211012211210211200220212022212222222222212222122122211200202122221222202022212220222222222222221222122221012021222221101221202021202222222112221020220210002221221222201220002122202222220222212222122120100200222222220222200122202222222222212220222202222221212121222222000220212020202222221102222020220200022220202222222221202222002202220222222212122222221211122022220222222222222220222222222220020222122222210222222220022220222022202022200002221121220201022222220221200222222012212212022222212212220020012201202022222222211022202221222222212220021202122220011021222221222220212120222222202022221020211202012202222200221222112012122202221222222202020020222222202022221222202022210221222222202210021202122220221021222221101220222121222122200122222221221210012202201222212222212002012210121222212222020022211220212122221222210222200221222222212202222222022222210020222221100221212021202022202022220122222210002222210211201220022122112212121222212212121220110221212222220222202122210222222222222211020202122220121122222220121121222121212122211012221020200201122212220220220222012212122221122222002222120021012212212022220222221222210222222222222212122202222220210122022222022220222221202122211012221020220212102222202222212220002012122201022222022212020121022222222222020222211222210220222222202212221202022221201220222220222020212221202022202112222222220201222221212200211220202212112201021222202202122220101202212122222222222022202220222222202202220222222221212122022222012122212021212222210212221120201210112200222221222221002102002210120222022202220220112222212222221222211122200220222222222211220212022220210020122222012221202021222122210112221120222220002201211211201222212202102221021222012212222222201221002022221222201222212222222022222222122222122022021020122220021120222120222222222002221120212221112210211211202222222002112212120222112222021120220222222122120222221022210220222022202201021222122120121122022222221222222020202222212202220121202211112222200221201221212122222211021222202222222222111220112022220222212222202220222122212210021202122222002220022220201022222021222022201002221221222222112201211220210222102222222222021222012212121222210201202022120222221220212221222122212210221202222122222222022222020221202021202122201012222020200222022221221212220220202122212221220222102222021222201200022122122222212022200221202022202202222212222120222222021220210122222222222022200002211120222221212222201222221222212222102210021222102222220122121202212122120222212221222220222022202200121222122222121122221221111221222220222122221222212220222100112212201220202221202202112201020222112202020220002220002222022222221020211220212122202210020202122121102022220222221122212022212222202122211222201210022202201211211222212002002221222222122212120221101222002022121221201121221220202122222212022202222222020022221222211121212121222222222012201220211120012210200121211220112122022221021222002202220021021201112222022221212122222220212122202222221222022020202221220222001122212020222222201222200121212001122211202001201221122212222200220222212222020120010222112122220221200020202220202112212222022212022221221020120221022221222220222220221112211222200110012200220001200220112200102221021222222212221220010200022122121222220220212220222012102221120212122020122122222220202221202021202221200212201021220002122210200012211220212010102220222222100222122000220212002222221222222122212220202112112211122222222020212220120221110020222222202220210022201021222201121200201200222221112110002212121222200202020111020201102122222222211220200220222022122210120202022022210021220220221220202220222020222212211020220101010200220210202222222211110222020222111202021021121220112122220222211222200222202022022211222222222220110022122222011120202220212021220012220221221211011211211022210220222012101222120222201222120212022221202122122221210022200220012102012211020202122121220120222221102120202122201022222002200222202112222022220120210220112022010221222022012202222102010222222122021221212121100222002212102222020222222022021122221221020120222202202221211002221122202112100112221221212220222011102200221122002222022020100221222022121222200122021220022112212200120202022021110122220222112022212021220120220012212020021221001201200222221222012100022201121022102222120222221211202022020222200021121221222222022202121212022022101121122222022120202122211020202102200121011201101101220112210221002012010200120122002212021102001200210222121220202020220221112221202201020202222221212120220220102021202000210122201012212022112200002102202022210222022110202201022222212202020020001200022122222220212220110220222011122222122012022122010120022220220021222200212220200012220221201220102202202012201221202122212221121122210202020222022210021022122222212022112221222012012201021212122220112122221221011120222202220221200022201022120222001222200211200222202002120201122022000202020111112202010122222220022221202221012001222220020112022020022122221220000122202000222020211022221222112011220022212200212222102222212200201122122222120111110200020022122221111121102221102111012220122112222021121001220020201020212002221221200002210120120002102121200000221222012020010212011122001212220100122222210122120221120222022220002202112211122002222220222120221122110222102021200021200002210222022022000122212012212222122021102220121222010222021100012211111122221220201220220220122100012220120212022121101011221122120221212202200110221022210222112121121210222112201220112021210221122122201212121201120220000022002220122220001220012110012200121102122020122101221122010020022100211121201101220220012121210001200010200221222120000202120222100212220002011202221022110221000221110221012210122202222012222121121000120112120021102201202000220210211221202200001010220000220221012201111200011202102212022201202201122022121222002020202220022102222222221102122222100212021010010022222021221220202210200122021122212022220000201222022121000200010122110212122110200201001022000221222020211220001101212200122112022022201122221111220121122020201011111110211121212221221120210012210220222000100221200212111202022021112212121022101220001121211222220212202211121002122120012021020101110221112121212002012210210020020001001001222220220222022212001220022112210222222201022210210222120221011022110222202221022220222222022220101022122212200120222011210001222211200022122211121102212021210222002101200211012102221222020212222211011222201220010021110220022211002200221202122122202222022010111122102201221012211110212021011021012112222222220221112202002220210102101222120021010202001122100222012220101222122121222222020122222121000202121220000021002000202022101100202121222012111002200110202222122100010211010112022212222222101210100222112220010221112221112100202210020012222221012011121211012020022110210121100001221121222221222200210221212222202110000200221202220222020120122200200122122220111120020220122110002201120022222222212100022200221021012020211012110001221121112022022010202020222221222020212212202222122212020221120200110222002222221120001221112101022212020112122120121211001220012120122121211120211011210022022011211022221202200221122102012212122212212212121201011200010122202222111020002221010201222220120202222220210100102022211020202211211000211201220120020101101222222021222220202022112222210202100212022010221200100022120221212220000221121112022212121001022211122111121021221121001202222202101012220021222010120202210202211222112022010222100002000202221011112200011222110110011022212001101222100121200102110221210001100200101200210222022220112221102012121001011101001021100000121002021101222110221020101111120011201000211002201200 diff --git a/input/day_09 b/input/day_09 new file mode 100644 index 0000000..5fb48d8 --- /dev/null +++ b/input/day_09 @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,3,1,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,37,0,1012,1101,26,0,1008,1101,0,39,1016,1101,0,36,1007,1101,669,0,1024,1102,1,29,1009,1102,0,1,1020,1102,24,1,1003,1102,22,1,1013,1101,0,30,1019,1101,260,0,1027,1101,38,0,1018,1101,642,0,1029,1102,25,1,1004,1101,23,0,1017,1101,21,0,1001,1102,20,1,1010,1102,33,1,1015,1102,35,1,1002,1102,1,1,1021,1102,31,1,1014,1101,895,0,1022,1101,0,32,1011,1102,1,28,1005,1101,0,892,1023,1101,263,0,1026,1102,1,27,1000,1101,647,0,1028,1101,0,34,1006,1102,1,660,1025,109,9,1208,-7,38,63,1005,63,201,1001,64,1,64,1106,0,203,4,187,1002,64,2,64,109,4,2101,0,-5,63,1008,63,24,63,1005,63,227,1001,64,1,64,1106,0,229,4,209,1002,64,2,64,109,5,21107,40,41,0,1005,1018,251,4,235,1001,64,1,64,1105,1,251,1002,64,2,64,109,18,2106,0,-9,1105,1,269,4,257,1001,64,1,64,1002,64,2,64,109,-40,1208,6,35,63,1005,63,287,4,275,1105,1,291,1001,64,1,64,1002,64,2,64,109,11,2102,1,0,63,1008,63,35,63,1005,63,315,1001,64,1,64,1106,0,317,4,297,1002,64,2,64,109,6,21107,41,40,-3,1005,1010,337,1001,64,1,64,1106,0,339,4,323,1002,64,2,64,109,-2,2101,0,-8,63,1008,63,24,63,1005,63,365,4,345,1001,64,1,64,1105,1,365,1002,64,2,64,109,9,21102,42,1,-3,1008,1017,43,63,1005,63,385,1105,1,391,4,371,1001,64,1,64,1002,64,2,64,109,-4,1206,5,407,1001,64,1,64,1105,1,409,4,397,1002,64,2,64,109,13,1206,-9,427,4,415,1001,64,1,64,1106,0,427,1002,64,2,64,109,-25,2107,27,1,63,1005,63,449,4,433,1001,64,1,64,1106,0,449,1002,64,2,64,109,-3,1202,-1,1,63,1008,63,27,63,1005,63,475,4,455,1001,64,1,64,1105,1,475,1002,64,2,64,109,6,21108,43,41,8,1005,1015,491,1106,0,497,4,481,1001,64,1,64,1002,64,2,64,109,6,1205,8,515,4,503,1001,64,1,64,1105,1,515,1002,64,2,64,109,-11,1207,1,23,63,1005,63,531,1105,1,537,4,521,1001,64,1,64,1002,64,2,64,109,1,2108,24,0,63,1005,63,559,4,543,1001,64,1,64,1105,1,559,1002,64,2,64,109,12,21101,44,0,1,1008,1016,44,63,1005,63,585,4,565,1001,64,1,64,1105,1,585,1002,64,2,64,109,-23,2102,1,8,63,1008,63,27,63,1005,63,607,4,591,1105,1,611,1001,64,1,64,1002,64,2,64,109,18,21108,45,45,3,1005,1013,633,4,617,1001,64,1,64,1105,1,633,1002,64,2,64,109,11,2106,0,7,4,639,1106,0,651,1001,64,1,64,1002,64,2,64,109,-1,2105,1,4,4,657,1001,64,1,64,1105,1,669,1002,64,2,64,109,-10,2107,26,-6,63,1005,63,685,1105,1,691,4,675,1001,64,1,64,1002,64,2,64,109,9,1205,1,703,1106,0,709,4,697,1001,64,1,64,1002,64,2,64,109,-12,2108,22,-3,63,1005,63,729,1001,64,1,64,1106,0,731,4,715,1002,64,2,64,109,-11,1207,10,35,63,1005,63,753,4,737,1001,64,1,64,1106,0,753,1002,64,2,64,109,9,21101,46,0,5,1008,1010,43,63,1005,63,773,1105,1,779,4,759,1001,64,1,64,1002,64,2,64,109,-1,1201,4,0,63,1008,63,26,63,1005,63,801,4,785,1105,1,805,1001,64,1,64,1002,64,2,64,109,7,1201,-8,0,63,1008,63,22,63,1005,63,825,1106,0,831,4,811,1001,64,1,64,1002,64,2,64,109,-1,1202,-6,1,63,1008,63,23,63,1005,63,855,1001,64,1,64,1106,0,857,4,837,1002,64,2,64,109,7,21102,47,1,0,1008,1017,47,63,1005,63,883,4,863,1001,64,1,64,1106,0,883,1002,64,2,64,109,8,2105,1,-2,1106,0,901,4,889,1001,64,1,64,4,64,99,21101,0,27,1,21101,915,0,0,1105,1,922,21201,1,20897,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1106,0,922,22101,0,1,-1,21201,-2,-3,1,21102,957,1,0,1106,0,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0 diff --git a/input/day_10 b/input/day_10 new file mode 100644 index 0000000..9730f12 --- /dev/null +++ b/input/day_10 @@ -0,0 +1,36 @@ +....#...####.#.#...........#........ +#####..#.#.#......#####...#.#...#... +##.##..#.#.#.....#.....##.#.#..#.... +...#..#...#.##........#..#.......#.# +#...##...###...###..#...#.....#..... +##.......#.....#.........#.#....#.#. +..#...#.##.##.....#....##..#......#. +..###..##..#..#...#......##...#....# +##..##.....#...#.#...#......#.#.#..# +...###....#..#.#......#...#.......#. +#....#...##.......#..#.......#..#... +#...........#.....#.....#.#...#.##.# +###..#....####..#.###...#....#..#... +##....#.#..#.#......##.......#....#. +..#.#....#.#.#..#...#.##.##..#...... +...#.....#......#.#.#.##.....#..###. +..#.#.###.......#..#.#....##.....#.. +.#.#.#...#..#.#..##.#..........#...# +.....#.#.#...#..#..#...###.#...#.#.. +#..#..#.....#.##..##...##.#.....#... +....##....#.##...#..........#.##.... +...#....###.#...##........##.##..##. +#..#....#......#......###........... +##...#..#.##.##..##....#..#..##..#.# +.#....#..##.....#.#............##... +.###.........#....#.##.#..#.#..#.#.. +#...#..#...#.#.#.....#....#......### +#...........##.#....#.##......#.#..# +....#...#..#...#.####...#.#..#.##... +......####.....#..#....#....#....#.# +.##.#..###..####...#.......#.#....#. +#.###....#....#..........#.....###.# +...#......#....##...##..#..#...###.. +..#...###.###.........#.#..#.#..#... +.#.#.............#.#....#........... +..#...#.###...##....##.#.#.#....#.#. diff --git a/input/day_11 b/input/day_11 new file mode 100644 index 0000000..f56eb6a --- /dev/null +++ b/input/day_11 @@ -0,0 +1 @@ +3,8,1005,8,325,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,28,2,3,7,10,2,1109,3,10,2,102,0,10,2,1005,12,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,101,0,8,67,2,109,12,10,1,1003,15,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,1,8,10,4,10,101,0,8,96,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1002,8,1,119,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,141,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,1001,8,0,162,1,106,17,10,1006,0,52,1006,0,73,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,194,1006,0,97,1,1004,6,10,1006,0,32,2,8,20,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,231,1,1,15,10,1006,0,21,1,6,17,10,2,1005,8,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,1,8,10,4,10,102,1,8,267,2,1007,10,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,294,1006,0,74,2,1003,2,10,1,107,1,10,101,1,9,9,1007,9,1042,10,1005,10,15,99,109,647,104,0,104,1,21101,936333018008,0,1,21101,342,0,0,1106,0,446,21102,937121129228,1,1,21101,0,353,0,1105,1,446,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,21101,0,209383001255,1,21102,400,1,0,1106,0,446,21101,0,28994371675,1,21101,411,0,0,1105,1,446,3,10,104,0,104,0,3,10,104,0,104,0,21101,867961824000,0,1,21101,0,434,0,1106,0,446,21102,1,983925674344,1,21101,0,445,0,1106,0,446,99,109,2,21201,-1,0,1,21102,40,1,2,21101,477,0,3,21102,467,1,0,1106,0,510,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,472,473,488,4,0,1001,472,1,472,108,4,472,10,1006,10,504,1101,0,0,472,109,-2,2106,0,0,0,109,4,1201,-1,0,509,1207,-3,0,10,1006,10,527,21102,1,0,-3,21202,-3,1,1,21201,-2,0,2,21102,1,1,3,21102,1,546,0,1106,0,551,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,574,2207,-4,-2,10,1006,10,574,22101,0,-4,-4,1105,1,642,21202,-4,1,1,21201,-3,-1,2,21202,-2,2,3,21101,0,593,0,1105,1,551,22102,1,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,612,21102,1,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,634,21201,-1,0,1,21101,634,0,0,105,1,509,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2106,0,0 diff --git a/input/day_12 b/input/day_12 new file mode 100644 index 0000000..814925d --- /dev/null +++ b/input/day_12 @@ -0,0 +1,4 @@ + + + + diff --git a/input/day_13 b/input/day_13 new file mode 100644 index 0000000..a9a41da --- /dev/null +++ b/input/day_13 @@ -0,0 +1 @@ +1,380,379,385,1008,2399,462045,381,1005,381,12,99,109,2400,1102,0,1,383,1101,0,0,382,20101,0,382,1,21001,383,0,2,21102,37,1,0,1105,1,578,4,382,4,383,204,1,1001,382,1,382,1007,382,44,381,1005,381,22,1001,383,1,383,1007,383,20,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1102,-1,1,384,1106,0,119,1007,392,42,381,1006,381,161,1101,0,1,384,21002,392,1,1,21101,0,18,2,21102,1,0,3,21101,138,0,0,1105,1,549,1,392,384,392,21002,392,1,1,21102,1,18,2,21102,3,1,3,21101,0,161,0,1106,0,549,1101,0,0,384,20001,388,390,1,20101,0,389,2,21102,1,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,21002,389,1,2,21102,1,205,0,1105,1,393,1002,390,-1,390,1102,1,1,384,20101,0,388,1,20001,389,391,2,21102,228,1,0,1105,1,578,1206,1,261,1208,1,2,381,1006,381,253,21002,388,1,1,20001,389,391,2,21102,253,1,0,1105,1,393,1002,391,-1,391,1101,1,0,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,279,0,0,1106,0,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21102,304,1,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1102,1,1,384,1005,384,161,21002,388,1,1,21002,389,1,2,21101,0,0,3,21101,0,338,0,1105,1,549,1,388,390,388,1,389,391,389,20101,0,388,1,20101,0,389,2,21102,1,4,3,21102,1,365,0,1106,0,549,1007,389,19,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,318,20,15,1,1,22,109,3,22101,0,-2,1,21202,-1,1,2,21102,1,0,3,21102,1,414,0,1106,0,549,21201,-2,0,1,22102,1,-1,2,21101,429,0,0,1106,0,601,2101,0,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2105,1,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22101,0,-3,-7,109,-8,2106,0,0,109,4,1202,-2,44,566,201,-3,566,566,101,639,566,566,1201,-1,0,0,204,-3,204,-2,204,-1,109,-4,2106,0,0,109,3,1202,-1,44,593,201,-2,593,593,101,639,593,593,21002,0,1,-2,109,-3,2105,1,0,109,3,22102,20,-2,1,22201,1,-1,1,21102,443,1,2,21101,114,0,3,21102,1,880,4,21102,1,630,0,1106,0,456,21201,1,1519,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,2,2,0,2,2,2,2,2,0,2,2,2,0,0,0,2,2,2,2,2,2,0,2,2,0,0,2,2,2,0,2,2,2,2,0,0,2,0,2,2,0,1,1,0,2,2,0,2,2,2,2,2,0,2,2,0,2,2,2,0,0,0,2,0,2,2,0,0,2,2,2,0,2,2,2,2,2,0,2,0,0,2,2,0,0,1,1,0,2,2,0,2,2,2,2,2,2,0,2,2,2,2,0,2,2,0,0,2,0,0,0,2,0,0,2,2,2,2,2,0,2,2,0,2,2,2,0,2,0,1,1,0,2,2,2,2,0,0,2,2,2,2,2,2,2,2,0,0,2,2,2,0,2,2,2,0,2,2,0,0,0,2,2,2,2,2,2,0,2,2,2,2,0,1,1,0,0,2,2,2,2,2,2,0,2,0,2,2,0,2,0,2,0,2,0,2,2,2,0,2,0,0,0,2,0,2,2,0,0,2,2,2,2,2,0,2,0,1,1,0,0,2,2,2,2,2,2,2,2,0,2,2,0,0,2,0,2,0,2,0,0,2,2,0,0,2,2,0,0,0,2,0,2,0,2,2,2,0,2,2,0,1,1,0,0,0,0,0,0,2,0,2,0,0,2,2,0,2,2,0,0,2,0,0,2,2,2,2,2,2,2,2,0,2,2,0,0,0,2,2,2,2,2,2,0,1,1,0,0,2,2,2,2,0,0,0,0,2,0,0,2,2,0,2,2,2,2,2,2,0,2,2,2,0,2,2,2,0,2,2,2,2,2,2,0,2,0,2,0,1,1,0,2,0,2,2,2,2,2,0,0,2,2,2,2,2,0,2,2,2,2,2,2,0,2,0,0,0,2,2,0,2,0,0,2,0,2,2,2,2,2,2,0,1,1,0,2,2,2,2,2,0,2,2,2,2,2,2,2,0,2,2,2,2,2,0,2,2,2,2,2,2,0,2,2,2,2,2,2,0,0,0,2,2,0,2,0,1,1,0,0,0,0,2,2,2,2,2,2,2,0,2,2,2,2,2,0,2,0,2,2,0,2,2,0,2,2,2,0,2,2,0,0,2,0,2,0,2,2,0,0,1,1,0,0,2,2,2,2,0,2,0,2,2,0,2,2,2,2,2,2,0,2,0,0,0,0,2,0,2,2,2,2,2,0,0,2,0,2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,56,72,33,24,73,85,29,45,48,12,58,96,32,17,48,17,9,49,78,6,48,98,91,23,28,37,16,54,30,88,69,69,23,59,33,61,89,94,79,64,42,13,82,45,98,57,57,80,6,2,67,86,26,84,80,47,72,38,22,73,75,4,3,47,96,34,52,22,26,90,74,84,37,68,37,73,86,59,27,67,52,22,63,92,41,46,68,93,55,3,6,78,32,82,8,34,41,77,29,92,77,81,17,90,40,50,27,80,82,96,66,21,67,96,69,12,39,65,93,7,91,97,55,95,64,9,91,48,23,44,96,67,38,43,26,70,64,17,47,98,35,54,89,31,67,18,36,42,52,19,71,4,47,21,43,77,6,64,45,94,49,52,54,85,9,78,73,44,56,3,37,15,45,16,78,98,82,27,59,13,26,75,73,18,74,20,63,65,56,55,98,34,10,97,55,70,51,25,9,16,10,79,49,58,13,92,19,25,79,33,48,5,78,86,94,48,39,3,43,90,35,45,56,60,51,92,4,52,64,63,18,70,44,82,70,29,72,53,91,36,75,95,57,61,42,79,98,26,8,73,10,3,69,95,69,39,13,70,90,66,96,97,21,35,38,43,21,79,91,5,92,93,48,25,31,15,39,58,51,68,46,93,10,56,16,5,54,34,54,68,22,97,18,14,96,52,92,62,62,62,43,62,73,41,85,36,81,81,1,41,92,94,78,32,72,15,30,54,86,1,60,28,20,94,15,52,60,68,63,15,45,39,66,65,42,35,28,31,83,59,87,69,83,22,58,45,22,70,86,98,44,13,37,24,67,80,7,67,16,10,88,54,60,76,97,37,63,31,61,91,10,61,97,76,59,40,28,15,45,50,86,61,30,11,85,87,53,10,88,40,69,82,60,57,38,74,35,44,33,98,80,47,3,51,56,12,28,86,26,91,45,10,92,18,63,4,66,47,73,18,57,51,32,79,25,41,61,68,78,34,71,3,33,29,40,25,15,72,88,51,20,76,70,10,20,38,13,27,92,97,60,22,54,73,20,51,27,87,51,41,73,61,1,31,94,11,74,56,34,9,74,31,20,91,63,75,1,54,62,31,30,60,74,67,13,83,65,10,63,38,65,75,94,85,98,53,59,63,42,21,93,13,55,36,76,53,14,30,71,2,84,16,82,87,57,74,57,29,48,14,73,4,22,91,81,94,41,67,27,82,20,4,89,43,92,36,70,29,45,82,65,49,2,63,78,18,13,75,76,50,85,64,37,4,57,41,18,15,65,70,44,85,72,11,36,35,84,4,70,49,47,20,10,80,79,59,89,1,87,5,22,87,31,23,38,35,49,71,33,46,81,64,43,59,46,51,62,33,89,61,66,64,92,23,30,56,17,71,85,18,2,72,2,42,31,13,53,35,17,91,73,73,48,95,20,26,23,10,65,4,40,6,79,49,84,7,15,49,90,45,24,42,76,21,97,3,63,42,30,92,55,38,44,53,67,44,42,36,28,9,17,66,92,44,51,55,57,59,6,50,52,97,21,45,19,17,21,76,86,32,23,56,78,93,97,13,93,87,32,83,89,23,21,63,40,87,83,95,95,74,57,60,82,48,45,18,93,63,74,31,30,43,50,28,69,60,43,81,86,67,64,17,67,27,79,49,92,21,71,59,32,83,29,72,3,62,47,95,76,63,32,53,32,28,75,50,22,37,43,20,10,13,80,80,19,43,55,23,14,70,32,80,4,44,4,40,35,44,55,41,68,80,68,25,27,97,39,30,24,42,52,88,87,36,23,83,58,50,85,60,97,72,97,51,37,83,40,59,52,25,83,8,76,14,20,94,43,45,75,47,12,67,46,56,30,74,1,28,41,42,74,21,36,22,80,69,23,12,62,25,39,77,8,46,56,64,43,34,8,54,85,43,20,84,24,13,64,92,68,7,61,49,46,16,87,54,24,94,70,63,63,33,43,30,29,34,22,23,98,20,90,14,77,27,89,39,13,3,77,47,462045 diff --git a/input/day_14 b/input/day_14 new file mode 100644 index 0000000..46d010b --- /dev/null +++ b/input/day_14 @@ -0,0 +1,59 @@ +3 JQFM, 5 QMQB, 20 WQCT => 8 PHBMP +2 XJFQR => 1 WQCT +133 ORE => 3 KFKWH +1 QGVJV, 9 TNRGW, 9 NSWDH => 5 HJPD +4 QMQB, 2 QZMZ, 3 DQPX, 1 HJFV, 5 SLQN, 4 XHKG, 23 DBKL => 5 CVZLJ +6 GFDP, 1 MXQF => 7 TDPN +19 BWHKF, 2 KXHQW, 8 GHNG, 8 CSNS, 8 JVRQ, 1 PHBMP, 20 LZWR, 7 JKRZH => 5 PZRSQ +1 JQFM => 1 QGVJV +8 KFKWH => 7 ZJKB +3 VMDSG, 2 BMSNV => 9 XJFQR +7 ZKZHV => 6 DVRS +1 WKFTZ, 5 SVTK, 1 QDJD => 7 JQFM +19 FRTK => 2 QMTMN +23 DVRS, 3 XNGTQ => 9 MCWF +188 ORE => 3 HDRMK +3 MCWF => 5 LHXN +12 KFKWH, 2 DWBL => 8 ZKZHV +2 GHNG => 8 SVTK +4 MLJN, 9 CSNS => 6 DQPX +2 NDNP, 1 LWGNJ, 6 DBKL, 3 RLKDF, 9 DQPX, 1 BWHKF => 3 JVGRC +4 TNRGW => 2 CFBP +2 KXHQW => 1 BWHKF +7 HJFV => 4 PDKZ +2 QZMZ => 5 BMSNV +1 SVTK, 1 LZWR, 1 WQCT => 3 SLQN +1 TDPN, 1 VMDSG => 7 NHVQD +1 SVTK => 2 LZWR +149 ORE => 9 DWBL +1 XMHN, 1 PDKZ => 5 LWGNJ +6 WCMV => 6 XNGTQ +7 MCWF, 2 VCMPS => 1 HJFV +11 BRTX, 37 CFBP, 2 HJPD, 72 HDRMK, 5 LWGNJ, 7 JVGRC, 3 CVZLJ, 8 PZRSQ, 3 LQBJP => 1 FUEL +9 QMTMN, 14 FRTK, 14 HJFV => 9 NDNP +1 KFKWH, 3 ZJKB => 9 MXQF +1 HJFV, 1 XJFQR => 9 TNRGW +1 DVRS => 2 BRTX +4 QZMZ, 3 BMSNV, 3 GFDP => 6 VMDSG +3 NHVQD => 6 WKFTZ +1 BWHKF => 6 DBKL +8 DWBL => 8 QZMZ +4 MLJN, 16 NSWDH, 4 XHKG => 8 JVRQ +2 DVRS, 32 XNGTQ, 9 MXQF => 7 GHNG +1 DWBL => 8 WCMV +8 SLQN, 1 CFBP => 9 MLJN +1 QDJD => 4 XMHN +3 BWHKF, 2 TNRGW => 9 XHKG +1 WGLN => 8 GFDP +1 MCWF, 1 XJFQR => 2 CSNS +3 XNGTQ => 1 QDJD +15 KXHQW, 3 WQCT, 2 QMTMN => 8 NSWDH +9 XCMJ, 1 QMTMN => 2 JKRZH +4 HDRMK => 4 WGLN +9 NSWDH, 12 LHXN, 16 NDNP => 1 QMQB +16 NHVQD, 3 DWBL, 1 WKFTZ => 4 FRTK +1 GFDP => 2 VCMPS +2 JQFM, 2 XMHN => 6 XCMJ +1 DVRS, 19 QZMZ, 1 DWBL => 5 KXHQW +1 QGVJV, 8 NDNP, 5 PDKZ => 1 RLKDF +29 HJFV, 2 WKFTZ, 4 GFDP => 2 LQBJP diff --git a/input/day_15 b/input/day_15 new file mode 100644 index 0000000..4e211d1 --- /dev/null +++ b/input/day_15 @@ -0,0 +1 @@ +3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1002,1034,1,1039,102,1,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1002,1034,1,1039,101,0,1036,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,102,1,1035,1040,1002,1038,1,1043,1002,1037,1,1042,1106,0,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1002,1037,1,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,9,1032,1006,1032,165,1008,1040,3,1032,1006,1032,165,1102,2,1,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1101,1,0,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,29,1044,1105,1,224,1101,0,0,1044,1105,1,224,1006,1044,247,102,1,1039,1034,1002,1040,1,1035,1001,1041,0,1036,1002,1043,1,1038,102,1,1042,1037,4,1044,1106,0,0,19,27,41,9,17,87,2,1,91,14,15,99,17,13,40,13,7,33,23,28,7,21,75,15,41,83,18,4,28,1,21,99,3,2,4,60,16,5,16,22,59,18,37,21,62,96,11,63,46,16,27,76,7,36,38,28,53,18,84,52,12,47,25,93,10,57,64,21,41,75,52,9,80,60,21,86,60,21,70,21,13,72,78,22,61,17,28,54,51,93,18,3,87,21,4,98,17,59,2,17,18,71,5,20,16,39,66,18,7,62,15,37,25,52,27,17,15,10,48,11,39,18,20,68,83,22,36,9,3,69,56,64,21,39,93,1,90,18,57,52,14,41,32,57,5,7,72,18,35,66,21,22,88,2,31,52,7,35,25,50,14,35,7,11,92,38,14,66,3,28,84,18,17,48,15,34,40,4,21,92,52,27,5,4,53,65,59,24,88,24,66,88,85,26,8,26,10,64,99,9,44,38,14,26,74,75,24,31,7,6,62,9,57,75,18,22,52,57,15,3,87,21,39,24,12,8,70,8,19,3,89,16,36,15,36,16,30,28,8,89,12,99,98,16,78,24,11,63,87,55,51,19,57,18,28,9,90,15,95,56,57,1,93,77,24,36,14,44,46,25,66,37,23,8,12,10,58,27,66,4,72,1,2,16,91,16,66,26,24,53,25,20,41,8,75,23,2,20,91,19,3,12,32,30,3,33,85,17,21,92,17,1,12,73,9,34,12,85,42,5,69,67,4,87,70,6,49,96,12,5,37,62,54,72,13,52,14,21,84,68,54,22,78,11,93,12,90,55,7,19,44,21,98,4,46,50,27,30,2,99,27,35,8,5,62,1,91,65,12,80,16,17,81,14,73,60,69,24,23,13,74,57,10,26,21,80,60,10,79,3,9,37,77,73,16,10,3,13,95,4,91,65,11,86,16,24,71,22,6,63,90,56,15,64,8,25,46,77,71,24,13,72,96,22,8,15,79,39,19,19,47,14,16,92,69,73,23,76,23,28,60,84,14,54,62,11,8,30,75,44,16,4,30,82,14,80,11,1,70,85,10,14,73,70,9,54,25,26,12,51,23,86,92,18,11,19,74,55,51,10,73,7,13,43,89,5,55,2,18,82,2,14,63,71,28,7,94,61,10,51,8,53,63,22,39,19,79,20,99,2,66,22,7,68,71,17,19,45,10,14,42,99,9,9,13,75,84,14,83,75,19,92,22,47,4,83,18,46,91,22,61,28,6,71,17,10,1,81,6,60,83,21,14,13,71,11,68,73,52,10,25,30,91,6,25,86,89,19,39,18,95,1,52,23,91,20,14,41,91,26,59,16,85,99,4,15,96,51,19,25,51,73,3,48,79,14,14,41,5,17,59,8,51,43,21,15,47,3,28,53,12,22,23,2,94,74,23,53,20,20,98,21,14,46,61,26,6,55,20,69,28,6,41,19,70,48,6,9,32,32,28,20,21,62,22,38,7,90,3,32,24,92,49,23,72,63,17,18,89,85,33,28,23,27,5,42,52,7,54,18,17,21,63,98,8,9,84,31,24,80,70,22,51,28,61,77,6,25,68,66,8,47,22,7,44,26,37,15,28,68,23,18,18,14,34,3,85,99,31,41,53,28,20,43,90,22,13,70,27,27,17,35,48,11,92,4,60,84,4,38,27,25,89,99,74,2,31,63,13,50,1,54,4,59,3,59,2,54,15,37,19,74,45,75,7,84,19,96,72,75,9,34,18,52,23,99,11,45,81,53,7,71,24,80,26,31,11,74,27,57,0,0,21,21,1,10,1,0,0,0,0,0,0