diff --git a/old/day08/Cargo.lock b/old/day08/Cargo.lock deleted file mode 100644 index 1d4626c..0000000 --- a/old/day08/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "day08" -version = "0.1.0" diff --git a/old/day08/Cargo.toml b/old/day08/Cargo.toml deleted file mode 100644 index 7156aba..0000000 --- a/old/day08/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "day08" -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/old/day08/src/main.rs b/old/day08/src/main.rs deleted file mode 100644 index a3ceb11..0000000 --- a/old/day08/src/main.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::{fs, collections::{HashMap, VecDeque}}; - -fn main() { - let input = fs::read_to_string("input.txt").unwrap(); - let input: Vec<_> = input.split("\n\n").collect(); - let (directions, nodes) = (input[0], input[1]); - let directions: Vec<_> = directions.chars().map(|char| { - match char { - 'L' => Direction::Left, - 'R' => Direction::Right, - _ => panic!("Invalid direction!") - } - }).collect(); - - let nodes: HashMap<&str, (&str, &str)> = nodes.split('\n') - .map(|line| { - let line = line.split('=').map(|x| x.trim()).collect::>(); - let children: Vec<_> = line[1].trim_matches(|c| c == '(' || c == ')').split(", ").collect(); - (line[0], (children[0], children[1])) - }).collect(); - - let starts: Vec<_> = nodes.keys().filter(|x| x.ends_with('A')).collect(); - let dists: Vec<_> = starts.iter().map(|start| dist(&start, &directions, &nodes)).collect(); - - let gcf = gcf(&dists); - - let step_count = gcf * dists.iter().map(|value| value / gcf).product::(); - - println!("{:?}", step_count); -} - -fn gcf(values: &Vec) -> i64 { - let mut gcf = values[0]; - - for val in values { - gcf = find_gcf(gcf, *val); - - if gcf == 1 { - return 1; - } - } - - gcf -} - -fn find_gcf(a: i64, b: i64) -> i64 { - if a == 0 { - return b; - } - - find_gcf(b % a, a) -} - -fn dist(cur_node: &str, directions: &Vec, nodes: &HashMap<&str, (&str, &str)>) -> i64 { - let mut cur_node = cur_node; - let mut step_queue: VecDeque = VecDeque::from(directions.clone()); - let mut step_count = 0; - - while !cur_node.ends_with('Z') { - step_count += 1; - let cur_step = step_queue.pop_front().unwrap(); - match cur_step { - Direction::Left => cur_node = nodes[cur_node].0, - Direction::Right => cur_node = nodes[cur_node].1, - } - step_queue.push_back(cur_step); - } - - return step_count; -} - -#[derive(Clone)] -#[derive(Debug)] -enum Direction { - Left, - Right -} - - -// use std::{fs, collections::{HashMap, VecDeque}}; - -// fn main() { -// let input = fs::read_to_string("input.txt").unwrap(); -// let input: Vec<_> = input.split("\n\n").collect(); -// let (directions, nodes) = (input[0], input[1]); -// let directions: Vec<_> = directions.chars().map(|char| { -// match char { -// 'L' => Direction::Left, -// 'R' => Direction::Right, -// _ => panic!("Invalid direction!") -// } -// }).collect(); - -// let nodes: HashMap<&str, (&str, &str)> = nodes.split('\n') -// .map(|line| { -// let line = line.split('=').map(|x| x.trim()).collect::>(); -// let children: Vec<_> = line[1].trim_matches(|c| c == '(' || c == ')').split(", ").collect(); -// (line[0], (children[0], children[1])) -// }).collect(); - -// let mut cur_node = "AAA"; -// let mut step_queue = VecDeque::from(directions); -// let mut step_count = 0; - -// while cur_node != "ZZZ" { -// step_count += 1; -// let cur_step = step_queue.pop_front().unwrap(); -// match cur_step { -// Direction::Left => cur_node = nodes[cur_node].0, -// Direction::Right => cur_node = nodes[cur_node].1, -// } -// step_queue.push_back(cur_step); -// } - -// println!("{:?}", step_count); -// } - -// #[derive(Debug)] -// enum Direction { -// Left, -// Right -// } diff --git a/src/day8.rs b/src/day8.rs new file mode 100644 index 0000000..af79c55 --- /dev/null +++ b/src/day8.rs @@ -0,0 +1,150 @@ +use std::collections::{HashMap, VecDeque}; + +use aoc_runner_derive::{aoc, aoc_generator}; +#[aoc_generator(day8)] +fn parse(input: &str) -> (Vec, HashMap) { + let input: Vec<_> = input.split("\n\n").collect(); + let (directions, nodes) = (input[0], input[1]); + let directions: Vec = directions.chars().map(|char| { + match char { + 'L' => Direction::Left, + 'R' => Direction::Right, + _ => panic!("Invalid direction!") + } + }).collect::>(); + + let nodes: HashMap = nodes.split('\n') + .map(|line| { + let line = line.split('=').map(|x| x.trim()).collect::>(); + let children = line[1].trim_matches(|c| c == '(' || c == ')').split(", ").collect::>(); + (line[0].into(), (children[0].into(), children[1].into())) + }).collect(); + + (directions, nodes) +} + +#[derive(Debug, Clone)] +enum Direction { + Left, + Right +} + +#[aoc(day8, part1)] +fn part1((directions, nodes): &(Vec, HashMap)) -> i64 { + let mut cur_node = "AAA"; + let mut step_queue = VecDeque::from(directions.clone()); + let mut step_count = 0; + + while cur_node != "ZZZ" { + step_count += 1; + let cur_step = step_queue.pop_front().unwrap(); + match cur_step { + Direction::Left => cur_node = &nodes[cur_node].0, + Direction::Right => cur_node = &nodes[cur_node].1, + } + step_queue.push_back(cur_step); + } + println!("{}", step_count); + step_count +} + +#[aoc(day8, part2)] +fn part2((directions, nodes): &(Vec, HashMap)) -> i64 { + let starts: Vec<_> = nodes.keys().filter(|x| x.ends_with('A')).collect(); + let dists: Vec<_> = starts.iter().map(|start| dist(&start, &directions, nodes)).collect(); + + let gcf = gcf(&dists); + + let step_count = gcf * dists.iter().map(|value| value / gcf).product::(); + + step_count +} + +fn gcf(values: &Vec) -> i64 { + let mut gcf = values[0]; + + for val in values { + gcf = find_gcf(gcf, *val); + + if gcf == 1 { + return 1; + } + } + + gcf +} + +fn find_gcf(a: i64, b: i64) -> i64 { + if a == 0 { + return b; + } + + find_gcf(b % a, a) +} + +fn dist(cur_node: &str, directions: &Vec, nodes: &HashMap) -> i64 { + let mut cur_node = cur_node; + let mut step_queue: VecDeque = VecDeque::from(directions.clone()); + let mut step_count = 0; + + while !cur_node.ends_with('Z') { + step_count += 1; + let cur_step = step_queue.pop_front().unwrap(); + match cur_step { + Direction::Left => cur_node = &nodes[cur_node].0, + Direction::Right => cur_node = &nodes[cur_node].1, + } + step_queue.push_back(cur_step); + } + + return step_count; +} + + +#[cfg(test)] +mod tests { + use super::*; + + const EX_1: &str = r"RL + +AAA = (BBB, CCC) +BBB = (DDD, EEE) +CCC = (ZZZ, GGG) +DDD = (DDD, DDD) +EEE = (EEE, EEE) +GGG = (GGG, GGG) +ZZZ = (ZZZ, ZZZ)"; + + const EX_2: &str = r"LLR + +AAA = (BBB, BBB) +BBB = (AAA, ZZZ) +ZZZ = (ZZZ, ZZZ)"; + + const EX_3: &str = r"LR + +11A = (11B, XXX) +11B = (XXX, 11Z) +11Z = (11B, XXX) +22A = (22B, XXX) +22B = (22C, 22C) +22C = (22Z, 22Z) +22Z = (22B, 22B) +XXX = (XXX, XXX)"; + + + #[test] + fn part1_example1() { + assert_eq!(part1(&parse(EX_1)), 2); + } + + #[test] + fn part1_example2() { + assert_eq!(part1(&parse(EX_2)), 6); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse(EX_3)), 6); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 64d52d5..3341d48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day8; mod day7; mod day6; mod day5;