Implemented line parsing for a dealt hand
This commit is contained in:
parent
98633ea9df
commit
bb63ca7f74
5 changed files with 135 additions and 25 deletions
|
@ -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![
|
||||||
|
|
|
@ -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
1
src/solutions/day7.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
mod dealt_hand;
|
99
src/solutions/day7/dealt_hand.rs
Normal file
99
src/solutions/day7/dealt_hand.rs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
0
src/solutions/day7/parsing.rs
Normal file
0
src/solutions/day7/parsing.rs
Normal file
Loading…
Add table
Reference in a new issue