generated from janezicmatej/aoc-template
Compare commits
2 Commits
00000160a1
...
00000180c1
Author | SHA1 | Date |
---|---|---|
Matej Janezic | 00000180c1 | |
Matej Janezic | 0000017058 |
|
@ -0,0 +1,5 @@
|
|||
LLR
|
||||
|
||||
AAA = (BBB, BBB)
|
||||
BBB = (AAA, ZZZ)
|
||||
ZZZ = (ZZZ, ZZZ)
|
|
@ -0,0 +1,10 @@
|
|||
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)
|
|
@ -0,0 +1,95 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use aoc::lcm;
|
||||
|
||||
pub fn part_one(input: &str) -> Option<u32> {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
let (directions, map_data) = input.split_once("\n\n")?;
|
||||
for line in map_data.lines() {
|
||||
let (k, v) = line.split_once(" = ")?;
|
||||
let v = v.strip_prefix('(')?;
|
||||
let v = v.strip_suffix(')')?;
|
||||
let (l, r) = v.split_once(", ")?;
|
||||
|
||||
*map.entry(k).or_default() = (l, r);
|
||||
}
|
||||
|
||||
let mut counter = 0;
|
||||
let mut loc = "AAA";
|
||||
|
||||
for d in directions.chars().cycle() {
|
||||
if loc == "ZZZ" {
|
||||
break;
|
||||
}
|
||||
|
||||
counter += 1;
|
||||
let (l, r) = map[loc];
|
||||
|
||||
match d {
|
||||
'L' => loc = l,
|
||||
'R' => loc = r,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
Some(counter)
|
||||
}
|
||||
|
||||
pub fn part_two(input: &str) -> Option<u64> {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
let (directions, map_data) = input.split_once("\n\n")?;
|
||||
for line in map_data.lines() {
|
||||
let (k, v) = line.split_once(" = ")?;
|
||||
let v = v.strip_prefix('(')?;
|
||||
let v = v.strip_suffix(')')?;
|
||||
let (l, r) = v.split_once(", ")?;
|
||||
|
||||
*map.entry(k).or_default() = (l, r);
|
||||
}
|
||||
|
||||
let mut res = 1;
|
||||
|
||||
for k in map.keys().filter(|x| x.ends_with('A')) {
|
||||
let mut location = *k;
|
||||
|
||||
for (i, d) in directions.chars().cycle().enumerate() {
|
||||
let (l, r) = map[location];
|
||||
|
||||
location = match d {
|
||||
'L' => l,
|
||||
'R' => r,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
if location.ends_with('Z') {
|
||||
res = lcm(res, i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(res as u64)
|
||||
}
|
||||
|
||||
aoc::solution!(8);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_part_one() {
|
||||
assert_eq!(
|
||||
part_one(&aoc::template::read_file_part("examples", 8, 1)),
|
||||
Some(6)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_part_two() {
|
||||
assert_eq!(
|
||||
part_two(&aoc::template::read_file_part("examples", 8, 2)),
|
||||
Some(6)
|
||||
);
|
||||
}
|
||||
}
|
24
src/lib.rs
24
src/lib.rs
|
@ -1,4 +1,28 @@
|
|||
#![feature(pattern)]
|
||||
|
||||
use std::mem::swap;
|
||||
|
||||
pub mod parsers;
|
||||
pub mod template;
|
||||
|
||||
pub fn lcm(first: usize, second: usize) -> usize {
|
||||
first * second / gcd(first, second)
|
||||
}
|
||||
|
||||
pub fn gcd(first: usize, second: usize) -> usize {
|
||||
let mut max = first;
|
||||
let mut min = second;
|
||||
if min > max {
|
||||
swap(&mut min, &mut max)
|
||||
}
|
||||
|
||||
loop {
|
||||
let res = max % min;
|
||||
if res == 0 {
|
||||
return min;
|
||||
}
|
||||
|
||||
max = min;
|
||||
min = res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,3 +54,14 @@ pub fn read_file(folder: &str, day: u8) -> String {
|
|||
let f = fs::read_to_string(filepath);
|
||||
f.expect("could not open input file").trim().to_string()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn read_file_part(folder: &str, day: u8, part: u8) -> String {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let filepath = cwd
|
||||
.join("data")
|
||||
.join(folder)
|
||||
.join(format!("{day:02}-{part}.txt"));
|
||||
let f = fs::read_to_string(filepath);
|
||||
f.expect("could not open input file").trim().to_string()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue