Implemented line parsing for a dealt hand

This commit is contained in:
BoolPurist 2024-08-23 06:45:11 +02:00
parent 98633ea9df
commit bb63ca7f74
5 changed files with 135 additions and 25 deletions

View file

@ -1,5 +1,6 @@
pub mod day5; pub mod day5;
pub mod day6; pub mod day6;
pub mod day7;
pub fn create_solutions() -> Vec<Vec<fn(&str) -> String>> { pub fn create_solutions() -> Vec<Vec<fn(&str) -> String>> {
vec![ vec![

View file

@ -1,4 +1,4 @@
use std::{str::FromStr}; use std::str::FromStr;
use thiserror::Error; use thiserror::Error;
@ -13,12 +13,6 @@ pub struct ItemMapping {
impl ItemMapping { impl ItemMapping {
fn offset_mapping(&self, to_map: UnsignedNumber) -> UnsignedNumber {
assert!(to_map >= self.source_range.start());
let difference = to_map - self.source_range.start();
self.target + difference
}
pub fn map_range(&self, to_map: SeedRange) -> MappedRange { pub fn map_range(&self, to_map: SeedRange) -> MappedRange {
let start = self.source_range.start(); let start = self.source_range.start();
let end = self.source_range.end(); let end = self.source_range.end();
@ -56,25 +50,9 @@ impl ItemMapping {
MappedRange::PartiallyWithin { outside, mapped } MappedRange::PartiallyWithin { outside, mapped }
} else if to_map.start() < start && to_map.end() > end { } else if to_map.start() < start && to_map.end() > end {
// -----yyy---- // -----yyy----
// ----xxxxxx // ----xxxxxx--
let left = { self.map_from_left_and_right(to_map)
let left_start = to_map.start();
let left_end = start - 1;
SeedRange::new(left_start, left_end)
};
let right = {
let right_start = end + 1;
let right_end = to_map.end();
SeedRange::new(right_start, right_end)
};
let mapped = {
let mapped_start = self.target;
let mapped_end = self.offset_mapping(end);
SeedRange::new(mapped_start, mapped_end)
};
MappedRange::FromBothSidePartiallyWithin { outside: (left, right), mapped }
} else { } else {
// ----yyyyyy---- // ----yyyyyy----
// -----xxxx----- // -----xxxx-----
@ -95,6 +73,37 @@ impl ItemMapping {
None None
} }
} }
fn map_from_left_and_right(&self, to_map: SeedRange) -> MappedRange {
let (start, end) = self.source_start_end();
let left = {
let left_start = to_map.start();
let left_end = start - 1;
SeedRange::new(left_start, left_end)
};
let right = {
let right_start = end + 1;
let right_end = to_map.end();
SeedRange::new(right_start, right_end)
};
let mapped = {
let mapped_start = self.target;
let mapped_end = self.offset_mapping(end);
SeedRange::new(mapped_start, mapped_end)
};
MappedRange::FromBothSidePartiallyWithin { outside: (left, right), mapped }
}
fn source_start_end(&self) -> (UnsignedNumber, UnsignedNumber) {
let range = self.source_range;
(range.start(), range.end())
}
fn offset_mapping(&self, to_map: UnsignedNumber) -> UnsignedNumber {
assert!(to_map >= self.source_range.start());
let difference = to_map - self.source_range.start();
self.target + difference
}
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]

1
src/solutions/day7.rs Normal file
View file

@ -0,0 +1 @@
mod dealt_hand;

View file

@ -0,0 +1,99 @@
use std::{str::FromStr, usize};
use derive_more::derive::Debug;
use thiserror::Error;
#[derive(Debug, PartialEq, Eq)]
pub struct DealtHand {
hand: String,
score: usize,
}
#[derive(Debug, Error, PartialEq, Eq)]
pub enum InvalidStrDealtHand {
#[error("Dealt hand must consist of 2 elements")]
Not2Elements,
#[error("Score must be an unsigned number")]
InvalidUnsignedNumberScore,
}
impl FromStr for DealtHand {
type Err = InvalidStrDealtHand;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut in_two = s.split_whitespace();
match (in_two.next(), in_two.next()) {
(Some(hand), Some(score)) => {
let score: usize = score
.parse()
.map_err(|_| InvalidStrDealtHand::InvalidUnsignedNumberScore)?;
let hand = hand.to_string();
let done = DealtHand { hand, score };
Ok(done)
}
_ => Err(InvalidStrDealtHand::Not2Elements),
}
}
}
#[cfg(test)]
mod testing {
use crate::solutions::day7::dealt_hand::{DealtHand, InvalidStrDealtHand};
#[test]
fn parse_str() {
fn assert_case(given: &str, expected: Result<DealtHand, InvalidStrDealtHand>) {
let actual = given.parse();
assert_eq!(expected, actual, "Input: {}", given);
}
fn happy_paths() {
assert_case(
"32T3K 765",
Ok(DealtHand {
hand: "32T3K".to_string(),
score: 765,
}),
);
assert_case(
"T55J5 684",
Ok(DealtHand {
hand: "T55J5".to_string(),
score: 684,
}),
);
assert_case(
"KK677 28",
Ok(DealtHand {
hand: "KK677".to_string(),
score: 28,
}),
);
assert_case(
"KTJJT 220",
Ok(DealtHand {
hand: "KTJJT".to_string(),
score: 220,
}),
);
assert_case(
"QQQJA 483",
Ok(DealtHand {
hand: "QQQJA".to_string(),
score: 483,
}),
);
}
fn error_paths() {
assert_case(
"xxxxx aaa",
Err(InvalidStrDealtHand::InvalidUnsignedNumberScore),
);
assert_case("xxxxx", Err(InvalidStrDealtHand::Not2Elements));
}
happy_paths();
error_paths();
}
}

View file