From bb63ca7f747e327f9382eafa4f1cc7d9583df529 Mon Sep 17 00:00:00 2001 From: BoolPurist Date: Fri, 23 Aug 2024 06:45:11 +0200 Subject: [PATCH] Implemented line parsing for a dealt hand --- src/solutions.rs | 1 + src/solutions/day5/item_mapping.rs | 59 ++++++++++-------- src/solutions/day7.rs | 1 + src/solutions/day7/dealt_hand.rs | 99 ++++++++++++++++++++++++++++++ src/solutions/day7/parsing.rs | 0 5 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 src/solutions/day7.rs create mode 100644 src/solutions/day7/dealt_hand.rs create mode 100644 src/solutions/day7/parsing.rs diff --git a/src/solutions.rs b/src/solutions.rs index f76b91a..c4459d9 100644 --- a/src/solutions.rs +++ b/src/solutions.rs @@ -1,5 +1,6 @@ pub mod day5; pub mod day6; +pub mod day7; pub fn create_solutions() -> Vec String>> { vec![ diff --git a/src/solutions/day5/item_mapping.rs b/src/solutions/day5/item_mapping.rs index 20dcab9..3ba3ed5 100644 --- a/src/solutions/day5/item_mapping.rs +++ b/src/solutions/day5/item_mapping.rs @@ -1,4 +1,4 @@ -use std::{str::FromStr}; +use std::str::FromStr; use thiserror::Error; @@ -13,12 +13,6 @@ pub struct 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 { let start = self.source_range.start(); let end = self.source_range.end(); @@ -56,25 +50,9 @@ impl ItemMapping { MappedRange::PartiallyWithin { outside, mapped } } else if to_map.start() < start && to_map.end() > end { - // -----yyy---- - // ----xxxxxx - 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 } + // ----xxxxxx-- + self.map_from_left_and_right(to_map) } else { // ----yyyyyy---- // -----xxxx----- @@ -95,6 +73,37 @@ impl ItemMapping { 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)] diff --git a/src/solutions/day7.rs b/src/solutions/day7.rs new file mode 100644 index 0000000..3b082df --- /dev/null +++ b/src/solutions/day7.rs @@ -0,0 +1 @@ +mod dealt_hand; diff --git a/src/solutions/day7/dealt_hand.rs b/src/solutions/day7/dealt_hand.rs new file mode 100644 index 0000000..86b340c --- /dev/null +++ b/src/solutions/day7/dealt_hand.rs @@ -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 { + 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) { + 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(); + } +} diff --git a/src/solutions/day7/parsing.rs b/src/solutions/day7/parsing.rs new file mode 100644 index 0000000..e69de29