Skip to content

Commit

Permalink
day 8
Browse files Browse the repository at this point in the history
  • Loading branch information
nottu committed Dec 8, 2023
1 parent e7cc3c8 commit 474bce1
Show file tree
Hide file tree
Showing 5 changed files with 959 additions and 0 deletions.
139 changes: 139 additions & 0 deletions src/bin/day8.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use std::collections::HashMap;

fn main() {
let input = include_str!("day8/input.txt");
dbg!(part1(input));

let input = include_str!("day8/input.txt");
dbg!(part2(input));
}

#[test]
fn day8_test_part1() {
let input = include_str!("day8/test_input.txt");
assert_eq!(part1(input), "2");

let input = include_str!("day8/test_input2.txt");
assert_eq!(part1(input), "6");
}

fn part1(input: &str) -> String {
let (directions, map) = parse_input(input);
let num_directions = directions.len();
let mut curr_node = "AAA".to_string();
let goal_node = "ZZZ".to_string();

let mut step_count = 0;
while curr_node != goal_node {
let next_dirs = &map[&curr_node];
curr_node = match directions[step_count % num_directions] {
Direction::Left => &next_dirs.left,
Direction::Right => &next_dirs.right,
}
.to_string();
step_count += 1;
}

step_count.to_string()
}

#[derive(Debug)]
struct Node {
left: String,
right: String,
}

#[derive(Debug, PartialEq, Eq)]
enum Direction {
Left,
Right,
}

impl From<char> for Direction {
fn from(value: char) -> Self {
match value {
'R' => Self::Right,
'L' => Self::Left,
_ => panic!("???"),
}
}
}

fn parse_input(input: &str) -> (Vec<Direction>, HashMap<String, Node>) {
let mut input_lines = input.lines();
let directions: Vec<Direction> = input_lines
.next()
.unwrap()
.chars()
.map(Direction::from)
.collect();
// one empty line
input_lines.next();
// parse nodes
let node_data = input_lines.map(|l| {
let mut node = l.split('=').map(|i| i.trim());
let node_name = node.next().unwrap();
let next_nodes = node.next().unwrap().replace(['(', ')'], "");
let next_nodes: Vec<_> = next_nodes.split(',').map(|n| n.trim()).collect();
(
node_name.to_owned(),
next_nodes[0].to_owned(),
next_nodes[1].to_owned(),
)
});
let mut node_map = HashMap::new();
for data in node_data {
node_map.insert(
data.0.to_owned(),
Node {
left: data.1,
right: data.2,
},
);
}
(directions, node_map)
}

#[test]
fn day8_test_part2() {
let input = include_str!("day8/test_input3.txt");
assert_eq!(part2(input), "6")
}

fn part2(input: &str) -> String {
let (directions, map) = parse_input(input);
let curr_nodes: Vec<String> = map
.keys()
.filter(|k| k.ends_with('A'))
.map(|n| n.to_owned())
.collect();

dbg!(&curr_nodes);

curr_nodes
.into_iter()
.map(|n| get_steps(n, &map, &directions))
.fold(1, num::integer::lcm)
.to_string()
}

fn get_steps(
mut curr_node: String,
map: &HashMap<String, Node>,
directions: &Vec<Direction>,
) -> usize {
let mut step_count = 0;
let num_directions = directions.len();

while !curr_node.ends_with('Z') {
let next_dirs = &map[&curr_node];
curr_node = match directions[step_count % num_directions] {
Direction::Left => &next_dirs.left,
Direction::Right => &next_dirs.right,
}
.to_string();
step_count += 1;
}

step_count
}
Loading

0 comments on commit 474bce1

Please # to comment.