diff --git a/2022/day1/Cargo.lock b/2022/aoc/Cargo.lock similarity index 90% rename from 2022/day1/Cargo.lock rename to 2022/aoc/Cargo.lock index ae5bfe8..a5b53ef 100644 --- a/2022/day1/Cargo.lock +++ b/2022/aoc/Cargo.lock @@ -3,5 +3,5 @@ version = 3 [[package]] -name = "day1" +name = "aoc" version = "0.1.0" diff --git a/2022/day1/Cargo.toml b/2022/aoc/Cargo.toml similarity index 91% rename from 2022/day1/Cargo.toml rename to 2022/aoc/Cargo.toml index a3c4e52..706d2e1 100644 --- a/2022/day1/Cargo.toml +++ b/2022/aoc/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "day1" +name = "aoc" version = "0.1.0" edition = "2021" diff --git a/2022/aoc/src/lib.rs b/2022/aoc/src/lib.rs new file mode 100644 index 0000000..7b9bd86 --- /dev/null +++ b/2022/aoc/src/lib.rs @@ -0,0 +1,8 @@ +use std::{env, fs}; + +pub fn read_input_file_to_string() -> String { + let args: Vec = env::args().collect(); + let filename = args.get(1).expect("Missing filename argument"); + fs::read_to_string(&filename).expect("Unable to read file") +} + diff --git a/2022/day01/Cargo.lock b/2022/day01/Cargo.lock new file mode 100644 index 0000000..e0a4e9a --- /dev/null +++ b/2022/day01/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aoc" +version = "0.1.0" + +[[package]] +name = "day1" +version = "0.1.0" +dependencies = [ + "aoc", +] diff --git a/2022/day01/Cargo.toml b/2022/day01/Cargo.toml new file mode 100644 index 0000000..0503676 --- /dev/null +++ b/2022/day01/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "day1" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../aoc" } diff --git a/2022/day1/input.txt b/2022/day01/input.txt similarity index 100% rename from 2022/day1/input.txt rename to 2022/day01/input.txt diff --git a/2022/day1/src/main.rs b/2022/day01/src/main.rs similarity index 81% rename from 2022/day1/src/main.rs rename to 2022/day01/src/main.rs index 2513bcd..bd0083e 100644 --- a/2022/day1/src/main.rs +++ b/2022/day01/src/main.rs @@ -1,5 +1,4 @@ -use std::env; -use std::fs; +use aoc; use std::str::Lines; fn get_calorie_totals(lines: Lines) -> Vec { @@ -23,12 +22,9 @@ fn get_calorie_totals(lines: Lines) -> Vec { } fn main() { - let args: Vec = env::args().collect(); - - let filename = args.get(1).expect("Missing filename argument"); - - let file_contents = fs::read_to_string(&filename).expect("Unable to read file"); + let file_contents = aoc::read_input_file_to_string(); let lines = file_contents.lines(); + let elves = get_calorie_totals(lines); println!( diff --git a/2022/day2/Cargo.lock b/2022/day02/Cargo.lock similarity index 100% rename from 2022/day2/Cargo.lock rename to 2022/day02/Cargo.lock diff --git a/2022/day2/Cargo.toml b/2022/day02/Cargo.toml similarity index 100% rename from 2022/day2/Cargo.toml rename to 2022/day02/Cargo.toml diff --git a/2022/day2/input.txt b/2022/day02/input.txt similarity index 100% rename from 2022/day2/input.txt rename to 2022/day02/input.txt diff --git a/2022/day2/src/main.rs b/2022/day02/src/main.rs similarity index 100% rename from 2022/day2/src/main.rs rename to 2022/day02/src/main.rs diff --git a/2022/day3/Cargo.lock b/2022/day03/Cargo.lock similarity index 100% rename from 2022/day3/Cargo.lock rename to 2022/day03/Cargo.lock diff --git a/2022/day3/Cargo.toml b/2022/day03/Cargo.toml similarity index 100% rename from 2022/day3/Cargo.toml rename to 2022/day03/Cargo.toml diff --git a/2022/day3/input.txt b/2022/day03/input.txt similarity index 100% rename from 2022/day3/input.txt rename to 2022/day03/input.txt diff --git a/2022/day3/src/main.rs b/2022/day03/src/main.rs similarity index 100% rename from 2022/day3/src/main.rs rename to 2022/day03/src/main.rs diff --git a/2022/day4/Cargo.lock b/2022/day04/Cargo.lock similarity index 100% rename from 2022/day4/Cargo.lock rename to 2022/day04/Cargo.lock diff --git a/2022/day4/Cargo.toml b/2022/day04/Cargo.toml similarity index 100% rename from 2022/day4/Cargo.toml rename to 2022/day04/Cargo.toml diff --git a/2022/day4/input.txt b/2022/day04/input.txt similarity index 100% rename from 2022/day4/input.txt rename to 2022/day04/input.txt diff --git a/2022/day4/src/main.rs b/2022/day04/src/main.rs similarity index 100% rename from 2022/day4/src/main.rs rename to 2022/day04/src/main.rs diff --git a/2022/day5/Cargo.lock b/2022/day05/Cargo.lock similarity index 100% rename from 2022/day5/Cargo.lock rename to 2022/day05/Cargo.lock diff --git a/2022/day5/Cargo.toml b/2022/day05/Cargo.toml similarity index 100% rename from 2022/day5/Cargo.toml rename to 2022/day05/Cargo.toml diff --git a/2022/day5/input.txt b/2022/day05/input.txt similarity index 100% rename from 2022/day5/input.txt rename to 2022/day05/input.txt diff --git a/2022/day5/src/main.rs b/2022/day05/src/main.rs similarity index 100% rename from 2022/day5/src/main.rs rename to 2022/day05/src/main.rs diff --git a/2022/day6/Cargo.lock b/2022/day06/Cargo.lock similarity index 100% rename from 2022/day6/Cargo.lock rename to 2022/day06/Cargo.lock diff --git a/2022/day6/Cargo.toml b/2022/day06/Cargo.toml similarity index 100% rename from 2022/day6/Cargo.toml rename to 2022/day06/Cargo.toml diff --git a/2022/day6/input.txt b/2022/day06/input.txt similarity index 100% rename from 2022/day6/input.txt rename to 2022/day06/input.txt diff --git a/2022/day6/src/main.rs b/2022/day06/src/main.rs similarity index 100% rename from 2022/day6/src/main.rs rename to 2022/day06/src/main.rs diff --git a/2022/day7.py b/2022/day07.py similarity index 100% rename from 2022/day7.py rename to 2022/day07.py diff --git a/2022/day8/Cargo.lock b/2022/day08/Cargo.lock similarity index 100% rename from 2022/day8/Cargo.lock rename to 2022/day08/Cargo.lock diff --git a/2022/day8/Cargo.toml b/2022/day08/Cargo.toml similarity index 100% rename from 2022/day8/Cargo.toml rename to 2022/day08/Cargo.toml diff --git a/2022/day8/example.txt b/2022/day08/example.txt similarity index 100% rename from 2022/day8/example.txt rename to 2022/day08/example.txt diff --git a/2022/day8/input.txt b/2022/day08/input.txt similarity index 100% rename from 2022/day8/input.txt rename to 2022/day08/input.txt diff --git a/2022/day8/src/main.rs b/2022/day08/src/main.rs similarity index 100% rename from 2022/day8/src/main.rs rename to 2022/day08/src/main.rs diff --git a/2022/day9/Cargo.lock b/2022/day09/Cargo.lock similarity index 100% rename from 2022/day9/Cargo.lock rename to 2022/day09/Cargo.lock diff --git a/2022/day9/Cargo.toml b/2022/day09/Cargo.toml similarity index 100% rename from 2022/day9/Cargo.toml rename to 2022/day09/Cargo.toml diff --git a/2022/day9/input.txt b/2022/day09/input.txt similarity index 100% rename from 2022/day9/input.txt rename to 2022/day09/input.txt diff --git a/2022/day9/src/main.rs b/2022/day09/src/main.rs similarity index 100% rename from 2022/day9/src/main.rs rename to 2022/day09/src/main.rs diff --git a/2022/day10/Cargo.lock b/2022/day10/Cargo.lock new file mode 100644 index 0000000..5f8ea61 --- /dev/null +++ b/2022/day10/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day10" +version = "0.1.0" diff --git a/2022/day10/Cargo.toml b/2022/day10/Cargo.toml new file mode 100644 index 0000000..40d2066 --- /dev/null +++ b/2022/day10/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day10" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2022/aoc2022/data/day10-input.txt b/2022/day10/input.txt similarity index 100% rename from 2022/aoc2022/data/day10-input.txt rename to 2022/day10/input.txt diff --git a/2022/aoc2022/data/day10-input-longer-example.txt b/2022/day10/long-example.txt similarity index 100% rename from 2022/aoc2022/data/day10-input-longer-example.txt rename to 2022/day10/long-example.txt diff --git a/2022/aoc2022/data/day10-input-small-example.txt b/2022/day10/small-example.txt similarity index 100% rename from 2022/aoc2022/data/day10-input-small-example.txt rename to 2022/day10/small-example.txt diff --git a/2022/day10/src/main.rs b/2022/day10/src/main.rs new file mode 100644 index 0000000..b7e1421 --- /dev/null +++ b/2022/day10/src/main.rs @@ -0,0 +1,129 @@ +use std::{env, fs}; + +#[derive(Debug)] +enum Instruction { + Noop, + AddX(i32), +} + +impl Instruction { + fn number_of_cycles(&self) -> u32 { + match self { + Instruction::Noop => 1, + Instruction::AddX(_) => 2, + } + } +} + +struct CPU<'a> { + instructions: Box + 'a>, + current_instruction: Option, + cycle: u32, + x: i32, +} + +impl<'a> CPU<'a> { + fn new + 'a>(instructions: T) -> CPU<'a> { + CPU { + instructions: Box::new(instructions), + current_instruction: None, + cycle: 0, + x: 1, + } + } +} + +impl Iterator for CPU<'_> { + type Item = State; + + fn next(&mut self) -> Option { + if self.current_instruction.is_none() { + self.current_instruction = self.instructions.next(); + self.cycle = 0; + } + + if let Some(current_instruction) = &self.current_instruction { + let state = Some(State::from_cpu(&self)); + self.cycle += 1; + + if self.cycle >= current_instruction.number_of_cycles() { + match current_instruction { + Instruction::Noop => {} + Instruction::AddX(value) => { + self.x += value; + } + } + + self.current_instruction = self.instructions.next(); + self.cycle = 0; + } + + state + } else { + None + } + } +} + +#[derive(Clone, Debug)] +struct State { + x: i32, +} + +impl State { + fn from_cpu(cpu: &CPU) -> State { + State { x: cpu.x } + } +} + +fn main() { + let args: Vec = env::args().collect(); + + let filename = args.get(1).expect("Missing filename argument"); + + let file_contents = fs::read_to_string(&filename).expect("Unable to read file"); + let lines = file_contents.lines(); + + let cpu = CPU::new(lines.map(|line| -> Instruction { + if line.starts_with("addx") { + let value = i32::from_str_radix(line.split(" ").collect::>()[1], 10).unwrap(); + Instruction::AddX(value) + } else { + Instruction::Noop + } + })); + + let mut number_of_cycles = 0; + let mut signal_strengths = 0; + let mut cycles: Vec = vec![]; + + for (i, cycle) in cpu.enumerate() { + cycles.push(cycle.clone()); + + let x = cycle.x; + + let cycle_number = i as i32 + 1; + if cycle_number % 40 == 20 { + signal_strengths += x * cycle_number; + } + number_of_cycles = i; + + let i = i as i32; + if i > 0 && i % 40 == 0 { + println!(""); + } + let horizontal_beam_position = i % 40; + if horizontal_beam_position == (x - 1) + || horizontal_beam_position == x + || horizontal_beam_position == (x + 1) + { + print!("#"); + } else { + print!("."); + } + } + + println!(""); + println!("There were {} instructions", number_of_cycles + 1); + println!("Part 1: sum of signal strengths: {}", signal_strengths); +} diff --git a/2022/day11/Cargo.lock b/2022/day11/Cargo.lock new file mode 100644 index 0000000..4ab9be8 --- /dev/null +++ b/2022/day11/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day11" +version = "0.1.0" diff --git a/2022/day11/Cargo.toml b/2022/day11/Cargo.toml new file mode 100644 index 0000000..8f5b9a5 --- /dev/null +++ b/2022/day11/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day11" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2022/day11/example.txt b/2022/day11/example.txt new file mode 100644 index 0000000..30e09e5 --- /dev/null +++ b/2022/day11/example.txt @@ -0,0 +1,27 @@ +Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 diff --git a/2022/day11/input.txt b/2022/day11/input.txt new file mode 100644 index 0000000..cff9230 --- /dev/null +++ b/2022/day11/input.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 54, 82, 90, 88, 86, 54 + Operation: new = old * 7 + Test: divisible by 11 + If true: throw to monkey 2 + If false: throw to monkey 6 + +Monkey 1: + Starting items: 91, 65 + Operation: new = old * 13 + Test: divisible by 5 + If true: throw to monkey 7 + If false: throw to monkey 4 + +Monkey 2: + Starting items: 62, 54, 57, 92, 83, 63, 63 + Operation: new = old + 1 + Test: divisible by 7 + If true: throw to monkey 1 + If false: throw to monkey 7 + +Monkey 3: + Starting items: 67, 72, 68 + Operation: new = old * old + Test: divisible by 2 + If true: throw to monkey 0 + If false: throw to monkey 6 + +Monkey 4: + Starting items: 68, 89, 90, 86, 84, 57, 72, 84 + Operation: new = old + 7 + Test: divisible by 17 + If true: throw to monkey 3 + If false: throw to monkey 5 + +Monkey 5: + Starting items: 79, 83, 64, 58 + Operation: new = old + 6 + Test: divisible by 13 + If true: throw to monkey 3 + If false: throw to monkey 0 + +Monkey 6: + Starting items: 96, 72, 89, 70, 88 + Operation: new = old + 4 + Test: divisible by 3 + If true: throw to monkey 1 + If false: throw to monkey 2 + +Monkey 7: + Starting items: 79 + Operation: new = old + 8 + Test: divisible by 19 + If true: throw to monkey 4 + If false: throw to monkey 5 diff --git a/2022/day11/src/main.rs b/2022/day11/src/main.rs new file mode 100644 index 0000000..ed1115b --- /dev/null +++ b/2022/day11/src/main.rs @@ -0,0 +1,443 @@ +use std::cell::RefCell; +use std::{env, fs}; + +#[allow(dead_code)] +#[derive(Clone, Copy, Debug, PartialEq)] +enum Verbosity { + None, + Full, +} + +#[derive(Clone, Debug, PartialEq)] +enum Term { + Old, + Fixed(i64), +} + +impl TryFrom<&str> for Term { + type Error = String; + + fn try_from(s: &str) -> Result { + if s == "old" { + Ok(Term::Old) + } else if let Ok(n) = i64::from_str_radix(s, 10) { + Ok(Term::Fixed(n)) + } else { + Err(format!("Unable to parse {s} as Term")) + } + } +} + +#[derive(Clone, Debug)] +struct Operation { + left: Term, + operator: Operator, + right: Term, +} + +impl Operation { + fn perform(&self, item: &i64, verbosity: Verbosity) -> i64 { + assert!(self.left == Term::Old); + match self.operator { + Operator::Add => match self.right { + Term::Old => { + let result = item + item; + if verbosity == Verbosity::Full { + println!(" Worry level increases by itself to {result}."); + } + item + item + } + Term::Fixed(value) => { + let result = item + value; + if verbosity == Verbosity::Full { + println!(" Worry level increases by {value} to {result}."); + } + result + } + }, + Operator::Sub => match self.right { + Term::Old => { + let result = item - item; + if verbosity == Verbosity::Full { + println!(" Worry level decreases by itself to {result}."); + } + result + } + Term::Fixed(value) => { + let result = item - value; + if verbosity == Verbosity::Full { + println!(" Worry level decreases by {value} to {result}."); + } + result + } + }, + Operator::Mul => match self.right { + Term::Old => { + let result = item * item; + if verbosity == Verbosity::Full { + println!(" Worry level is multiplied by itself to {result}."); + } + result + } + Term::Fixed(value) => { + let result = item * value; + if verbosity == Verbosity::Full { + println!(" Worry level is multiplied by {value} to {result}."); + } + result + } + }, + Operator::Div => match self.right { + Term::Old => { + let result = item / item; + if verbosity == Verbosity::Full { + println!(" Worry level is divided by itself to {result}."); + } + result + } + Term::Fixed(value) => { + let result = item / value; + if verbosity == Verbosity::Full { + println!(" Worry level is divided by {value} to {result}."); + } + result + } + }, + } + } +} + +impl Operation { + fn new(left: Term, operator: Operator, right: Term) -> Operation { + Operation { + left, + operator, + right, + } + } +} + +#[derive(Clone, Debug)] +enum Operator { + Add, + Sub, + Mul, + Div, +} + +impl TryFrom<&str> for Operator { + type Error = String; + + fn try_from(s: &str) -> Result { + match s { + "+" => Ok(Operator::Add), + "-" => Ok(Operator::Sub), + "*" => Ok(Operator::Mul), + "/" => Ok(Operator::Div), + _ => Err(format!("Unable to format {s} as Operator")), + } + } +} + +struct InspectionReport { + target_monkey: usize, + item: i64, +} + +impl InspectionReport { + fn new(target_monkey: usize, item: i64) -> InspectionReport { + InspectionReport { + target_monkey, + item, + } + } +} + +#[derive(Clone, Debug)] +struct Monkey { + n: usize, + items: RefCell>, + operation: Operation, + test_divisor: i64, + target_monkey_if_true: usize, + target_monkey_if_false: usize, +} + +impl Monkey { + fn take_item(&self, item: i64) { + self.items.borrow_mut().push(item); + } + + fn inspect_items( + &self, + with_anxiety_easying: bool, + verbosity: Verbosity, + ) -> Vec { + if verbosity == Verbosity::Full { + println!("Monkey {}:", self.n); + } + let reports = self + .items + .borrow() + .iter() + .map(|item| self._inspect_item(item, with_anxiety_easying, verbosity)) + .collect(); + + self.items.borrow_mut().clear(); + + reports + } + + fn _inspect_item( + &self, + item: &i64, + should_ease_anxiety: bool, + verbosity: Verbosity, + ) -> InspectionReport { + if verbosity == Verbosity::Full { + println!(" Monkey inspects an item with a worry level of {}", item); + } + let mut modified_worry_level = self.operation.perform(item, verbosity); + + if should_ease_anxiety { + if verbosity == Verbosity::Full { + println!( + " Monkey gets bored with item. Worry level is divided by 3 to {}", + modified_worry_level + ); + } + modified_worry_level = modified_worry_level / 3; + } else { + modified_worry_level = modified_worry_level % 9699690; + if verbosity == Verbosity::Full { + println!( + " Monkey gets bored with item. Normalizing worry level to {}", + modified_worry_level + ); + } + } + + if modified_worry_level % self.test_divisor == 0 { + if verbosity == Verbosity::Full { + println!( + " Current worry level is divisible by {}", + self.test_divisor + ); + println!( + " Item with worry level {} is thrown to {}", + modified_worry_level, self.target_monkey_if_true + ); + } + InspectionReport::new(self.target_monkey_if_true, modified_worry_level) + } else { + if verbosity == Verbosity::Full { + println!( + " Current worry level is not divisible by {}", + self.test_divisor + ); + println!( + " Item with worry level {} is thrown to {}", + modified_worry_level, self.target_monkey_if_false + ); + } + InspectionReport::new(self.target_monkey_if_false, modified_worry_level) + } + } +} + +struct MonkeyBuilder { + n: usize, + items: Vec, + operation: Option, + test_divisor: i64, + target_monkey_if_true: usize, + target_monkey_if_false: usize, +} + +impl MonkeyBuilder { + fn new(n: usize) -> MonkeyBuilder { + MonkeyBuilder { + n, + items: Vec::new(), + operation: None, + test_divisor: 0, + target_monkey_if_true: 0, + target_monkey_if_false: 0, + } + } + + fn build(self) -> Monkey { + Monkey { + n: self.n, + items: RefCell::new(self.items), + operation: self.operation.unwrap(), + test_divisor: self.test_divisor, + target_monkey_if_true: self.target_monkey_if_true, + target_monkey_if_false: self.target_monkey_if_false, + } + } + + fn items(mut self, items: Vec) -> MonkeyBuilder { + self.items = items; + self + } + + fn operation(mut self, operation: Operation) -> MonkeyBuilder { + self.operation = Some(operation); + self + } + + fn test_divisor(mut self, divisor: i64) -> MonkeyBuilder { + self.test_divisor = divisor; + self + } + + fn target_monkey_if_true(mut self, target_monkey: usize) -> MonkeyBuilder { + self.target_monkey_if_true = target_monkey; + self + } + + fn target_monkey_if_false(mut self, target_monkey: usize) -> MonkeyBuilder { + self.target_monkey_if_false = target_monkey; + self + } +} + +fn main() { + let args: Vec = env::args().collect(); + let filename = args.get(1).expect("Missing filename"); + let file_contents = fs::read_to_string(filename).expect("Unable to read {filename}"); + + let mut monkeys: Vec = Vec::new(); + let mut monkey_builder: Option = None; + + for line in file_contents.lines() { + if line.starts_with("Monkey") { + let split_line: Vec<&str> = line.split(&[' ', ':'][..]).collect(); + let n = usize::from_str_radix(split_line[1], 10).unwrap(); + assert!(monkey_builder.is_none()); + monkey_builder = Some(MonkeyBuilder::new(n)); + } else if line.starts_with(" Starting items:") { + let mut split = line.split(": ").skip(1); + let items: Vec = split + .next() + .unwrap() + .split(", ") + .map(|s| i64::from_str_radix(s, 10).unwrap()) + .collect(); + monkey_builder = Some(monkey_builder.unwrap().items(items)); + } else if line.starts_with(" Operation:") { + let mut split = line.split(": ").skip(1); + + let operation_terms: Vec<&str> = split.next().unwrap().split(" ").collect(); + let left_term = Term::try_from(operation_terms[2]).unwrap(); + let right_term = Term::try_from(operation_terms[4]).unwrap(); + let operator = Operator::try_from(operation_terms[3]).unwrap(); + + let operation = Operation::new(left_term, operator, right_term); + monkey_builder = Some(monkey_builder.unwrap().operation(operation)); + } else if line.starts_with(" Test:") { + let mut split = line.split(": ").skip(1); + let divisor = + i64::from_str_radix(split.next().unwrap().split(" ").skip(2).next().unwrap(), 10) + .unwrap(); + monkey_builder = Some(monkey_builder.unwrap().test_divisor(divisor)); + } else if line.starts_with(" If true:") { + let split: Vec<&str> = line.split(" ").collect(); + let target_monkey = usize::from_str_radix(split.last().unwrap(), 10).unwrap(); + monkey_builder = Some(monkey_builder.unwrap().target_monkey_if_true(target_monkey)); + } else if line.starts_with(" If false:") { + let split: Vec<&str> = line.split(" ").collect(); + let target_monkey = usize::from_str_radix(split.last().unwrap(), 10).unwrap(); + monkey_builder = Some( + monkey_builder + .unwrap() + .target_monkey_if_false(target_monkey), + ); + } else if line == "" { + let builder = monkey_builder.take(); + monkeys.push(builder.unwrap().build()) + } + } + + if let Some(builder) = monkey_builder.take() { + monkeys.push(builder.build()); + } + + { + let part1_monkeys = monkeys.clone(); + let mut part1_monkey_inspection_counts: Vec = vec![0; part1_monkeys.len()]; + + for round in 1..=20 { + println!("----- Round {round} -----"); + + for monkey in &part1_monkeys { + let reports = monkey.inspect_items(true, Verbosity::Full); + part1_monkey_inspection_counts[monkey.n] += reports.len() as u32; + + for r in reports { + part1_monkeys[r.target_monkey].take_item(r.item); + } + } + + println!("After round {round}, the monkeys are holding items with these worry levels:"); + for monkey in &part1_monkeys { + println!( + "Monkey {}: {}", + monkey.n, + monkey + .items + .borrow() + .iter() + .map(|i| i.to_string()) + .collect::>() + .join(", ") + ); + } + } + + println!("----- Final Counts -----"); + for (i, c) in part1_monkey_inspection_counts.iter().enumerate() { + println!("Monkey {i} inspected items {c} times."); + } + + let mut part1_sorted_counts = part1_monkey_inspection_counts.clone(); + part1_sorted_counts.sort_by(|a, b| b.cmp(a)); + println!( + "Part 1: monkey business: {} * {} = {}", + part1_sorted_counts[0], + part1_sorted_counts[1], + part1_sorted_counts[0] * part1_sorted_counts[1] + ); + } + + { + let part2_monkeys = monkeys.clone(); + let mut part2_monkey_inspection_counts: Vec = vec![0; part2_monkeys.len()]; + for round in 1..=10000 { + println!("----- Round {round} -----"); + + for monkey in &part2_monkeys { + let reports = monkey.inspect_items(false, Verbosity::None); + part2_monkey_inspection_counts[monkey.n] += reports.len() as u64; + + for r in reports { + part2_monkeys[r.target_monkey].take_item(r.item); + } + } + + for (i, c) in part2_monkey_inspection_counts.iter().enumerate() { + println!("Monkey {i} inspected items {c} times."); + } + } + + let mut part2_sorted_counts = part2_monkey_inspection_counts.clone(); + part2_sorted_counts.sort_by(|a, b| b.cmp(a)); + println!( + "Part 2: monkey business: {} * {} = {}", + part2_sorted_counts[0], + part2_sorted_counts[1], + part2_sorted_counts[0] * part2_sorted_counts[1] + ); + } +} diff --git a/2022/day12/Cargo.lock b/2022/day12/Cargo.lock new file mode 100644 index 0000000..5e9bbe3 --- /dev/null +++ b/2022/day12/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day12" +version = "0.1.0" diff --git a/2022/day12/Cargo.toml b/2022/day12/Cargo.toml new file mode 100644 index 0000000..ba13763 --- /dev/null +++ b/2022/day12/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day12" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2022/day12/example.txt b/2022/day12/example.txt new file mode 100644 index 0000000..86e9cac --- /dev/null +++ b/2022/day12/example.txt @@ -0,0 +1,5 @@ +Sabqponm +abcryxxl +accszExk +acctuvwj +abdefghi diff --git a/2022/day12/input.txt b/2022/day12/input.txt new file mode 100644 index 0000000..615b920 --- /dev/null +++ b/2022/day12/input.txt @@ -0,0 +1,41 @@ +abccccccccaaaaaaaccaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccaaaaaa +abccccccccaaaaaaaccaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccaaaaaa +abccccccccccaaaaaaccaaaaaaaaaaaaaaaaccccccccccccccccacccccccccccccccccccaaaaa +abcccccaaaacaaaaaaccaaaaaaaaaaaaaaaaacccccccccccccccaaaccccaccccccccccccccaaa +abccccaaaaacaaccccccaaaaaacaaacaacaaaaaaacccccccccccaaaacccaacccccccccccccaaa +abaaccaaaaaaccccaaacaaaacacaaacaaccaaaaaacccccccccccaklaccccccccccccccccccaac +abaaccaaaaaaccaaaaaacccccccaaacccaaaaaaaccccccccccckkkllllccccccccccccccccccc +abaaccaaaaaaccaaaaaacccccccaaaaacaaaaaaacccccccccckkkklllllcccccccaaaccaccccc +abacccccaacccccaaaaacccccccaaaaaccaaaaaaacccccccckkkkpppllllccccccaaaaaaccccc +abacccccccccccaaaaacccccccccaaaacccaaaaaaccccccckkkkpppppplllccccddddaaaccccc +abccccccccccccaaaaaccccccccccaaaccaaaccccccccccckkkppppppppllllldddddddaccccc +abccacccccccccccccccccccccccccccccaaccccccccccckkkopppupppplllmmmmdddddaacccc +abccaaacaaaccccccccccccccccccccaaaaaaaaccccccckkkkopuuuuupppllmmmmmmddddacccc +abccaaaaaaaccccccccccccccccccccaaaaaaaacccccjjkkkooouuuuuuppqqqqqmmmmddddcccc +abccaaaaaacccccccccccccccaaccccccaaaacccccjjjjjjoooouuxuuuppqqqqqqmmmmdddcccc +abcaaaaaaaacccccccccccccaaacccccaaaaaccccjjjjoooooouuuxxuuvvvvvqqqqmmmdddcccc +abaaaaaaaaaacccccccaaaaaaacaacccaacaaacccjjjooooouuuuxxxxvvvvvvvqqqmmmdddcccc +abaaaaaaaaaacccaaacaaaaaaaaaacccacccaaccjjjooootttuuuxxxyyvyyvvvqqqmmmeeecccc +abcccaaacaaacccaaaaaaacaaaaaccccccccccccjjjooottttxxxxxxyyyyyyvvqqqmmmeeccccc +abcccaaacccccccaaaaaacaaaaaccccaaccaacccjjjnnntttxxxxxxxyyyyyvvvqqqnneeeccccc +SbccccaacccccccaaaaaaaaacaaacccaaaaaacccjjjnnntttxxxEzzzzyyyyvvqqqnnneeeccccc +abcccccccccccccaaaaaaaaacaaccccaaaaaccccjjjnnnttttxxxxyyyyyvvvrrrnnneeecccccc +abcccaacccccccaaaaaaaaaccccccccaaaaaacccciiinnnttttxxxyyyyywvvrrrnnneeecccccc +abcccaaaaaaccaaaaaaaacccccccccaaaaaaaaccciiiinnnttttxyyywyyywvrrrnnneeecccccc +abcccaaaaaaccaaaaaaaacccccccccaaaaaaaacccciiinnnntttxwywwyyywwwrrnnneeecccccc +abcaaaaaaaccaaaaaaaaaccccccccccccaacccccccciiinnnttwwwwwwwwwwwwrrnnneeecccccc +abcaaaaaaaccaaaaaacccccccccccccccaaccccccaaiiiinnttwwwwwwwwwwwrrrnnnffecccccc +abcccaaaaaaccaaaaaccccccccccccccccccccaaaaaciiinnssswwwssssrwwrrrnnnfffcccccc +abaacaaccaaccaaaccccccccaacccccccccccccaaaaaiiinnssssssssssrrrrrronnfffcccccc +abaccaaccaacccccccccaaacaacccccccccccccaaaaaiiimmmssssssmoosrrrrooonffaaacccc +abaaaccccaaaaaaccccccaaaaaccccccccccccaaaaaccihmmmmsssmmmoooooooooofffaaacccc +abaaaccccaaaaaacccccccaaaaaacccccccccccccaacchhhmmmmmmmmmoooooooooffffaaccccc +abaacccaaaaaaaccccccaaaaaaaaccccaaccccccccccchhhhmmmmmmmgggggooofffffaaaccccc +abaacccaaaaaaaccccccaaaaaaaccccaaaaccccccccccchhhhmmmmhggggggggfffffaaaaccccc +abccccccaaaaaaacccccaacaaaaacccaaaaccccccccccchhhhhhhhggggggggggfffaacaaccccc +abccaacccaaaaaaccccccccaaaaaccaaaaacccccccccccchhhhhhhggaaaaaaccccccccccccccc +abccaaaccaaccccccccccccccaaaaaaaaaccccccccccccccchhhhaaaccaaaacccccccccccccaa +abaaaaaaaccccccccccccccccaaaaaaaaccccccccccccccccccccaaaccccaaccccccccccccaaa +abaaaaaaaccccccccaaaccccacaaaaaacccccccccccccccccccccaaaccccccccccccccccccaaa +abaaaaaacccccccaaaaacaaaaaaaaaaacccccccccccccccccccccaaccccccccccccccccaaaaaa +abaaaaaacccccccaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccaaaaaa diff --git a/2022/day12/src/main.rs b/2022/day12/src/main.rs new file mode 100644 index 0000000..06080b1 --- /dev/null +++ b/2022/day12/src/main.rs @@ -0,0 +1,176 @@ +use std::cmp::Ordering; +use std::collections::BinaryHeap; +use std::{env, fs}; + +trait Elevation { + fn elevation(&self) -> Option; +} + +impl Elevation for char { + fn elevation(&self) -> Option { + let value = match self { + 'S' => 'a', + 'E' => 'z', + _ => *self + }; + + Some((value as u32) - 'a' as u32) + } +} + +#[derive(Debug)] +struct Square { + symbol: char, + up: Option, + down: Option, + left: Option, + right: Option, +} + +impl Square { + fn new(symbol: char) -> Square { + Square { symbol, up: None, down: None, left: None, right: None } + } + + fn elevation(&self) -> u32 { + self.symbol.elevation().unwrap() + } +} + +#[derive(Clone, Eq, PartialEq)] +struct State { + node: usize, + cost: u32, +} + +impl Ord for State { + fn cmp(&self, other: &Self) -> Ordering { + other.cost.cmp(&self.cost).then_with(|| self.node.cmp(&other.node)) + } +} + +impl PartialOrd for State { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +/// An implemetation of Dijkstra's algorithm to find the shortest path from start to end and return +/// its length. +fn find_length_of_shortest_path(squares: &Vec, start: usize, end: usize) -> Option { + let mut distances: Vec<_> = (0..squares.len()).map(|_| u32::MAX).collect(); + let mut heap = BinaryHeap::new(); + + // Initial state + distances[start] = 0; + heap.push(State { node: start, cost: 0 }); + + while let Some(State { node, cost }) = heap.pop() { + if node == end { + return Some(cost); + } + + if cost > distances[node] { + continue; + } + + let square = &squares[node]; + for edge in &[square.up, square.right, square.down, square.left] { + if edge.is_none() { + continue; + } + + let edge = edge.unwrap(); + + let next_cost = cost + 1; + let next = State { node: edge, cost: next_cost }; + if next.cost < distances[edge] { + heap.push(next); + distances[edge] = next_cost; + } + } + } + + None +} + +fn main() { + let args: Vec = env::args().collect(); + + let filename = args.get(1).expect("Missing filename argument"); + + let file_contents = fs::read_to_string(&filename).expect("Unable to read file"); + let character_grid = file_contents.lines().map(|l| l.chars().collect::>()).collect::>>(); + + // Assume a square grid + let width = character_grid[0].len(); + let height = character_grid.len(); + + let index_into_squares_array = |x: usize, y: usize| -> usize { + y * width + x + }; + + let mut start: usize = 0; + let mut end: usize = 0; + let mut squares: Vec = Vec::new(); + + for y in 0..height { + for x in 0..width { + let symbol = character_grid[y][x]; + + match symbol { + 'S' => start = index_into_squares_array(x, y), + 'E' => end = index_into_squares_array(x, y), + _ => {}, + } + + let elevation = symbol.elevation().unwrap(); + let mut square = Square::new(symbol); + + if y > 0 { + let up_elevation = character_grid[y-1][x].elevation().unwrap(); + if up_elevation <= elevation + 1 { + square.up = Some(index_into_squares_array(x, y - 1)); + } + } + + if y < height - 1 { + let down_elevation = character_grid[y + 1][x].elevation().unwrap(); + if down_elevation <= elevation + 1 { + square.down = Some(index_into_squares_array(x, y + 1)); + } + } + + if x > 0 { + let left_elevation = character_grid[y][x - 1].elevation().unwrap(); + if left_elevation <= elevation + 1 { + square.left = Some(index_into_squares_array(x - 1, y)); + } + } + + if x < width - 1 { + let right_elevation = character_grid[y][x + 1].elevation().unwrap(); + if right_elevation <= elevation + 1 { + square.right = Some(index_into_squares_array(x + 1, y)); + } + } + + squares.push(square); + } + } + + let length_of_shortest_path = find_length_of_shortest_path(&squares, start, end).unwrap(); + println!("Part 1: length of shortest path to location with best signal: {length_of_shortest_path}"); + + let mut paths_from_all_a_squares: Vec<(usize, u32)> = squares + .iter() + .enumerate() + .filter(|(_, sq)| sq.elevation() == 0) + .map(|(i, _)| (i, find_length_of_shortest_path(&squares, i, end))) + .filter(|(_, distance)| distance.is_some()) + .map(|(i, distance)| (i, distance.unwrap())) + .collect(); + paths_from_all_a_squares.sort_by(|a, b| b.1.cmp(&a.1)); + + dbg!(&paths_from_all_a_squares.last()); +} diff --git a/2022/day13/Cargo.lock b/2022/day13/Cargo.lock new file mode 100644 index 0000000..74e24a1 --- /dev/null +++ b/2022/day13/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day13" +version = "0.1.0" diff --git a/2022/day13/Cargo.toml b/2022/day13/Cargo.toml new file mode 100644 index 0000000..36c9510 --- /dev/null +++ b/2022/day13/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day13" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2022/day13/example.txt b/2022/day13/example.txt new file mode 100644 index 0000000..af73fbb --- /dev/null +++ b/2022/day13/example.txt @@ -0,0 +1,23 @@ +[1,1,3,1,1] +[1,1,5,1,1] + +[[1],[2,3,4]] +[[1],4] + +[9] +[[8,7,6]] + +[[4,4],4,4] +[[4,4],4,4,4] + +[7,7,7,7] +[7,7,7] + +[] +[3] + +[[[]]] +[[]] + +[1,[2,[3,[4,[5,6,7]]]],8,9] +[1,[2,[3,[4,[5,6,0]]]],8,9] diff --git a/2022/day13/input-head-2.txt b/2022/day13/input-head-2.txt new file mode 100644 index 0000000..f303a75 --- /dev/null +++ b/2022/day13/input-head-2.txt @@ -0,0 +1,2 @@ +[[[7,8],5],[[9,[8,7,8],[],[2,4,10,10],[2,10,8,3,3]],[],[[6,1,10],[],3,6],[3]],[],[4],[3,0,1,10]] +[[[[3,2,1,5],7]],[2,0,7,[4,[4],[10,2,10],[3,0,5,9],1]],[[[]],[[]]],[1,[[0,8,0,3],6,[9,9,5,5,5],6],[[]],8,[[],[0,4,2],[4,2]]],[4]] diff --git a/2022/day13/input.txt b/2022/day13/input.txt new file mode 100644 index 0000000..ec8ab5e --- /dev/null +++ b/2022/day13/input.txt @@ -0,0 +1,449 @@ +[[[7,8],5],[[9,[8,7,8],[],[2,4,10,10],[2,10,8,3,3]],[],[[6,1,10],[],3,6],[3]],[],[4],[3,0,1,10]] +[[[[3,2,1,5],7]],[2,0,7,[4,[4],[10,2,10],[3,0,5,9],1]],[[[]],[[]]],[1,[[0,8,0,3],6,[9,9,5,5,5],6],[[]],8,[[],[0,4,2],[4,2]]],[4]] + +[[],[0,[[5,1,10,6],[]],5,[[3,2,6,1],0,3],[6,3,[10,5],[]]]] +[[[[10,2],6,[1,5,8,0],3],[[4,10,8,10,9]],4,1],[[10,6],1,[[8,9,7,5]]]] + +[[[2,4,[8,0,7],7,0],[6,[1,5,9,10,8],[5,1,3,6,0]]],[10,2],[10,9]] +[[[],3],[6]] + +[[[1,[9,2],[2,2,9,6],2,9],[[8],[8,2],9,[7,2,8]],[10,[3],[9],[3,4],[8]],[[2,4,7,10,10],[0,10,3],[8]]],[8,7,[2]],[[[3,2,2,7,3],5],[],[9],6,[6,[3,10],[1],9]]] +[[],[[],6,10],[8],[],[5]] + +[[9],[10],[],[10],[[[2,9,4,7],1],7,[[10,8,8,7,0]],[[9],7,[],[],[8,7,8,7]]]] +[[[5,[4,0,9,3,1],[8,5,7,5],7]],[2]] + +[[[4,[9,1,0,6],[4,1,3]],[0],[[4,1],10,[1,5,2,1],1,5],[2,5,[10,4,4,10,4],0],7],[3,[[0,5,9,6,5],[7],8]],[],[4,4],[]] +[[[[7,8,5]],0,5,[0,[7,8,8,5],[],7,10]],[[3,8,[10,6],2],8,[1,[9,8,4,5,9],8,[4,3,8,2],[2,5,7]],10],[[10,9,1,6,0],[1,[6,10,8],[7,3,0,0,6]]],[9,8,[[3,5],[0,7,7,2],7]],[[],1,[1],[1,10],3]] + +[[8,[[4],4]],[],[10,5,10]] +[[0,[[8,6,5,4],[0,6]]],[[3],[[0],3]],[[[6,0]],2,10,10],[]] + +[[[7],7,4,[9,[2,3,0,7,6]]],[0,[[6,2,7],[10,6],[10,4,8],[7,2],5],[7,6,[5,5,4]],[[10],[1,4,9,6,1]],7]] +[[[5,[10,6,9]],[6,[7,8,5,4,10],4,[9]],9],[[[5,6,6],4,[8,7,6]],5,3,2,[[5,1],0,8,[],[4,3,0,6,7]]],[[[5],10,1]],[[],4]] + +[[5,[2],[[4,4,7,7],[5,0],[5,1,0]],8],[[],7,[[4,9,3,0,1]]]] +[[[[7,1,4,1,1],8,4,[4],4],[2,[3,10],9,[10,3,4],[2]],6],[],[[0,9,2,[0,9,8,7,5]]]] + +[[4,[[8,3,2,9],7,8],[3,[5,10],[8,4,4,5],[1,10,6,1,9]],[9,4,[],10],[]],[[3,8,[0,0,4],1,6],3,[1,5,6]],[[4,[9],[6,5,10,2]],7],[],[0,2,[],8,3]] +[[10,[[8],[]],[6,[2,7,2,7],[],5]],[[[0,0,0]],[1,[7],0,2],5,3,[[7,6,8,4]]]] + +[[[],[1,[10],0,10],[],4],[1],[10]] +[[[1],[7],[],7],[[[3,0,9,7,2],3,2,10,1],[[7,9,5,2],7,3,[2,1,8]],[9,9]],[[[0,8,10,10],5,2,[8,5,2,3,10]]]] + +[5,6,6,7,3] +[5,6,6,7] + +[[[[7,5,2,9,0],6,[],3,5],10,7],[1,10,[[4,5,10]],4,1],[[[2,3,1,9],2,5],[1,2,1],0,[9,5,[8,9],[4,0]]],[10,10,[],[[3,3]]]] +[[[[4,6],[],4,[],[8,2,8]],4,[3,[2,4],[5],1,[4,2,8,10,9]],[]],[[]],[[[10,9,10],10,[],[1,6,8,6],[5,9,4,1,10]]]] + +[[],[2,0],[6]] +[[[5,[6,8,2,5],7,9,10]],[]] + +[[[],4,8,[7,[4],[4,2,3,6,7],6],[0,[8,0,7,10,4],[7,3,7,2],1]],[2,4]] +[[[[3]],[[2,8,1,1,3],[],3]],[8,8,6],[[5],4,2,3,4],[],[2,3,[7,[2,2,7,6,3],8,3,[5,2]]]] + +[[7,6,5],[9,1]] +[[[3,2,[1,0,9,2,7],4,2],[[4,10,3,4],6,[0,4]],[],[9,[1,0],[]]],[],[5,[4,[4,10,9,6,3],3],[[8,2,8],[10,7,7,1],10,[],5],[9],9],[0,7,3,5,10]] + +[[6,[[5,5,6],5,[],[5,0,9,8],[5,5,0]],[]],[5,1,[1,[2,3]]]] +[[[],2,[[]],3],[5,[[],[4],4,10,[5,8,4,7,8]],[],[5,[0,10,5,7],[5,8],[8,2,4,5]]],[10,10,[]],[10,7,[[]],10]] + +[[[1,0,[6,3,1,8]]]] +[[[1]],[[2,[2,2,9,1],[7],6,3],[[],0],6,[[2,2],10],[4,5,[1,4]]]] + +[[[[]],5,10],[]] +[[[[4,0,9,5,4],[8,7,1,4]],7],[[10,3],7,10,7],[9,[[6,10],[4,5,2,3],0,8,1],3,3,[[7,4,6,6],[2],[3,7,10],[10,10,0]]],[]] + +[[[3,[6,8,2,5,2],[],[8,7],[3,1,8]]],[],[[[2,3,7,10,1],3,0,[9,7,7,8],4],[[6],2]]] +[[1,[[6,9,10],[0,2,5,1,8],5,0],4],[],[0,2]] + +[[[0,4],[[10,8,6,3],7],3],[],[[],[[2,5,3],[],[6,7,10,7],5,7]],[5,9,[[],[4,3],3,[1,4,3]],3],[10,5,3,5,[9,2,[9,9],10,[3,8,9,8,5]]]] +[[[6,2,[8,2,4,6]],[9,6,[],[]],[2,[9,7,8],[8,8,5,7],[6,7,0,10]],[[0,7]],8],[[[6],[9],1],[[],5]],[[7,0,[4,8],10],5,7,8]] + +[[[],2],[[[8,1]],[[2,10],[3,9,3],[10,2,8,10]],6,8]] +[[5,[]],[9,10,6,[[1],[0,10,3]]],[7,5,[]],[[8]]] + +[[1,10],[[],[[9,2,2],4,7],9,7],[0,7,5]] +[[],[6,[8]]] + +[[6,[6,3,[10,0]]],[[],1,[[5],4],9,1],[6,7,5,[[6]],[8,9]],[]] +[[8,7,5,[9,0,[5,6,0,2,7],4,[9,2,2,9,5]]],[5],[8,9,5,[[4,8,6]],3],[10,[],3,[3,9,[2,8,3,7,4],6]],[5,[4,4],7,9]] + +[[6,[5,[4,10,4,4,10],[5,0]]],[[[1,3,6,1,8],10,[4],9,9],3,[[4,10],2,[10,5,2],9,8],8,[4,10,2,6]]] +[[8]] + +[[[],[5,4,9,3,10],[[4],3,[8,0,9,10,6],[4,6]]],[1,[6,[8,4],[6,8,10,5],10],[7,4]],[],[[0],3],[[[9,8,2]],7,3]] +[[[[7],[5,1,6,8],1],2,1,[[4,0,9,5,10],[1,6,2],5,3]],[]] + +[[9,[[0,2,7,7,10],[6,9,0,10,4],9]]] +[[0],[[6,9,6,10],[[9,3,8,5]],10]] + +[[[4,[7,1,10],[0,0,3,8,9]]],[],[[[],[1,7],[1,5],3],[6,[2,6,7,1]],[[10]]]] +[[[]],[]] + +[[3,[]]] +[[8],[[[],0,1,3]],[[8]],[8],[2,[5],10,8]] + +[[6,2,[5,[0,6,6,4,6]],4],[[[7,8,8,5,5],6,2,3,8],5],[[],[6],3]] +[[10,0,[1,[],1,[1,6,3],[9]],4,[5,[8,4,6,2],9,[0,10]]]] + +[[4],[[[3],2,0,3],7]] +[[7]] + +[[[],[10]],[[0,0,2],[4],[[0]],8],[[[2]],2,6,[10,[0,6,6],[10,4,1,4,2],[9],[5,7]]]] +[[7,[[],[5,10,7,0]],5,0],[[],9],[[3,[9,7,4,8],[]]],[4,7,[[],4,[6],2,[6,4,9]]]] + +[[[],7],[[7,0,[5],10,[]],2]] +[[[[6],[]],[]],[[9,[2],3,3],[[3,2,0]]]] + +[[1],[2,[8,9,2,[4,8,3,2,5],0],[0,3],7]] +[[],[2,0,7]] + +[[[[4,1,0],[1,1,10,4,7]],[2,[8,5,8],2,[8,7,8]]]] +[[9,[]],[2,1],[[6],[9,[7]],7,9]] + +[[[[10],[7],3,3],[[10,8],[],1,2,[]],[1,[0,8,2]],6],[[[],0],8,[[1]],1,6]] +[[3,[],[[],2,[9,2,5,5],7],6],[10,[],[7]],[[[2],[1,1,10],10,5]],[7,[2,[1,5,10,10]],[[8,1,6,1,8],[10,9,7,3],[6,4,1,8,0],[0,5,4]],[3],[]],[]] + +[[9,4],[8,6,[],[]]] +[[[8],2,0]] + +[[4,10],[[[10,5,7]],[[7,0],0,1,[2,7,9,8,9]],3,3,7],[7,8,[],[]]] +[[[0,[5,2,4],4],6,[[]]],[1],[[9],3,7,7],[[[4],[3,2]]],[[[3,0,1,6,4]]]] + +[[8,[],[8,[],[10,4,4,1]]],[[9,10]],[3,9,3,3]] +[[[4],7,[2,0,[8],7,4],[[3,9,6],5]],[],[[2,8,1,[8,7]],8]] + +[[],[],[4,0,[0,1]],[4,10],[4,9]] +[[[],2,1],[[9,[3,3,4,7],0],[],[[1],[],[],0,2]],[[0]],[[[6,9,6,3],[6,1,10,1,0],10],4,[[],6,[3,7],8,[10]],[4,9]]] + +[[2,[[4,10,5,1,4],[6,1,0,2],[7]]],[5,[],[[2,3,10,1,0],8],4,6],[9,[7,[4]],4,4,[[8,3,9,7,9],[1,7,2],3]],[3],[[[],6,0],5,[[7,6]]]] +[[[[5],9,[3,10,8,10],[6,1]],[4],1,9,0],[[6,7,10,[6,2]],9]] + +[[[5,[1,5,1,0],7,[]],5,[[10,6,7,1],[]],7,[[10,2,2],[2,8]]]] +[[[[7,0,3,3,3],8,[1,5],6,9]],[[6,9,3,[3],1]],[],[7,7,5]] + +[[],[],[]] +[[3,7,[],[10,0,[7,3]]],[[7],[[3,0,10],[1],7,[]],10],[1,0,[7,[3,10],9,6,[]],[],[[3,7,7,7,1],[10,8],[7,3,8,9,3]]],[[[0,4],9,1,[7,9,2,8],6],9,[[6,2,3],9,[4,4,8,10],[4],[3]]]] + +[[3,5],[10,1,[5,7,[5,3,7,10]],[[7,7,2,7,8],2,[10,4,6],5]],[[7,8,3,[5,10,4]],2],[[[4,2,1,10]],[[9,10],[1,7,9],10],[9,10],7],[]] +[[[[10,6,4],0,[3,5]]],[1,[3],6,[[0],9,4]],[6,[7,[4],[2,6],7,[6]],4],[[[10,7,5,7],5,1,5,5],2,[],[4]]] + +[[3,[],[[],6],1],[[],[0]]] +[[[8,[0,9,0,5,5],[]]],[8,4,[5,2,5,[9,0,2,7]],8],[[3,10,[2,2,8]],[1,[1,4,7,1],[0,5,3,9],5],[[6,2],[4],[1,7]],[[7,8,7,0],[2,8,3],[],1,9]],[[[]]],[]] + +[[5,[[4,5,10,8],10,5,9]],[],[[[4,2,2],9],5]] +[[6,[[3,0,1,10]],[9,[8,6,5,9,9],[5,0,7,10],4]]] + +[[[8],[],[[1,2,10],5],[[0],[8,1,6]],[[4,9,6,10,4],4,[2],[4,8,2,8],4]],[[[3],7,[6],0,[5,6]],[[8,9],7,4,6],[6],[[3],9,3],7]] +[[],[2,3,10]] + +[[2,[10],[10,[6,9,6,3],6,[0,8,9,6],[7,6]],[[2],[],0,[]],[[10],6,[3,9]]],[[6],3,[],5],[[[],10,3,[],6],[[6,0,7,7],3,[7,1],0,9],4]] +[[],[],[],[9]] + +[[],[2,1,4,4],[[[2,8],10,[2,7,2],[5],2]],[],[8,5,[4],[[4,4,0,8],7,1],[7,1]]] +[[[2,4,5,4,7],[1,3,8],[[7,1]],8,8],[2,[9,4,9],[2,10,7,[10,6]],5,7],[7],[],[[6,[],6,[],1],[[6,6],9,[8,10,2],[10,0,5]]]] + +[[[6,[4,8,2,8,10]],[[5,10,0],3,[1],7,[8,9,0,1]],[3,10,[],[7,2,1]],9],[0,[],[[],2,5,4,[10,9,4,4,10]],[1,7]],[[3,[],7,9,[2]],7,2,9],[]] +[[[]],[[3,6,[],6],5,[]],[8,[],[],9,[]],[]] + +[[7,[[],3],[8,[],[5,9]]],[[9,[2,5],[10,10,0]],[2,10],0,[6],9],[3,[9,8]],[[5,[0,10,4,1,9],9],[],[[8,8,1,4]],[[0,1,10],3,8],[[8],8,[4,1,9,9,8],[4,10]]]] +[[[[6,6,5,9],[0,2,6,10,9],4,3],4],[[[7,1]],6,[]],[[[9,9,2],[3],[3,6,5,1,1]],10,8]] + +[[[[6,10,2,9,8],9],[[9,7,6],4,[2,10,5],[]],8,4,[[7,1,8],[0],[5]]]] +[[8,[2,[2],8,[]]],[[3,[10,0,8,3,9]]],[[4],[],[[7,6,8,10],3,[7,6],[0,8]]]] + +[[8,[9,7],[[2,4],7,5,[]]],[[[0,3,8],2,[8]],8,6],[],[0,3,8,[10,[9,9,10],0],5],[2,7,6,[],3]] +[[],[4,8]] + +[[3,[7],[0],7]] +[[5,2]] + +[[[[1,8,8],[3,8],[1],4,9],[1,[4,10]],[]],[8,7,8,6],[],[[5,4,[6,10,8,1],2],[6],0],[0,[10],9,[0,10,[5]],[]]] +[[[6],5],[4,[],8],[3,10],[[[0,7],4,7,[7],[]],5,2],[]] + +[[[5,0]],[0,10,[5,1,4,[3,0,10,7,7],2]]] +[[[9,[6,8,4],7,10,4],10,4,0],[5,[8,10],9]] + +[[[]],[[[8],4,[8,9,10,3,4],[5,0,6,2,6],[10,0,0,10]],10,[[3,5,6]],[0,[0,10,9],[5]]],[6,[6,[6,9,6,2]],[[7]]]] +[[9],[[[],[5],8,[],1],[],[6,7,2],9],[5,9],[8,[[7,4]],1],[3,[4,[10,4,1,10],[2,0,4,5,4]],[[8,0,10,7,1],[],9,8],[]]] + +[[7],[[[3,8,1,1],[6,2,10],[5],[5]],10],[5,2,[3,[8,2,1,5],8,[10],[2,2,2,8]],[]],[[7,6,9,[0,6],3],[[1],[0,0,4,7,6]],8,[[8,5,1,4],[10,0,0],5],7]] +[[],[[[0,8,2,5],[8,4,6,7],0],9,3,[],6],[],[1,[0,[3,10,4,6,2],6,8,0],8,[[],[0,0,6,9],[0,1]],[[6,2],[5,10,1],3]],[[[3]],5,8]] + +[[],[[6,4,6,[0],[6,9,3]],[[],1],[[1,9],8,[],7],[3,2,3,[]],[7,[]]]] +[[9,1,3,[[3,0,9,4],[0,0,2,0,2],0,[2,10,0,4,7],[0]],[[10,8],[8,8],2,1]],[[[8,5],[]],[7,8,[7,6],[6,9]],2],[[2],[],6],[],[]] + +[[],[[[],[9,8,8],[]],[],1,[[3,0],7,3,4],1]] +[[8,8,1],[[6],8,[]]] + +[[[6,[7,7]]],[]] +[[3,[5,[4,0,1],[10,5,0,8],[10,5]],0,9]] + +[[1,[7,[5,7],[0,9]],[[10,3,2,3],[2,10,8],9],[[9,1,7,1],0,2,10,[]],7],[]] +[[3,[6,8,8,[10,5],9],[[],2,0,[8,0]],[[9,7],7,[],10,10]],[1,9,4,8]] + +[[[2,[6,1],4,[7,3,8,2,10]],[3],9,[2,[]]]] +[[4],[[[1,6],[9,4,5],[8,3],3]],[],[[9,2,[3],[2,1]]]] + +[[[[],0,[3,7]],0,[]],[],[[[3,0],6],[3,[7,9,3,4],5,3,[6,7,10,6]],2]] +[[[],9]] + +[[[[7,9,5,9,8]],[],9],[1,2,[],0],[1,4,9],[5,10],[7,0]] +[[[5,[2,7,5,0]],6],[5],[],[[3],[4],3,0],[[[],7],[9,9]]] + +[[],[[[9,7,8]],[[4,7,9],[7,0,4],3,6],3,[[2,10,2],[10,0,10,6,9],1],8],[4],[2,9,3,3]] +[[5,[2,0,7],7],[9,1,10,7,2],[[[1,2,5,4],5,6,[1]],8,0,2],[10]] + +[[[[1,1,10,1,8],0,7],2,7],[2,5,8,[[1,9,0,7,9],7,0,2,[8,1,0]],[[],[]]]] +[[10,2,3,0,[]],[[8,7,0,3],3],[],[[],1,6,4],[4,[],9,[7,3,5,[0,5,1,0],0],[[9],[1,1,8],6,8,7]]] + +[[7,6],[[8,[4,6],10],[0]],[]] +[[8,9,8],[0,8,9,0,[6,6]]] + +[[[[8,2,7]]],[9,[4,2],[5,1,9,[1,9,2,9,2],[8,3,1,5]]]] +[[10,[[6,2,8,2,9]],10,[[5,10,1],4,[6,3,9,8,6]],[8,7,[7,10,9,6],[4,7,3]]],[[3,5,6],[[0,1,8,0,0],[8,2,1],[1,10,8],7],[3,[0],6]],[],[[],[[10,1,0],2,[3,10,3],7],1]] + +[[[7,6],1,[[0,5,0],4],[[]],1]] +[[[0,5],[7],1,2]] + +[[[[0,5]],[[7],0]],[]] +[[[0,4],7,[5,7,5,0]],[],[],[0,[4,[2],6],0,[],[]],[10,7,[[5,5,7],[0],6,[1,9,2,7,4]],[[3,3,7,1,9]]]] + +[[[3,8,3,[5,3,6,5,0],7],[0,6,2,[4,9,0,1],10],5,3,3]] +[[[[7,7,2,3],6,6],[[2],[],[9,7],10,7],[1,8,[2,5],5,[2,3,7]],1],[]] + +[[[[8,1,2],3,[8,5,0,6,3],[8]],10],[[[8,2,10,4],[3,10],[0,2,2,9],[0,1,9,1,2],5],7,[],[]],[7,6,[4,2],9,[0]]] +[[[10,[6,3,5,8],6,8],[]],[[[1,8,1,7,10],9,[0,1,3],[0,7,7,6],[0,4]],[]],[3,8,9,[7]],[[[2,2,6,1,10],2,[10,2,2],1,[9]],2,4,7]] + +[[[[6,1,4,1],8,6,10,[5,3,9,10]],[[],4,0],9],[4,1,7,6],[[5,[3,8,1,4,6],1,[]],7]] +[[],[7,[],[1,[6,10,5,3],[1],7,[9,0,5,0,5]],[7,5,4,3],[[4,7,6],[],4,[8,9,2,9,3]]],[[0,[],[8,4,8],1],4,0,[6,[8,10,1,8,2],3,6]],[]] + +[[1,0]] +[[[5,9,[8,10,0,1,0]]]] + +[[[[9],2,1],4],[7,9,8,[[6,10],[10,5,8],[2,4,7],1],[5,[9,9,7,1,1]]],[[4,0],[[6,6],[5],4]]] +[[[],6,10,9],[4,2,3,[[1,4,4],8,[],[6,8,8,9,0],[5,0,5]]],[[],1,0,8,[8,5,3,[],[8,1,10,8]]]] + +[[2,[3]],[0]] +[[[[8,5,6,10,8]]],[4]] + +[[10,2,[],[]],[[7,[2,7,10]]]] +[[[[],[5]],2,[[9,6,9,10,7],8,8,[8,3,7,8]],[[],2],10]] + +[[[[0,6],[8,7],[],9],3],[],[6]] +[[],[],[0,[]],[[]],[1,10]] + +[[[[9,7,2,4]],9,[2,1]],[]] +[[[5],3,8,[[7,9,3,5,5],[2,8,7,4],[0,6,10]]],[[3,[0,8]],6,0,[10]]] + +[[8,[[],8],6,3,2],[3,8,[1,5,9]],[[3],[4],[[2,5,10,4],4,[3,8],[4,1]]],[0,[[9,6],[5,9,7,0],[3,5,10,7,6]],8]] +[[[9,[],7,[3,0],10],5],[5,4,5,5,7]] + +[[[3,8,[9,4,4],[2,3,6,2]],4],[[],8,[[1,6,1,4]]],[[[4,9,10,2,10]],6,[5],[2,[7,9,3,4,9],[7,4,7],4],9],[[],5,[9]],[[],1,0]] +[[[[6],[9,2,6],[1,6,6],[10,4,9,3,3]],[10,10,[10],[8,0,7],[7,5,8,4]],[[5,7],2]],[6,[],2]] + +[[4,4,3,7,[9,0,[]]]] +[[6,[[2,10,2],[5,4,1,1,9]],[[6,2,5,2,10],[4],[6,9],3,[5]],5],[[0,7,2],3,1,6],[]] + +[[[1]],[[[],[]],3],[[10,6],[7,8],[9,7],1]] +[[3],[[5,7,[1,4,10]]]] + +[[],[10],[0,[],[],[[0,8]]],[2,3,10]] +[[10,2],[1],[6,8,[[2],5,6,1],[4,[8,9,6,3],5]]] + +[[[9,[6,2],4]],[[[7,4,4,5,5],1,6,3,9]],[0]] +[[3,[1,8,7,[]]]] + +[[[2,4,[4,8,8,6],[10,1,5,7,5],1],6,3,[[9,10],[6,7,2,10]]],[[4,[3],3],0],[[],3],[3,3,6]] +[[0,1],[[8,[]],0,[],7,5]] + +[[8,2,[5,0,0,0],1],[5]] +[[[[8,9],[3],0,[10]],[[6,10],0,[10,7,0,8]],1,1],[[[],[5],[3,5,8,7,4],[]],[[0,6,1],[10,9],7]],[8,[[3],[9,3,9,4,5],1,0,3],9],[[[2],[3,6,7,3,9],[9,0,2],[4]],4,0]] + +[[0,[[4,0,3,0,10],[],0,9],[1,8,6,6,2],[[6,4],[],[0,3],[7,5]],[1]],[[7],[1],[9],10],[[],[[8,9],[4],3,[4]],[[2,4],[8,8],[3,3,3,3],[7,1,5],8]],[2,[5,[3,3],6,[3,3,9,1]]]] +[[[[1,3,5,7,1]],[],[4,7,[1,5,1],[3,10,3,3]],[],[2,9,[9,8],3]],[[[3],9,3,5,6],7,[[]],8],[8,5],[[6,7,10],2]] + +[[[2,[9,6,3]],5,[6]],[6,6,2,[0,8,[0,0,1],0,0],[]],[6,3,2],[],[[[0,9,10,4],[],5,[4,8],[2,7,6,4,10]],[[0,6,3,4]],[3,[4,7,9,2,8],7]]] +[[7,3,[[8,6,7,5]],0],[10,[8,[3,3,8,1],0,[9],[2,4]],[[],[6,2,0,7],[9]],6,[[9],4]]] + +[[[[8,10,8,6,10],8,6,[5,0,9]]],[[8,[2,3],9],5,6,3],[4,[]],[[[5,9,5],5,[],[4]],[6,[8,2,3],[5,6,5,5,7]]]] +[[8,[],6,[[7],[10,5,8,8],9,[]],[]]] + +[[[[9,5],3]],[[7],[4],9,[],5],[3,3],[4,[[1],0,3],4,[[1,9,5,2]],[[0,6,9],[]]]] +[[[6,10,3,[],[9,1,8]],0,5,[],[[3,7,10,4,1],9,[0,0,8]]]] + +[[[[8]],3,[1,7,5]],[[[3,1,2,8],[4,5],[1,0,4,2,9],1,[]],8,5,[5,[],[9,4,7,3,9],[0,10,10,6,0],[7,5,5,3]],6]] +[[0,[],7,4]] + +[[7,[10,5],[[7],[3,5,3,10],[0,3,1],9],4]] +[[],[[[3],1,[2,10],2],4,9,5]] + +[[[[10,1,4],1,[6,10,2,8,3],6],3],[[3,3]],[[[6,6],[8,7,1],10,5],1,7,[],10],[[],[0],7]] +[[],[3,4,[[3,5]]],[[[4],[1,7]],9,[2,0,8,9],1]] + +[[10,6,[5,[5,9,7],4]],[],[],[8,[[4],[1,6,10,5,8],3],1,[[1,1]],9]] +[[[10,[2,10,10,8]],[[2,8,10,2,6],8],[4,0,8,[7,5]],10]] + +[[[[0,5,5,10],[6,5]]],[[[3],[5,6,4,2,8],7,10],2,10],[],[[[5,9,1]],[],4]] +[[1,[[],[3,2,10,2,4]]],[6],[4,6,0,[5,[1,2],[10,4,3,8],7],[[2,4,4,5],[5],[8,3,10,7,3]]],[3,4]] + +[[[[8,0],[5,3,9,10],4]],[8,1,9,6],[6,2],[0,6,2,5,[[7,8,4],[10],[9,6,1],6]],[]] +[[],[3,[10]],[],[4,[[],[5,2],[],3],6]] + +[[],[],[[[3,8,9],1]],[[7,[4,5],[7,8,8,8],4],[9]],[]] +[[7,0,[[10,7],0],1,[10,6,[5,5,8],9]],[[7,[9,4]],[],5,2,[[6,1,8,9,0],[0,2,6],[3,10,3,0],[2,6,1,2,10],4]],[4,2,[4,7,4,[]]],[6,[[10,4,1],2,0,[10,8,7,1,0]],4,[[2,5,5,6]]]] + +[[[[4,1,4],[6,8,1],8,2,[0,3,4]],[9],[[1,10],[7],7,[0],2],6],[10,2,0],[6,[2,0]]] +[[10],[4,9,[6,4,[8,1,10,4],[10,9,8],6]],[],[[[8,1]],3]] + +[[],[10,6,[[4,1,5],[3,2,6],2,[8,1],[]],1],[3,5,9,[],6],[9,[[2,2,1],[3,4],[],8,[]],[]]] +[[1,[]],[],[[10,[]],[3,[4,10],4],5,[[5,6,3,9,4],[]],7],[5],[[10],[[8,10,6],2,[4,8,10,9],2,10],7,[8,[4,10,10,7,10],10],4]] + +[[7,[3,4,6,[4,3,4,7,3]]],[]] +[[],[[7],1,2,8,2],[],[0,[],1]] + +[[8,7],[4,[],4,[0,[9,6,7,4],5],[4,7,[9,10,9]]]] +[[],[8,5,9],[1],[],[[[3,1],[6,9,10,10],[6,3,9,5,2]],5]] + +[[6,0,6],[9,[2,2,8,[5,2,1,2,8],8],6,[],[3,0,[6,10,3,6,7],[]]],[7],[9,1,[6,7,[],[0,7,0,7],[7,3,10,7,4]],[]]] +[[6],[2,[[]],10,9],[6,[[],[8,9,7],[8,4]],7]] + +[[7,0,[10,[9,1,6,10,8],[2,8],[4,4,5],0],[[4,1,3,10],3,[3,5],[3,6,10,9]],[2,5,7,10,[6]]],[[],10,[[],3]]] +[[10,[[10,7]],[],9],[5,[[3,9,6],[10,2,3,8,5],6,3,[2,4]],[[6,8,8],4,9]],[],[],[8,[[3,2,6,3],[],4],1,[[0],[7]]]] + +[[[10,[1,5],[1,4,3,0,8],2,[9]],[],3],[[[8,0,5],[],2],[2],5,[1,6,[8,8,7],5]],[10,7,9],[]] +[[[[1],[8,0,0,8,1],[1],[8,4]],[2,[],[2],4,[1,8,9]],9],[],[[4,8,[8,0],[10,0,10,0,0]],1,2,1],[[6],5,6,9,6],[[[5],[7,4,9],2,[6]],9,[[10],6]]] + +[[0]] +[[3,[]],[[],[5,1]],[4,4],[[[9,5,10,9,3],6,[1,8],10],9],[3]] + +[[],[[[1,0,9],[1,4,1,0],[1,3],5,[9,10,5,1,0]],9,[[7,8,9],[6,5,0,8,6],10,[9,8,8],10],[8,4,[]],[]]] +[[]] + +[[6,[[5,6,6,6,6],4,[1],5,[9,2,4]],1,[2,9,[10,6,9,0],6,7]],[[8,7],9,2],[]] +[[[0,2,9],[0],7],[6,2,[[7,2,4,8,0]],[5,10,[6,1,8]],[]],[[[3,8]],0,9],[[[1,8,9,7],10],[[6,9,2]],[[],3],6,[[8,9,9]]]] + +[[],[10,[[9,8,6]],5],[[1,1,[10,4,6,7],[1,4,1,0,0],[7,8]],[[2,0,10,3,1],[],[1],[]],[10,[9,7,9,8,8],8],10],[],[[]]] +[[[3],[7,10]],[0]] + +[[0],[10,5],[9,[[],[7,2,7,9]],[[10],[9,9,8,10],[6],10,6],[[]]]] +[[[4,[4]]],[],[9,2,[[8,10,0,3]],[1,[10],[1,8]]]] + +[[[[1,7,4,3,2],4,8,[2,2,6],4],6,6],[3,3,3,1,5],[[1]],[10,[]],[2]] +[[[],3],[[],7],[8,0,8],[8,2]] + +[[4,9,1]] +[[[[8],7,[]],[3,1,0],5],[[7,7,1,[10,9,6,4],0]]] + +[[[],1,7]] +[[3],[5,6],[[[4],5,[],[10,5,3,7],1],[5,[],8,[7,8,9]],8],[5],[[],[9,7],[[5,8,5,4],9,5],[[2],5,[],4]]] + +[[[[],[]],7,[[4,4,10,6],[5,4,3,4],0,9,[1,8,3,2,1]]],[4,[[7,6,1],[5,2,6,10]]],[[[8,6,8,5],5,[0,2,8,9]],7,[[1,8,8],[]]],[9,0,[4,10,0],8,[]]] +[[[2,[3,7],3,[4,1,10],[8]],1],[[[10,3,9],[10],[6,2,4],[0,4,6]],[10,[10,2,1,4]],6],[[4],[],7,[3]],[[7,0,[0,8,10],[6,7,0]]]] + +[[[[4,7,8,3],[9,4,5]],6,[],7,[[0,3,4,0],[]]],[7,[3,[3,5,3],5,8,5]]] +[[6,8,[9,[],4],10],[],[[8,[7,6],6]],[6,7,[7,6,6,5,1],3]] + +[[],[[6,[6,3,0,9,10],2,7,0]],[[[6,4,0,0,7],1,0],8]] +[[],[0,5,[5,9,10,[6,0,1,0,5]],[[6,5,6,5]],[[0,1]]],[[[],8,[]],[[2,2],2,[1,4,6,9],[],10],5,6,[[3,0],4,7,[3,6,9]]],[[9]]] + +[[[[],6,[2],4]],[[10,[5,6]],9,[[0]]],[]] +[[3],[7,8,[[],7],4,1]] + +[[[],2]] +[[[9,4,[5,3,5]],6,4],[[[3,9,4,3,3],[2,9,0,2]],10],[[4,0,7,[7,4,9,4,3]],[[1,2],2,[],[],4],3],[[]]] + +[[[9,[2,9,1,6,2]],[5,0,[6],[2,7,10,10,9]],[2,10],[[5,3,10],6,[5,9,5],[]]],[1,[[0],[],[1],[9,9,4],[1,6,7,0]]]] +[[3,6,[4,7],7],[[2,[7,9,3],[5,5,9,8,5],4,[10,3,3]],4],[[3,4],[],7]] + +[[0,1],[[[6,6,3,5],[4],[4,10],[2,10,3,3]],7,[9,[8,7,6,8],0],[]],[],[[[6],[4,6,10,6,5],[0,4,9,10,4]],[],[[7,9,5,10,8],8,[10,6,7,5]]]] +[[[],0,[],6,2],[[3,0,3,[10,1,2,8,8],0],10,3,[4]]] + +[[4,4,[[9],[0,9,6,3]],[[6],7,9,[4,6,2,3]],[]],[[[7,2,4],[8,4,9,8,5],[0,10],[6,1,6]],5,[3],[[0,1,8,6,1],2,[],0]],[[2,[5,1,0,4,8]],[4,8,[10,5,8,5,0],6],10],[8]] +[[[[4,2],[],[5,7],9],2,[[9],[0,0,9,4],[9,8,8,0],3]],[]] + +[[0],[0],[[],[10,2,6,[],1],0,[[1],[6,9,6,7],[],0,2],[6,[6,10,5,5],[8,5,7,4]]],[],[]] +[[8,[[2,6,8,4],1]],[[],[],[[8,3,0,8],6],[3,[1,3],8]],[1,10,[2,2,[0,5,2,9],[4,10,4,8]]],[[8,9,6],[[],[4]]]] + +[[],[[7,[4,1,1,8]],[[1,7,6,0,1],[10,9,0,10,4],0,[],[4,8,10,0,3]],1,0]] +[[[0,[3]],[7,9,6,0,8]],[5],[[],4,2,[[],10]],[[],1,0]] + +[[4,2,[[4,3],2,[4,5,5,1,1]]],[[8,[7],[9,7],4,[0,3,8,6]],0],[5],[2,2,[10,10,[3,6,10,2,5],[],0]]] +[[[[6,3,2,2,6],1,[0,2,5,9,4],[6],[2]],9,[7,3]],[[[7],7,4,2,2],5,6,[3],3]] + +[[[[5,3,2],[4,9,8,4,5],[3,2,1,0]]],[[[10,5,7,1,8]]],[9,5,[[4,2,8],[0,6]],10,6],[[],6,7,[4,5,4],3],[[[5],[8,0,5,9],[10],[10,9]],[[],[7,8],[10,0]],1,[2]]] +[[[[5,3,10,2],[9,5,4,1,4],5,3],8,[8,8,[0],3,[]],2,[]],[2,2,[[],0],[7,5,0],7],[[[4],[1,8,6,9],[2,9,7,4],[5]],[4,1,[2,9,1,6,4],[7,8,2]],[10,5,0]],[]] + +[[[7,5,4],[3,1,[8,9,3,3,8],0]],[8],[2,[9,[4],3,6,[]],8,10,0],[10,2,[[0,10,10,0,3],[8,5,4,2,0],6],1,5],[[[0,0,6,10,7],[1,8]],9,[2,9],2,10]] +[[1],[[],2,[5],[[8,10],[6,0,8,5,10]],4],[5],[],[[],7]] + +[[[3,9],[9,[3,0,5,2]],[[2,9],[],9,5,[1,7]],[0,[7,4,2,3],7,[]],0],[6],[],[[1,1],[[7],9,[]],10,[0],0],[[9,[],[2,9],[5],5],8]] +[[[[0,6,7,5,2],[],3,[2,8,10,2],[3]],10,[[4,8,4,8,10]],[[10,3,3],[4,4],6]],[[6,5,7,[3,3],[]],0,[],[8],[[9,1],8,[9,6,4,9]]],[],[10,0,0,[[3,3,1,5],1,6,[],[9,2,0,4,5]],[[4,8,4,0]]]] + +[[6,1,[[5,4,4],8],[5,7,[],6,[4,7,10,7,10]]]] +[[8,1,5,[[0,8]]],[0,[2,[1,2,5,4,8],[],3],[[]],[],5],[9]] + +[[[[0,6,2]],2,[[7],7,7,10,[6,5]],[[1,10,0,3]]],[3,3,10,5,[6,[6,4],6,7]],[[[4],8,8,[5]]]] +[[0,[[2,3],[10,7,3,10,5],[4,4,2,1,0],[9,5,2,7]],[[9],[1,6],[3,5,8,4],[3,7,1,6,9]]],[2,[4,[]],[[9,10,6],7,10,[10,0,10,0]],[[7,7,5],9,6,4],[[7,6,0,5,0],8]],[]] + +[[],[[8,0,7,[5,9],[0,3]],[],10],[[4,2,[]],10,1],[]] +[[5,[9,9]],[8,[[0,4,2],7,[7,6,7],9],[[0],[],[10,2],[],8],0,0]] + +[0,10,10,8] +[0,10,10,8,2] + +[[7],[[],[9,9,[2,0],[1,7,0,5]],9,[6],9]] +[[7,4,3,10],[[8,[1,0,6]],[8,0,[],[0,4,7,6],[]]],[[[10,7,9],[7,1,1],[6,10,8,0,0]],10,[5,9,0],[[2,9,1,4]],[[3,2,10],[10,5]]]] + +[[10,7],[6,4,[[4],[8,8,4,2],[],[3,8],1]],[[3,[]],4,6],[[4,3,3,0]],[4,4,0]] +[[],[[4],2,1],[],[[],9],[7,3,10,9,8]] + +[] +[[8,[3,7],6,0],[[[5,3]]],[6,[1,2,[10,2,7,3,7]],[[4],[0,8],[4],[8,3,6,6],[8,0,7,9]],[]],[9]] + +[[[8],7,[]],[5,[],8,[[4,3,4],0,0,5],[[2]]],[1,4]] +[[2,8,9,7,[[8,9,8],[4,10],[8,7,10,2],[10,3,5],[9,4]]],[[6,5,[4,1,10,0,1]],3,8],[10,2,5,1]] + +[[[[6,6,0],[0,10,5]]],[[[],[]],[],[],[10,[3,0,10],[0,8,1,3,10]],9],[4,[],8,[[1]],1],[[[6]]]] +[[[7,[9,5,4,10,3]],0,[[8,0,7,1,0],4,5,[9,9,3,10,0],1]],[9]] + +[[[7,[7,3,0]]],[[],3],[],[[[5,7,5,9,1],[10,7],7,5,6],10],[]] +[[[3],0],[4,8,[[0],[],3,[0,8,5,5]]]] + +[[[[6,6]],[4,[]],[[],8],6],[],[8]] +[[[[8,8,5,0],[0]],[4,5,[8,1],4,[0,6,5,5]]],[],[[9],[7,3],8,9,6],[]] + +[[[[1,6,3,6],[1,4,7,5,5]],2,[6,3,7],6],[4],[9,0,6,[[5,7,5],0,2,[7,1,2,0,2]],5]] +[[[[9,6],[2],[6,3,4,0,8],2],[],4,[[7,9,2,9,3]]],[[[10,5],[5,3,0],0],8,[[1,6],[0,10,2],6]],[],[3],[2,7,10,10,8]] + +[[10,[[],[1],0],[]]] +[[[6,8,[5,4,8,5,4],1,2],9,7,[],[8,7,[],3,[8,7]]],[],[],[9,1],[[10]]] + +[[[[9,10,9],9,[7,4,6,0]],3],[[0,[2,6],[7,4,6,5],10,9],1,1,9,4],[5,0,[[],[2,5,3,9,2],8,[5,3,3,5],[10,4,10]]]] +[[],[]] + +[[0,10],[1,[4,[],2]],[9,3,3,0,[4,[],[],3]],[[5,[6,2,9,7,6],9,[]],8,8],[1,7,1,0,4]] +[[[],[10,2],5],[],[[0,6,[0,6]],0,1],[3,1,10,5]] + +[[9,[2,7],[[1,8,9]],[[5,5,8,7],[]]]] +[[10,[6,[],9]],[[7],[2,2,[7,3]],[[5,6,5]],5,[1]],[3,4,[]]] + +[[1,4,6,[]]] +[[1,3],[2],[6,6,0,[5,[],9]],[[2,[1,4,5],[6],[5,10,9,4]],[7,4,6,[2,6,8,9],[5,6]],[[8],[]],[[9,5,6],[]],8],[[0,[2,9,6,3],[5,3]]]] + +[[],[[[],7,[0],[1,7,2],[9,9]],[[1,3,8,6,1],8,[4,5],[7],0],[[9,0,9,5,4]],4]] +[[[8,[0,6,5,0],[9,2,1,8,5],0,2],2,[[9,9,3,0],9,2],[[6],4],[[8],2]],[8,2,[9,[6,4,3,1]],7],[3,[[],1,1],[[1],[],[4]],8,2],[1,10,[[5,7,10],10,[6,0,10,0,9]],8],[]] + +[[[[4,7,10],[]],[2,6,6,[2],[9,6]],[],1],[9,5,10,5,3],[[],5,3,1,[[9,7,10,10],[4,6,5,7],6,[10,1,6,7],[4,5,3]]]] +[[[6,[9],1],[3,[4],0]],[]] + +[[[4],5],[2,9,9,8,[7,[4],6,[10],[10,7,8,8]]],[9,2],[[3,[10,10,3,6],5,9,[8,1,1,3]]],[6,[5,[7,3]],9,3]] +[[[3,[3,2,10]]],[1,[[2,10,8,10,1],0,7]],[[8,[]],2,[6,2,[10,4,6,0,0],4],4,4]] + +[[5,[[],[10,1,10,6],5],[[0,9],[7,1,2,2],[1,6,1]],9]] +[[1,[7,1,[2,4,0],[4,4,8,6,6]]],[],[[6,[7,3,0],[1],[8,8,0,9],2],[[8,10,8,3],9,[6,5],[3,0,9,3,6]],[[],[],[],[1],0]],[9,9,10,7],[6]] + +[[],[[],0,2],[9,[]],[3,[[8,4,9,1,9]],[10,3,7],1,[5,[10,0,4],[8,8,4,10,8],[6,1,3]]]] +[[0,[]]] diff --git a/2022/day13/src/main.rs b/2022/day13/src/main.rs new file mode 100644 index 0000000..ecf5734 --- /dev/null +++ b/2022/day13/src/main.rs @@ -0,0 +1,374 @@ +use std::convert::TryFrom; +use std::{cmp, env, fmt, fs}; + +const VERBOSE: bool = false; + +type Pair = (Packet, Packet); +type Int = u32; + +#[derive(Clone, Eq, PartialEq)] +enum Datum { + Int(Int), + List(Vec), +} + +impl Datum { + fn is_int(&self) -> bool { + match self { + Datum::Int(_) => true, + _ => false, + } + } + + fn list_mut<'a>(&'a mut self) -> Option<&'a mut Vec> { + match self { + Datum::List(ref mut list) => Some(list), + _ => None, + } + } +} + +impl cmp::PartialOrd for Datum { + fn partial_cmp(&self, other: &Datum) -> Option { + if VERBOSE { + println!(" Compare {} vs {}", self, other); + } + match (self, other) { + (Datum::Int(self_value), Datum::Int(other_value)) => { + self_value.partial_cmp(other_value) + } + (Datum::Int(_), Datum::List(_)) => { + let self_list = Datum::List(vec![self.clone()]); + self_list.partial_cmp(other) + } + (Datum::List(_), Datum::Int(_)) => { + let other_list = Datum::List(vec![other.clone()]); + self.partial_cmp(&other_list) + } + (Datum::List(self_list), Datum::List(other_list)) => self_list.partial_cmp(other_list), + } + } +} + +impl fmt::Debug for Datum { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Datum::Int(value) => write!(f, "Int({})", value), + Datum::List(list) => { + let strings: Vec = list.iter().map(|d| format!("{}", d)).collect(); + write!(f, "[{}]", strings.join(",")) + } + } + } +} + +impl fmt::Display for Datum { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Datum::Int(value) => write!(f, "{}", value), + Datum::List(list) => { + let strings: Vec = list.iter().map(|d| format!("{}", d)).collect(); + write!(f, "[{}]", strings.join(",")) + } + } + } +} + +#[derive(Clone, Eq, PartialEq)] +struct Packet(Datum); + +impl TryFrom<&str> for Packet { + type Error = &'static str; + + fn try_from(line: &str) -> Result { + let mut parsing_stack = Vec::new(); + let mut has_trailing_list_item = false; + + for c in line.chars() { + match c { + '[' => parsing_stack.push(Datum::List(Vec::new())), + ']' => { + let top_item = parsing_stack + .pop() + .expect("Found ']' with no items on the stack"); + + if top_item.is_int() || has_trailing_list_item { + //println!("Pushing {:?} onto List", &top_item); + parsing_stack + .last_mut() + .expect("Found ']' and int on the stack, with no other items") + .list_mut() + .expect("Second item from top wasn't a List") + .push(top_item); + } else { + parsing_stack.push(top_item); + } + + has_trailing_list_item = true; + } + c if c.is_ascii_digit() => { + let c_digit: Int = c.to_digit(10).unwrap(); + match parsing_stack.last_mut() { + Some(Datum::Int(accumulated_int)) => { + *accumulated_int = *accumulated_int * 10 + c_digit + } + _ => parsing_stack.push(Datum::Int(c_digit)), + } + } + ',' => { + let completed_item = parsing_stack + .pop() + .expect("Found ',' with no items on the stack"); + parsing_stack + .last_mut() + .expect("Found ']' and int on the stack, with no other items") + .list_mut() + .expect("Second item from top wasn't a List") + .push(completed_item); + has_trailing_list_item = false; + } + _ => assert!(false, "Invalid character"), + } + } + + if has_trailing_list_item && parsing_stack.len() > 1 { + let top_item = parsing_stack + .pop() + .expect("Found ']' with no items on the stack"); + parsing_stack + .last_mut() + .expect("Found ']' and int on the stack, with no other items") + .list_mut() + .expect("Second item from top wasn't a List") + .push(top_item); + } + + assert!(parsing_stack.len() == 1); + + let top_item = parsing_stack + .pop() + .expect("Missing completed packet after parsing all characters on line"); + let packet = Packet(top_item); + + assert!(format!("{}", packet) == line); + + Ok(packet) + } +} + +impl cmp::Ord for Packet { + fn cmp(&self, other: &Packet) -> cmp::Ordering { + self.partial_cmp(other).unwrap() + } +} + +impl cmp::PartialOrd for Packet { + fn partial_cmp(&self, other: &Packet) -> Option { + if VERBOSE { + println!("Compare {} vs {}", self.0, other.0); + } + + let ordering = self.0.partial_cmp(&other.0); + if VERBOSE { + println!(" -> {:?}", ordering); + } + + ordering + } +} + +impl fmt::Debug for Packet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl fmt::Display for Packet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +fn last_two_packets(packets: &Vec) -> (Packet, Packet) { + let (_, last_two) = packets.split_at(packets.len() - 2); + + (last_two[0].clone(), last_two[1].clone()) +} + +fn main() { + let args: Vec = env::args().collect(); + + let filename = args.get(1).expect("Missing filename argument"); + + let file_contents = fs::read_to_string(&filename).expect("Unable to read file"); + let lines = file_contents.lines(); + + let mut pairs: Vec = Vec::new(); + let mut completed_packets: Vec = Vec::new(); + + for line in lines { + if line == "" { + pairs.push(last_two_packets(&completed_packets)); + continue; + } + + let packet = Packet::try_from(line).expect("Unable to parse packet!"); + if VERBOSE { + println!("Completed packet! {}", &packet); + } + + completed_packets.push(packet); + } + + pairs.push(last_two_packets(&completed_packets)); + + let pairs_in_right_order = pairs + .iter() + .enumerate() + .map(|(i, p)| (i + 1, p)) + .filter(|(_, pair)| { + if let Some(ordering) = pair.0.partial_cmp(&pair.1) { + ordering == cmp::Ordering::Less + } else { + false + } + }) + .collect::>(); + + println!("----- Pairs in the Right Order -----"); + for (i, p) in &pairs_in_right_order { + println!("{} ->\n {}\n {}", i, p.0, p.1); + } + println!("{} pairs", pairs.len()); + println!( + "Sum of indicies of pairs in correct order: {}", + &pairs_in_right_order.iter().map(|(i, _)| i).sum::() + ); + + println!("----- Divider Packets -----"); + let divider_a = Packet(Datum::List(vec![Datum::List(vec![Datum::Int(2)])])); + let divider_b = Packet(Datum::List(vec![Datum::List(vec![Datum::Int(6)])])); + + completed_packets.push(divider_a.clone()); + completed_packets.push(divider_b.clone()); + completed_packets.sort(); + + dbg!(&completed_packets); + + let product_of_indexes_of_divider_packets: usize = completed_packets + .iter() + .enumerate() + .filter(|(_, p)| **p == divider_a || **p == divider_b) + .map(|(i, _)| i + 1) + .product(); + println!("Product of indexes of divider packets: {product_of_indexes_of_divider_packets}"); +} + +#[cfg(test)] +mod test { + use crate::{Datum, Packet}; + use std::cmp::Ordering; + + #[test] + fn shorter_vecs_are_less() { + assert!(vec![].partial_cmp(&vec![3]).unwrap() == Ordering::Less); + assert!(vec![1, 2, 3].partial_cmp(&vec![1, 2, 3, 4]).unwrap() == Ordering::Less); + } + + #[test] + fn single_empty_list() { + let packet = Packet::try_from("[]").unwrap(); + assert!(packet == Packet(Datum::List(vec![]))); + } + + #[test] + fn three_int_list() { + let packet = Packet::try_from("[1,2,3]").unwrap(); + assert!( + packet + == Packet(Datum::List(vec![ + Datum::Int(1), + Datum::Int(2), + Datum::Int(3), + ])), + ); + } + + #[test] + fn one_embedded_empty_list() { + let packet = Packet::try_from("[1,2,[],3,4]").unwrap(); + assert!( + packet + == Packet(Datum::List(vec![ + Datum::Int(1), + Datum::Int(2), + Datum::List(vec![]), + Datum::Int(3), + Datum::Int(4), + ])), + ); + } + + #[test] + fn double_embedded_list() { + let packet = Packet::try_from("[[9,[8,7,8],[]]]").unwrap(); + assert!( + packet + == Packet(Datum::List(vec![Datum::List(vec![ + Datum::Int(9), + Datum::List(vec![Datum::Int(8), Datum::Int(7), Datum::Int(8)]), + Datum::List(vec![]) + ])])) + ); + } + + #[test] + fn first_input_packet() { + let packet = Packet::try_from("[[[7,8],5],[[9,[8,7,8],[],[2,4,10,10],[2,10,8,3,3]],[],[[6,1,10],[],3,6],[3]],[],[4],[3,0,1,10]]").unwrap(); + assert!( + packet + == Packet(Datum::List(vec![ + Datum::List(vec![ + Datum::List(vec![Datum::Int(7), Datum::Int(8)]), + Datum::Int(5) + ]), + Datum::List(vec![ + Datum::List(vec![ + Datum::Int(9), + Datum::List(vec![Datum::Int(8), Datum::Int(7), Datum::Int(8)]), + Datum::List(vec![]), + Datum::List(vec![ + Datum::Int(2), + Datum::Int(4), + Datum::Int(10), + Datum::Int(10) + ]), + Datum::List(vec![ + Datum::Int(2), + Datum::Int(10), + Datum::Int(8), + Datum::Int(3), + Datum::Int(3) + ]) + ]), + Datum::List(vec![]), + Datum::List(vec![ + Datum::List(vec![Datum::Int(6), Datum::Int(1), Datum::Int(10)]), + Datum::List(vec![]), + Datum::Int(3), + Datum::Int(6) + ]), + Datum::List(vec![Datum::Int(3)]) + ]), + Datum::List(vec![]), + Datum::List(vec![Datum::Int(4)]), + Datum::List(vec![ + Datum::Int(3), + Datum::Int(0), + Datum::Int(1), + Datum::Int(10) + ]) + ])) + ); + } +} diff --git a/2022/day14/Cargo.toml b/2022/day14/Cargo.toml new file mode 100644 index 0000000..85aa832 --- /dev/null +++ b/2022/day14/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day14" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2022/day14/example.txt b/2022/day14/example.txt new file mode 100644 index 0000000..4e87bb5 --- /dev/null +++ b/2022/day14/example.txt @@ -0,0 +1,2 @@ +498,4 -> 498,6 -> 496,6 +503,4 -> 502,4 -> 502,9 -> 494,9 diff --git a/2022/day14/src/main.rs b/2022/day14/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/2022/day14/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +}