minor improvements

This commit is contained in:
Rüdiger Ludwig 2023-08-05 20:38:05 +02:00
parent 4e64b9786d
commit bcefb1b68f
18 changed files with 111 additions and 124 deletions

View file

@ -3,6 +3,7 @@ pub mod direction;
pub mod file; pub mod file;
pub mod helper; pub mod helper;
pub mod math; pub mod math;
pub mod name;
pub mod parser; pub mod parser;
pub mod pos; pub mod pos;
pub mod turn; pub mod turn;

30
src/common/name.rs Normal file
View file

@ -0,0 +1,30 @@
use std::{fmt::Display, ops::Deref, rc::Rc};
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Name(Rc<str>);
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)
}
}

View file

@ -1,12 +1,9 @@
use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::Itertools; use itertools::Itertools;
use std::num::ParseIntError; use std::num::ParseIntError;
use thiserror::Error; use thiserror::Error;
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType};
pub struct Day; pub struct Day;
const DAY_NUMBER: usize = 1; const DAY_NUMBER: usize = 1;

View file

@ -1,8 +1,6 @@
use std::cmp::Ordering;
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use std::{cmp::Ordering, str::FromStr};
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 2; const DAY_NUMBER: usize = 2;
@ -60,9 +58,7 @@ impl Rps {
Err(RPSError::IllegalLine(line.to_owned()))? Err(RPSError::IllegalLine(line.to_owned()))?
}; };
let first = Rps::try_from(first)?; Ok((first.parse()?, second.parse()?))
let second = Rps::try_from(second)?;
Ok((first, second))
} }
pub fn value(&self) -> i64 { pub fn value(&self) -> i64 {
@ -98,10 +94,10 @@ impl PartialOrd for Rps {
} }
} }
impl TryFrom<&str> for Rps { impl FromStr for Rps {
type Error = RPSError; type Err = RPSError;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> { fn from_str(value: &str) -> Result<Self, Self::Err> {
match value { match value {
"A" | "X" => Ok(Rps::Rock), "A" | "X" => Ok(Rps::Rock),
"B" | "Y" => Ok(Rps::Paper), "B" | "Y" => Ok(Rps::Paper),
@ -110,6 +106,7 @@ impl TryFrom<&str> for Rps {
} }
} }
} }
#[derive(Debug, Eq, PartialEq, Clone, Copy)] #[derive(Debug, Eq, PartialEq, Clone, Copy)]
enum Strategy { enum Strategy {
Loose, Loose,
@ -124,9 +121,7 @@ impl Strategy {
Err(RPSError::IllegalLine(line.to_owned()))? Err(RPSError::IllegalLine(line.to_owned()))?
}; };
let first = Rps::try_from(first)?; Ok((first.parse()?, second.parse()?))
let second = Strategy::try_from(second)?;
Ok((first, second))
} }
pub fn fullfill(&self, other: &Rps) -> Rps { pub fn fullfill(&self, other: &Rps) -> Rps {
@ -139,10 +134,10 @@ impl Strategy {
} }
} }
impl TryFrom<&str> for Strategy { impl FromStr for Strategy {
type Error = RPSError; type Err = RPSError;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> { fn from_str(value: &str) -> Result<Self, Self::Err> {
match value { match value {
"X" => Ok(Strategy::Loose), "X" => Ok(Strategy::Loose),
"Y" => Ok(Strategy::Draw), "Y" => Ok(Strategy::Draw),

View file

@ -1,6 +1,5 @@
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::Itertools; use itertools::Itertools;
use thiserror::Error; use thiserror::Error;

View file

@ -1,6 +1,5 @@
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::Itertools; use itertools::Itertools;
use std::num::ParseIntError; use std::num::ParseIntError;
use thiserror::Error; use thiserror::Error;

View file

@ -1,6 +1,5 @@
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::Itertools; use itertools::Itertools;
use std::num::ParseIntError; use std::num::ParseIntError;
use thiserror::Error; use thiserror::Error;
@ -124,7 +123,7 @@ impl Move {
if self.to_stack >= stacks.len() { if self.to_stack >= stacks.len() {
return Err(CrateError::TooFewStacks(stacks.len(), self.to_stack)); 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)); return Err(CrateError::TooFewStacks(stacks.len(), self.from_stack));
}; };
if from_stack.len() < self.amount { if from_stack.len() < self.amount {

View file

@ -1,12 +1,10 @@
use super::template::{DayTrait, ResultType};
use crate::common::{file::split_lines, name::Name};
use std::{ use std::{
cell::{Cell, RefCell}, cell::{Cell, RefCell},
num::ParseIntError, num::ParseIntError,
rc::{Rc, Weak}, rc::{Rc, Weak},
}; };
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType};
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 7; const DAY_NUMBER: usize = 7;
@ -75,7 +73,7 @@ enum DirectoryError {
#[derive(Debug)] #[derive(Debug)]
struct Node { struct Node {
parent: Option<Weak<RefCell<Node>>>, parent: Option<Weak<RefCell<Node>>>,
name: String, name: Name,
sub_dirs: Vec<Rc<RefCell<Node>>>, sub_dirs: Vec<Rc<RefCell<Node>>>,
file_size: i64, file_size: i64,
size: Cell<Option<i64>>, size: Cell<Option<i64>>,
@ -85,7 +83,7 @@ impl Node {
fn root() -> Node { fn root() -> Node {
Node { Node {
parent: None, parent: None,
name: "/".to_owned(), name: "/".into(),
sub_dirs: vec![], sub_dirs: vec![],
file_size: 0, file_size: 0,
size: Cell::new(None), size: Cell::new(None),
@ -96,7 +94,7 @@ impl Node {
self.sub_dirs.push(subdir); self.sub_dirs.push(subdir);
} }
fn add_file(&mut self, _name: &str, size: i64) { fn add_file<N: Into<Name>>(&mut self, _name: N, size: i64) {
self.file_size += size; self.file_size += size;
} }
@ -141,10 +139,10 @@ impl Directory {
self.node.borrow().file_size self.node.borrow().file_size
} }
pub fn add_subdir(&mut self, name: &str) { pub fn add_subdir<N: Into<Name>>(&mut self, name: N) {
let subdir = Rc::new(RefCell::new(Node { let subdir = Rc::new(RefCell::new(Node {
parent: Some(Rc::downgrade(&self.node)), parent: Some(Rc::downgrade(&self.node)),
name: name.to_owned(), name: name.into(),
sub_dirs: vec![], sub_dirs: vec![],
file_size: 0, file_size: 0,
size: Cell::new(None), size: Cell::new(None),
@ -152,7 +150,7 @@ impl Directory {
self.node.borrow_mut().add_subdir(subdir); self.node.borrow_mut().add_subdir(subdir);
} }
pub fn add_file(&mut self, name: &str, size: i64) { pub fn add_file<N: Into<Name>>(&mut self, name: N, size: i64) {
self.node.borrow_mut().add_file(name, size) self.node.borrow_mut().add_file(name, size)
} }
@ -165,8 +163,9 @@ impl Directory {
.map(|node| Directory { node }) .map(|node| Directory { node })
} }
pub fn get_subdir(&self, name: &str) -> Option<Directory> { pub fn get_subdir<N: Into<Name>>(&self, name: N) -> Option<Directory> {
let node = self.node.borrow(); let node = self.node.borrow();
let name = name.into();
let sub_node = node.sub_dirs.iter().find(|node| node.borrow().name == name); let sub_node = node.sub_dirs.iter().find(|node| node.borrow().name == name);
sub_node.map(|node| Directory::create(node.clone())) sub_node.map(|node| Directory::create(node.clone()))
} }
@ -187,7 +186,7 @@ impl Directory {
} }
_ => { _ => {
let Some(next) = current.get_subdir(dir) else { let Some(next) = current.get_subdir(dir) else {
return Err(DirectoryError::NoSuchDirectory(dir.to_owned())) return Err(DirectoryError::NoSuchDirectory(dir.to_owned()));
}; };
next next
} }

View file

@ -1,9 +1,7 @@
use std::str::FromStr;
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::{iproduct, FoldWhile, Itertools}; use itertools::{iproduct, FoldWhile, Itertools};
use std::str::FromStr;
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 8; const DAY_NUMBER: usize = 8;

View file

@ -1,7 +1,7 @@
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; 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; use thiserror::Error;
const DAY_NUMBER: usize = 10; const DAY_NUMBER: usize = 10;
@ -14,17 +14,13 @@ impl DayTrait for Day {
} }
fn part1(&self, lines: &str) -> anyhow::Result<ResultType> { fn part1(&self, lines: &str) -> anyhow::Result<ResultType> {
let instructions = split_lines(lines) let instructions: Vec<_> = split_lines(lines).map(|line| line.parse()).try_collect()?;
.map(|line| Instruction::parse(line))
.collect::<Result<Vec<_>, _>>()?;
let result = CpuCycles::signal_strength(&instructions, &[20, 60, 100, 140, 180, 220]); let result = CpuCycles::signal_strength(&instructions, &[20, 60, 100, 140, 180, 220]);
Ok(ResultType::Integer(result as i64)) Ok(ResultType::Integer(result as i64))
} }
fn part2(&self, lines: &str) -> anyhow::Result<ResultType> { fn part2(&self, lines: &str) -> anyhow::Result<ResultType> {
let instructions = split_lines(lines) let instructions: Vec<_> = split_lines(lines).map(|line| line.parse()).try_collect()?;
.map(|line| Instruction::parse(line))
.collect::<Result<Vec<_>, _>>()?;
let result = CpuCycles::draw(&instructions); let result = CpuCycles::draw(&instructions);
Ok(ResultType::Lines(result)) Ok(ResultType::Lines(result))
} }
@ -39,18 +35,18 @@ enum CpuError {
InvalidInteger(#[from] ParseIntError), InvalidInteger(#[from] ParseIntError),
} }
enum Instruction { #[derive(Debug, PartialEq, Eq)]
Add(i32), struct Instruction(Option<i32>);
Noop,
}
impl Instruction { impl FromStr for Instruction {
pub fn parse(line: &str) -> Result<Self, CpuError> { type Err = CpuError;
fn from_str(line: &str) -> Result<Self, Self::Err> {
if line == "noop" { if line == "noop" {
Ok(Instruction::Noop) Ok(Instruction(None))
} else if line.starts_with("addx") { } else if line.starts_with("addx") {
let value = line[5..].parse()?; let value = line[5..].parse()?;
Ok(Instruction::Add(value)) Ok(Instruction(Some(value)))
} else { } else {
Err(CpuError::UnknownInstruction(line.to_owned())) Err(CpuError::UnknownInstruction(line.to_owned()))
} }
@ -114,10 +110,7 @@ impl<'a> Iterator for CpuCycles<'a> {
self.current = None; self.current = None;
Some(start_register) Some(start_register)
} else if let Some(instruction) = self.instructions.next() { } else if let Some(instruction) = self.instructions.next() {
match instruction { self.current = instruction.0;
Instruction::Add(value) => self.current = Some(*value),
Instruction::Noop => {}
}
Some(self.register) Some(self.register)
} else { } else {
None None
@ -134,7 +127,11 @@ mod test {
#[test] #[test]
fn test_simple() -> Result<()> { 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 expected = vec![1, 1, 1, 4, 4];
let result = CpuCycles::create(&instructions).collect::<Vec<_>>(); let result = CpuCycles::create(&instructions).collect::<Vec<_>>();
assert_eq!(result, expected); assert_eq!(result, expected);

View file

@ -1,8 +1,7 @@
use super::template::{DayTrait, ResultType};
use crate::common::parser::{ use crate::common::parser::{
empty_lines, eol_terminated, extract_result, ignore, trim0, trim_left1, true_false, empty_lines, eol_terminated, extract_result, ignore, trim0, trim_left1, true_false,
}; };
use super::template::{DayTrait, ResultType};
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::tag,

View file

@ -1,8 +1,6 @@
use std::collections::{BinaryHeap, HashSet};
use crate::common::{file::split_lines, pos::Pos};
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::{file::split_lines, pos::Pos};
use std::collections::{BinaryHeap, HashSet};
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 12; const DAY_NUMBER: usize = 12;

View file

@ -1,9 +1,7 @@
use std::cmp::Ordering;
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::Itertools; use itertools::Itertools;
use std::cmp::Ordering;
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 13; const DAY_NUMBER: usize = 13;

View file

@ -1,11 +1,9 @@
use super::template::{DayTrait, ResultType};
use crate::common::{file::split_lines, pos::Pos};
use itertools::Itertools; use itertools::Itertools;
use std::{collections::HashSet, num::ParseIntError}; use std::{collections::HashSet, num::ParseIntError};
use thiserror::Error; use thiserror::Error;
use crate::common::{file::split_lines, pos::Pos};
use super::template::{DayTrait, ResultType};
const DAY_NUMBER: usize = 14; const DAY_NUMBER: usize = 14;
pub struct Day; pub struct Day;

View file

@ -1,5 +1,8 @@
use super::template::{DayTrait, ResultType}; 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 itertools::Itertools;
use nom::{ use nom::{
branch::alt, branch::alt,
@ -95,6 +98,7 @@ impl Mul<Flow> for Time {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
struct Flow(i64); struct Flow(i64);
impl Deref for Flow { impl Deref for Flow {
type Target = i64; type Target = i64;
@ -208,7 +212,7 @@ impl<'a> TryFrom<&'a str> for RawValve<'a> {
#[derive(Debug)] #[derive(Debug)]
struct Valve { struct Valve {
id: String, id: Name,
idx: Index, idx: Index,
flow: Flow, flow: Flow,
distances: Vec<Time>, distances: Vec<Time>,
@ -245,7 +249,7 @@ impl Valve {
distances.sort_unstable_by_key(|(id, _)| *id); distances.sort_unstable_by_key(|(id, _)| *id);
Ok(Valve { Ok(Valve {
id: valve.id.to_owned(), id: valve.id.into(),
idx, idx,
flow: valve.flow, flow: valve.flow,
distances: distances distances: distances
@ -257,7 +261,7 @@ impl Valve {
fn zero_flow(valve: &RawValve, idx: Index) -> Valve { fn zero_flow(valve: &RawValve, idx: Index) -> Valve {
Valve { Valve {
id: valve.id.to_owned(), id: valve.id.into(),
idx, idx,
flow: valve.flow, flow: valve.flow,
distances: vec![], distances: vec![],
@ -309,11 +313,12 @@ impl ValveSystem {
} }
#[allow(dead_code)] #[allow(dead_code)]
fn get_valve_by_id(&self, id: &str) -> Result<&Valve, ValveError> { fn get_valve_by_id<N: Into<Name>>(&self, id: N) -> Result<&Valve, ValveError> {
let id = id.into();
self.valves self.valves
.iter() .iter()
.find(|valve| valve.id == id) .find(|valve| valve.id == id)
.ok_or(ValveError::ValveNotFound(id.to_owned())) .ok_or(ValveError::ValveNotFound(id.to_string()))
} }
fn get_valve(&self, idx: Index) -> &Valve { fn get_valve(&self, idx: Index) -> &Valve {

View file

@ -1,9 +1,7 @@
use std::{cell::Cell, marker::PhantomData, ops::Index};
use crate::common::file::{read_string, split_lines};
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::file::{read_string, split_lines};
use itertools::Itertools; use itertools::Itertools;
use std::{cell::Cell, marker::PhantomData, ops::Index};
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 17; const DAY_NUMBER: usize = 17;

View file

@ -1,11 +1,9 @@
use super::template::{DayTrait, ResultType};
use crate::common::file::split_lines;
use itertools::Itertools; use itertools::Itertools;
use std::{collections::HashSet, num::ParseIntError}; use std::{collections::HashSet, num::ParseIntError};
use thiserror::Error; use thiserror::Error;
use crate::common::file::split_lines;
use super::template::{DayTrait, ResultType};
const DAY_NUMBER: usize = 18; const DAY_NUMBER: usize = 18;
pub struct Day; pub struct Day;
@ -173,7 +171,7 @@ impl Blob {
} }
pub fn count_outside(&self) -> i64 { pub fn count_outside(&self) -> i64 {
let Some(mut extent)= self.extent() else { let Some(mut extent) = self.extent() else {
return 0; return 0;
}; };
let mut sides = 0; let mut sides = 0;

View file

@ -1,7 +1,8 @@
use std::{collections::HashMap, ops::Deref, rc::Rc, str::FromStr};
use super::template::{DayTrait, ResultType}; use super::template::{DayTrait, ResultType};
use crate::common::parser::{extract_result, ignore, trim0}; use crate::common::{
name::Name,
parser::{extract_result, ignore, trim0},
};
use nom::{ use nom::{
branch::alt, branch::alt,
character::complete::{alpha1, char, i64, multispace0, one_of}, character::complete::{alpha1, char, i64, multispace0, one_of},
@ -10,6 +11,7 @@ use nom::{
sequence::{terminated, tuple}, sequence::{terminated, tuple},
Err, IResult, Parser, Err, IResult, Parser,
}; };
use std::{collections::HashMap, str::FromStr};
use thiserror::Error; use thiserror::Error;
const DAY_NUMBER: usize = 21; const DAY_NUMBER: usize = 21;
@ -34,29 +36,6 @@ impl DayTrait for Day {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
struct Name(Rc<str>);
impl Name {
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))
}
}
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum MonkeyError { enum MonkeyError {
#[error("Not a valid description: {0}")] #[error("Not a valid description: {0}")]