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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy