Naive day 8 added.
This commit is contained in:
139
src/days/day8.rs
Normal file
139
src/days/day8.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
use std::{path::Path, str::FromStr, collections::HashMap};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{error::AdventError, input::read_into};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
impl FromStr for Direction {
|
||||
type Err = AdventError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"L" => Ok(Direction::Left),
|
||||
"R" => Ok(Direction::Right),
|
||||
_ => Err(AdventError(format!("Unexpected input for Direction: {}", s))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Node {
|
||||
left: String,
|
||||
right: String
|
||||
}
|
||||
|
||||
struct BaseMap {
|
||||
catalog: HashMap<String, Node>,
|
||||
directions: Vec<Direction>,
|
||||
start: Vec<String>,
|
||||
}
|
||||
|
||||
trait Step {
|
||||
fn take_step(&self, current: &String, direction: &Direction) -> Result<String, AdventError>;
|
||||
}
|
||||
|
||||
impl Step for BaseMap {
|
||||
fn take_step(&self, current: &String, direction: &Direction) -> Result<String, AdventError> {
|
||||
if let Some(node) = self.catalog.get(current) {
|
||||
Ok(match direction {
|
||||
Direction::Left => node.left.clone(),
|
||||
Direction::Right => node.right.clone()
|
||||
})
|
||||
}
|
||||
else {
|
||||
Err(AdventError(format!("Node missing in catalog for: {}", current)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Map1(BaseMap);
|
||||
struct Map2(BaseMap);
|
||||
|
||||
impl FromStr for BaseMap {
|
||||
type Err = AdventError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut lines = s.lines();
|
||||
let directions = &lines.next().unwrap().chars().map(|c| {
|
||||
Ok(Direction::from_str(format!("{}", c).as_str())?)
|
||||
}).collect::<Result<Vec<Direction>, AdventError>>()?;
|
||||
|
||||
let mut nodes = HashMap::<String, Node>::new();
|
||||
for line in lines.skip(1) {
|
||||
let name = &line[0..3];
|
||||
let left = &line[7..10];
|
||||
let right = &line[12..15];
|
||||
|
||||
nodes.insert(name.to_string(), Node{left: left.to_string(), right: right.to_string()});
|
||||
};
|
||||
|
||||
Ok(BaseMap{
|
||||
catalog: nodes,
|
||||
directions: directions.to_vec(),
|
||||
start: vec![]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Map1 {
|
||||
type Err = AdventError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut base_map = BaseMap::from_str(s)?;
|
||||
base_map.start.push("AAA".to_string());
|
||||
Ok(Map1(base_map))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Map2 {
|
||||
type Err = AdventError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut base_map = BaseMap::from_str(s)?;
|
||||
base_map.start = base_map.catalog.keys().filter(|x| x.ends_with('A')).map(|x| x.clone()).collect_vec();
|
||||
Ok(Map2(base_map))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_end1(node: &String) -> bool {
|
||||
node == &"ZZZ".to_string()
|
||||
}
|
||||
|
||||
fn is_end2(nodes: &Vec<String>) -> bool {
|
||||
nodes.iter().all(|x| {
|
||||
x.ends_with('Z')
|
||||
})
|
||||
}
|
||||
|
||||
pub fn one() -> Result<u32, AdventError> {
|
||||
let map = read_into::<Map1>(Path::new("resources/input8.txt"))?.0;
|
||||
let mut node = map.start[0].clone();
|
||||
for (i, direction) in map.directions.iter().cycle().enumerate() {
|
||||
node = map.take_step(&node, direction)?;
|
||||
if is_end1(&node) {
|
||||
return Ok(i as u32 +1);
|
||||
}
|
||||
}
|
||||
panic!("Cycle iterator should never terminate")
|
||||
}
|
||||
|
||||
pub fn two() -> Result<u32, AdventError> {
|
||||
let map = read_into::<Map2>(Path::new("resources/input8.txt"))?.0;
|
||||
let mut nodes = map.start.clone();
|
||||
for (i, direction) in map.directions.iter().cycle().enumerate() {
|
||||
nodes = nodes.iter().map(|current| {
|
||||
map.take_step(¤t, direction)
|
||||
}).collect::<Result<Vec<String>,AdventError>>()?.iter().unique().map(|x| x.clone()).collect_vec();
|
||||
|
||||
if is_end2(&nodes) {
|
||||
return Ok(i as u32 +1);
|
||||
}
|
||||
}
|
||||
panic!("Cycle iterator should never terminate")
|
||||
}
|
||||
@@ -4,4 +4,5 @@ pub mod day3;
|
||||
pub mod day4;
|
||||
pub mod day5;
|
||||
pub mod day6;
|
||||
pub mod day7;
|
||||
pub mod day7;
|
||||
pub mod day8;
|
||||
@@ -18,6 +18,7 @@ fn main() -> Result<(), AdventError> {
|
||||
(day5::one as fn() -> Result<u32, AdventError>, day5::two as fn() -> Result<u32, AdventError>),
|
||||
(day6::one as fn() -> Result<u32, AdventError>, day6::two as fn() -> Result<u32, AdventError>),
|
||||
(day7::one as fn() -> Result<u32, AdventError>, day7::two as fn() -> Result<u32, AdventError>),
|
||||
(day8::one as fn() -> Result<u32, AdventError>, day8::two as fn() -> Result<u32, AdventError>),
|
||||
];
|
||||
|
||||
if env::args().len() == 1 {
|
||||
|
||||
Reference in New Issue
Block a user