update day8
This commit is contained in:
parent
1c4bf97e07
commit
831d97d5b4
7
old/day08/Cargo.lock
generated
7
old/day08/Cargo.lock
generated
@ -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"
|
|
@ -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]
|
|
@ -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::<Vec<_>>();
|
|
||||||
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::<i64>();
|
|
||||||
|
|
||||||
println!("{:?}", step_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gcf(values: &Vec<i64>) -> 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<Direction>, nodes: &HashMap<&str, (&str, &str)>) -> i64 {
|
|
||||||
let mut cur_node = cur_node;
|
|
||||||
let mut step_queue: VecDeque<Direction> = 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::<Vec<_>>();
|
|
||||||
// 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
|
|
||||||
// }
|
|
150
src/day8.rs
Normal file
150
src/day8.rs
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
#[aoc_generator(day8)]
|
||||||
|
fn parse(input: &str) -> (Vec<Direction>, HashMap<String, (String, String)>) {
|
||||||
|
let input: Vec<_> = input.split("\n\n").collect();
|
||||||
|
let (directions, nodes) = (input[0], input[1]);
|
||||||
|
let directions: Vec<Direction> = directions.chars().map(|char| {
|
||||||
|
match char {
|
||||||
|
'L' => Direction::Left,
|
||||||
|
'R' => Direction::Right,
|
||||||
|
_ => panic!("Invalid direction!")
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let nodes: HashMap<String, (String, String)> = nodes.split('\n')
|
||||||
|
.map(|line| {
|
||||||
|
let line = line.split('=').map(|x| x.trim()).collect::<Vec<_>>();
|
||||||
|
let children = line[1].trim_matches(|c| c == '(' || c == ')').split(", ").collect::<Vec<_>>();
|
||||||
|
(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<Direction>, HashMap<String, (String, String)>)) -> 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<Direction>, HashMap<String, (String, String)>)) -> 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::<i64>();
|
||||||
|
|
||||||
|
step_count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gcf(values: &Vec<i64>) -> 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<Direction>, nodes: &HashMap<String, (String, String)>) -> i64 {
|
||||||
|
let mut cur_node = cur_node;
|
||||||
|
let mut step_queue: VecDeque<Direction> = 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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod day8;
|
||||||
mod day7;
|
mod day7;
|
||||||
mod day6;
|
mod day6;
|
||||||
mod day5;
|
mod day5;
|
||||||
|
Loading…
Reference in New Issue
Block a user