diff --git a/src/common/mod.rs b/src/common/mod.rs index 3a2379d..35c9c55 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -3,6 +3,7 @@ pub mod direction; pub mod file; pub mod helper; pub mod math; +pub mod name; pub mod parser; pub mod pos; pub mod turn; diff --git a/src/common/name.rs b/src/common/name.rs new file mode 100644 index 0000000..bc79e69 --- /dev/null +++ b/src/common/name.rs @@ -0,0 +1,30 @@ +use std::{fmt::Display, ops::Deref, rc::Rc}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Name(Rc); + +impl Name { + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl Deref for Name { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From<&str> for Name { + fn from(value: &str) -> Self { + Self(Rc::from(value)) + } +} + +impl Display for Name { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} diff --git a/src/days/day01/mod.rs b/src/days/day01/mod.rs index 6419b99..9fb7835 100644 --- a/src/days/day01/mod.rs +++ b/src/days/day01/mod.rs @@ -1,12 +1,9 @@ +use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; use itertools::Itertools; use std::num::ParseIntError; - use thiserror::Error; -use crate::common::file::split_lines; - -use super::template::{DayTrait, ResultType}; - pub struct Day; const DAY_NUMBER: usize = 1; diff --git a/src/days/day02/mod.rs b/src/days/day02/mod.rs index 9f19241..2a6393a 100644 --- a/src/days/day02/mod.rs +++ b/src/days/day02/mod.rs @@ -1,8 +1,6 @@ -use std::cmp::Ordering; - -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; +use std::{cmp::Ordering, str::FromStr}; use thiserror::Error; const DAY_NUMBER: usize = 2; @@ -60,9 +58,7 @@ impl Rps { Err(RPSError::IllegalLine(line.to_owned()))? }; - let first = Rps::try_from(first)?; - let second = Rps::try_from(second)?; - Ok((first, second)) + Ok((first.parse()?, second.parse()?)) } pub fn value(&self) -> i64 { @@ -98,10 +94,10 @@ impl PartialOrd for Rps { } } -impl TryFrom<&str> for Rps { - type Error = RPSError; +impl FromStr for Rps { + type Err = RPSError; - fn try_from(value: &str) -> std::result::Result { + fn from_str(value: &str) -> Result { match value { "A" | "X" => Ok(Rps::Rock), "B" | "Y" => Ok(Rps::Paper), @@ -110,6 +106,7 @@ impl TryFrom<&str> for Rps { } } } + #[derive(Debug, Eq, PartialEq, Clone, Copy)] enum Strategy { Loose, @@ -124,9 +121,7 @@ impl Strategy { Err(RPSError::IllegalLine(line.to_owned()))? }; - let first = Rps::try_from(first)?; - let second = Strategy::try_from(second)?; - Ok((first, second)) + Ok((first.parse()?, second.parse()?)) } pub fn fullfill(&self, other: &Rps) -> Rps { @@ -139,10 +134,10 @@ impl Strategy { } } -impl TryFrom<&str> for Strategy { - type Error = RPSError; +impl FromStr for Strategy { + type Err = RPSError; - fn try_from(value: &str) -> std::result::Result { + fn from_str(value: &str) -> Result { match value { "X" => Ok(Strategy::Loose), "Y" => Ok(Strategy::Draw), diff --git a/src/days/day03/mod.rs b/src/days/day03/mod.rs index a86653c..7f09707 100644 --- a/src/days/day03/mod.rs +++ b/src/days/day03/mod.rs @@ -1,6 +1,5 @@ -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; use itertools::Itertools; use thiserror::Error; diff --git a/src/days/day04/mod.rs b/src/days/day04/mod.rs index 62a84a9..d639e66 100644 --- a/src/days/day04/mod.rs +++ b/src/days/day04/mod.rs @@ -1,6 +1,5 @@ -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; use itertools::Itertools; use std::num::ParseIntError; use thiserror::Error; diff --git a/src/days/day05/mod.rs b/src/days/day05/mod.rs index 57429eb..3295539 100644 --- a/src/days/day05/mod.rs +++ b/src/days/day05/mod.rs @@ -1,6 +1,5 @@ -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; use itertools::Itertools; use std::num::ParseIntError; use thiserror::Error; @@ -124,7 +123,7 @@ impl Move { if self.to_stack >= stacks.len() { return Err(CrateError::TooFewStacks(stacks.len(), self.to_stack)); } - let Some(from_stack) = stacks.get(self.from_stack ) else { + let Some(from_stack) = stacks.get(self.from_stack) else { return Err(CrateError::TooFewStacks(stacks.len(), self.from_stack)); }; if from_stack.len() < self.amount { diff --git a/src/days/day07/mod.rs b/src/days/day07/mod.rs index beb77c6..d8375fe 100644 --- a/src/days/day07/mod.rs +++ b/src/days/day07/mod.rs @@ -1,12 +1,10 @@ +use super::template::{DayTrait, ResultType}; +use crate::common::{file::split_lines, name::Name}; use std::{ cell::{Cell, RefCell}, num::ParseIntError, rc::{Rc, Weak}, }; - -use crate::common::file::split_lines; - -use super::template::{DayTrait, ResultType}; use thiserror::Error; const DAY_NUMBER: usize = 7; @@ -75,7 +73,7 @@ enum DirectoryError { #[derive(Debug)] struct Node { parent: Option>>, - name: String, + name: Name, sub_dirs: Vec>>, file_size: i64, size: Cell>, @@ -85,7 +83,7 @@ impl Node { fn root() -> Node { Node { parent: None, - name: "/".to_owned(), + name: "/".into(), sub_dirs: vec![], file_size: 0, size: Cell::new(None), @@ -96,7 +94,7 @@ impl Node { self.sub_dirs.push(subdir); } - fn add_file(&mut self, _name: &str, size: i64) { + fn add_file>(&mut self, _name: N, size: i64) { self.file_size += size; } @@ -141,10 +139,10 @@ impl Directory { self.node.borrow().file_size } - pub fn add_subdir(&mut self, name: &str) { + pub fn add_subdir>(&mut self, name: N) { let subdir = Rc::new(RefCell::new(Node { parent: Some(Rc::downgrade(&self.node)), - name: name.to_owned(), + name: name.into(), sub_dirs: vec![], file_size: 0, size: Cell::new(None), @@ -152,7 +150,7 @@ impl Directory { self.node.borrow_mut().add_subdir(subdir); } - pub fn add_file(&mut self, name: &str, size: i64) { + pub fn add_file>(&mut self, name: N, size: i64) { self.node.borrow_mut().add_file(name, size) } @@ -165,8 +163,9 @@ impl Directory { .map(|node| Directory { node }) } - pub fn get_subdir(&self, name: &str) -> Option { + pub fn get_subdir>(&self, name: N) -> Option { let node = self.node.borrow(); + let name = name.into(); let sub_node = node.sub_dirs.iter().find(|node| node.borrow().name == name); sub_node.map(|node| Directory::create(node.clone())) } @@ -181,14 +180,14 @@ impl Directory { "/" => root.clone(), ".." => { let Some(next) = current.parent() else { - return Err(DirectoryError::NoParentDirectory); - }; + return Err(DirectoryError::NoParentDirectory); + }; next } _ => { let Some(next) = current.get_subdir(dir) else { - return Err(DirectoryError::NoSuchDirectory(dir.to_owned())) - }; + return Err(DirectoryError::NoSuchDirectory(dir.to_owned())); + }; next } }; diff --git a/src/days/day08/mod.rs b/src/days/day08/mod.rs index c031b2a..50bb849 100644 --- a/src/days/day08/mod.rs +++ b/src/days/day08/mod.rs @@ -1,9 +1,7 @@ -use std::str::FromStr; - -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; use itertools::{iproduct, FoldWhile, Itertools}; +use std::str::FromStr; use thiserror::Error; const DAY_NUMBER: usize = 8; diff --git a/src/days/day10/mod.rs b/src/days/day10/mod.rs index 255231b..d726d37 100644 --- a/src/days/day10/mod.rs +++ b/src/days/day10/mod.rs @@ -1,7 +1,7 @@ -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; -use std::{num::ParseIntError, slice::Iter}; +use crate::common::file::split_lines; +use itertools::Itertools; +use std::{num::ParseIntError, slice::Iter, str::FromStr}; use thiserror::Error; const DAY_NUMBER: usize = 10; @@ -14,17 +14,13 @@ impl DayTrait for Day { } fn part1(&self, lines: &str) -> anyhow::Result { - let instructions = split_lines(lines) - .map(|line| Instruction::parse(line)) - .collect::, _>>()?; + let instructions: Vec<_> = split_lines(lines).map(|line| line.parse()).try_collect()?; let result = CpuCycles::signal_strength(&instructions, &[20, 60, 100, 140, 180, 220]); Ok(ResultType::Integer(result as i64)) } fn part2(&self, lines: &str) -> anyhow::Result { - let instructions = split_lines(lines) - .map(|line| Instruction::parse(line)) - .collect::, _>>()?; + let instructions: Vec<_> = split_lines(lines).map(|line| line.parse()).try_collect()?; let result = CpuCycles::draw(&instructions); Ok(ResultType::Lines(result)) } @@ -39,18 +35,18 @@ enum CpuError { InvalidInteger(#[from] ParseIntError), } -enum Instruction { - Add(i32), - Noop, -} +#[derive(Debug, PartialEq, Eq)] +struct Instruction(Option); -impl Instruction { - pub fn parse(line: &str) -> Result { +impl FromStr for Instruction { + type Err = CpuError; + + fn from_str(line: &str) -> Result { if line == "noop" { - Ok(Instruction::Noop) + Ok(Instruction(None)) } else if line.starts_with("addx") { let value = line[5..].parse()?; - Ok(Instruction::Add(value)) + Ok(Instruction(Some(value))) } else { Err(CpuError::UnknownInstruction(line.to_owned())) } @@ -114,10 +110,7 @@ impl<'a> Iterator for CpuCycles<'a> { self.current = None; Some(start_register) } else if let Some(instruction) = self.instructions.next() { - match instruction { - Instruction::Add(value) => self.current = Some(*value), - Instruction::Noop => {} - } + self.current = instruction.0; Some(self.register) } else { None @@ -134,7 +127,11 @@ mod test { #[test] fn test_simple() -> Result<()> { - let instructions = vec![Instruction::Noop, Instruction::Add(3), Instruction::Add(-5)]; + let instructions = vec![ + Instruction(None), + Instruction(Some(3)), + Instruction(Some(-5)), + ]; let expected = vec![1, 1, 1, 4, 4]; let result = CpuCycles::create(&instructions).collect::>(); assert_eq!(result, expected); diff --git a/src/days/day11/mod.rs b/src/days/day11/mod.rs index ddb6f62..65d210e 100644 --- a/src/days/day11/mod.rs +++ b/src/days/day11/mod.rs @@ -1,8 +1,7 @@ +use super::template::{DayTrait, ResultType}; use crate::common::parser::{ empty_lines, eol_terminated, extract_result, ignore, trim0, trim_left1, true_false, }; - -use super::template::{DayTrait, ResultType}; use nom::{ branch::alt, bytes::complete::tag, diff --git a/src/days/day12/mod.rs b/src/days/day12/mod.rs index 1c099d0..a861e81 100644 --- a/src/days/day12/mod.rs +++ b/src/days/day12/mod.rs @@ -1,8 +1,6 @@ -use std::collections::{BinaryHeap, HashSet}; - -use crate::common::{file::split_lines, pos::Pos}; - use super::template::{DayTrait, ResultType}; +use crate::common::{file::split_lines, pos::Pos}; +use std::collections::{BinaryHeap, HashSet}; use thiserror::Error; const DAY_NUMBER: usize = 12; diff --git a/src/days/day13/mod.rs b/src/days/day13/mod.rs index f6b146a..8173964 100644 --- a/src/days/day13/mod.rs +++ b/src/days/day13/mod.rs @@ -1,9 +1,7 @@ -use std::cmp::Ordering; - -use crate::common::file::split_lines; - use super::template::{DayTrait, ResultType}; +use crate::common::file::split_lines; use itertools::Itertools; +use std::cmp::Ordering; use thiserror::Error; const DAY_NUMBER: usize = 13; diff --git a/src/days/day14/mod.rs b/src/days/day14/mod.rs index 56a1e02..e2b8e56 100644 --- a/src/days/day14/mod.rs +++ b/src/days/day14/mod.rs @@ -1,11 +1,9 @@ +use super::template::{DayTrait, ResultType}; +use crate::common::{file::split_lines, pos::Pos}; use itertools::Itertools; use std::{collections::HashSet, num::ParseIntError}; use thiserror::Error; -use crate::common::{file::split_lines, pos::Pos}; - -use super::template::{DayTrait, ResultType}; - const DAY_NUMBER: usize = 14; pub struct Day; diff --git a/src/days/day16/mod.rs b/src/days/day16/mod.rs index e068986..4739cfc 100644 --- a/src/days/day16/mod.rs +++ b/src/days/day16/mod.rs @@ -1,5 +1,8 @@ use super::template::{DayTrait, ResultType}; -use crate::common::parser::{eol_terminated, extract_result, ignore, trim0, trim1, trim_left1}; +use crate::common::{ + name::Name, + parser::{eol_terminated, extract_result, ignore, trim0, trim1, trim_left1}, +}; use itertools::Itertools; use nom::{ branch::alt, @@ -95,6 +98,7 @@ impl Mul for Time { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] struct Flow(i64); + impl Deref for Flow { type Target = i64; @@ -208,7 +212,7 @@ impl<'a> TryFrom<&'a str> for RawValve<'a> { #[derive(Debug)] struct Valve { - id: String, + id: Name, idx: Index, flow: Flow, distances: Vec