diff --git a/src/days/day7.rs b/src/days/day7.rs index 279dd9f..5fa1f10 100644 --- a/src/days/day7.rs +++ b/src/days/day7.rs @@ -2,24 +2,52 @@ use std::{path::Path, str::FromStr}; use itertools::Itertools; +use::std::hash::Hash; + use crate::{error::AdventError, input::read_into_vec}; #[derive(Debug, Eq, PartialEq, Hash)] -struct Card(char); +struct CardOne(char); -impl PartialOrd for Card { +#[derive(Debug, Eq, PartialEq, Hash)] +enum CardTwo { + Card(char), + Joker, +} + +trait Card { + fn strength(self: &Self) -> u32; +} + +impl Hash for dyn Card { + fn hash(&self, state: &mut H) { + self.strength().hash(state) + } +} + +impl Eq for dyn Card { + +} + +impl PartialEq for dyn Card { + fn eq(&self, other: &Self) -> bool { + self.strength().eq(&other.strength()) + } +} + +impl PartialOrd for dyn Card { fn partial_cmp(&self, other: &Self) -> Option { self.strength().partial_cmp(&other.strength()) } } -impl Ord for Card { +impl Ord for dyn Card { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.strength().cmp(&other.strength()) } } -impl Card { +impl Card for CardOne { fn strength(self: &Self) -> u32 { match self.0 { '2' => 2, @@ -40,6 +68,29 @@ impl Card { } } +impl Card for CardTwo { + fn strength(self: &Self) -> u32 { + match self { + Self::Card(c) => match c { + '2' => 2, + '3' => 3, + '4' => 4, + '5' => 5, + '6' => 6, + '7' => 7, + '8' => 8, + '9' => 9, + 'T' => 10, + 'Q' => 12, + 'K' => 13, + 'A' => 14, + _ => panic!("Invalid card found") + }, + Self::Joker => 1 + } + } +} + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] enum HandType { None, @@ -52,43 +103,127 @@ enum HandType { FiveOfAKind, } -#[derive(Debug, Eq)] -struct Hand { - cards: [Card;5], +#[derive(PartialEq, Eq)] +struct HandOne { hand_type: HandType, + cards: [Box;5], + } -impl PartialOrd for Hand { +#[derive(PartialEq, Eq)] +struct HandTwo { + hand_type: HandType, + cards: [Box;5] +} + +impl HandTwo { + fn new() -> Self { + Self { + cards: [ + Box::new(CardTwo::Card(' ')), + Box::new(CardTwo::Card(' ')), + Box::new(CardTwo::Card(' ')), + Box::new(CardTwo::Card(' ')), + Box::new(CardTwo::Card(' ')) + ], + hand_type: HandType::None + } + } +} + +impl Hand for HandTwo { + fn determine_type(&mut self) -> () { + todo!() + } + + fn get_hand_type(&self) -> &HandType { + todo!() + } + + fn get_cards(&self) -> &[Box;5] { + todo!() + } +} + +trait Hand { + fn determine_type(&mut self) -> (); + + fn get_hand_type(&self) -> &HandType; + fn get_cards(&self) -> &[Box;5]; +} + +impl PartialOrd for dyn Hand { fn partial_cmp(&self, other: &Self) -> Option { - match self.hand_type.partial_cmp(&other.hand_type) { + match self.get_hand_type().partial_cmp(&other.get_hand_type()) { Some(core::cmp::Ordering::Equal) => {} ord => return ord, } - self.cards.partial_cmp(&other.cards) + self.get_cards().partial_cmp(&other.get_cards()) } } -impl Ord for Hand { +impl Eq for dyn Hand { + +} + +impl Ord for dyn Hand { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.hand_type.cmp(&other.hand_type) + self.get_hand_type().cmp(&other.get_hand_type()) } } -impl PartialEq for Hand { +impl PartialEq for dyn Hand { fn eq(&self, other: &Self) -> bool { - self.hand_type == other.hand_type + self.get_hand_type() == other.get_hand_type() } } -impl Hand { +impl HandOne { fn new() -> Self { - Hand { - cards: [Card(' '), Card(' '), Card(' '), Card(' '), Card(' ')], + Self { + cards: [ + Box::new(CardOne(' ')), + Box::new(CardOne(' ')), + Box::new(CardOne(' ')), + Box::new(CardOne(' ')), + Box::new(CardOne(' ')) + ], hand_type: HandType::None } } +} +impl FromStr for HandOne { + type Err = AdventError; + + fn from_str(s: &str) -> Result { + let mut hand = HandOne::new(); + for i in 0..s.len() { + hand.cards[i] = Box::new(CardOne(s.chars().nth(i).ok_or(AdventError("Couldn't convert into Card".into()))?)); + } + hand.determine_type(); + Ok(hand) + } +} + +impl FromStr for HandTwo { + type Err = AdventError; + + fn from_str(s: &str) -> Result { + let mut hand = HandTwo::new(); + for i in 0..s.len() { + hand.cards[i] = Box::new(match s.chars().nth(i).ok_or(AdventError("Couldn't convert into Card".into()))? { + 'J' => CardTwo::Joker, + c => CardTwo::Card(c), + }); + }; + hand.determine_type(); + Ok(hand) + } +} + +impl Hand for HandOne { fn determine_type(&mut self) -> () { let counts = self.cards.iter().counts(); let value_counts = counts.iter().map(|c| { c.1 }).collect_vec(); @@ -113,36 +248,41 @@ impl Hand { (_, _) => panic!("Hand type match should never fail") }; } -} + fn get_hand_type(&self) -> &HandType { + &self.hand_type + } - -impl FromStr for Hand { - type Err = AdventError; - - fn from_str(s: &str) -> Result { - let mut hand: Hand = Hand::new(); - for i in 0..s.len() { - hand.cards[i] = Card(s.chars().nth(i).ok_or(AdventError("Couldn't convert into Card".into()))?); - hand.determine_type(); - } - Ok(hand) + fn get_cards(&self) -> &[Box;5] { + &self.cards } } -#[derive(Debug, Eq)] -struct Line { - hand: Hand, +#[derive(Eq)] +struct LineOne { + hand: Box, bid: u32, } -impl PartialEq for Line { +#[derive(Eq)] +struct LineTwo { + hand: Box, + bid: u32, +} + +impl PartialEq for LineOne { fn eq(&self, other: &Self) -> bool { - self.hand == other.hand + self.hand.as_ref() == other.hand.as_ref() } } -impl PartialOrd for Line { +impl PartialEq for LineTwo { + fn eq(&self, other: &Self) -> bool { + self.hand.as_ref() == other.hand.as_ref() + } +} + +impl PartialOrd for LineOne { fn partial_cmp(&self, other: &Self) -> Option { match self.hand.partial_cmp(&other.hand) { Some(core::cmp::Ordering::Equal) => {} @@ -152,25 +292,52 @@ impl PartialOrd for Line { } } -impl Ord for Line { +impl PartialOrd for LineTwo { + fn partial_cmp(&self, other: &Self) -> Option { + match self.hand.partial_cmp(&other.hand) { + Some(core::cmp::Ordering::Equal) => {} + ord => return ord, + } + self.bid.partial_cmp(&other.bid) + } +} + +impl Ord for LineOne { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.hand.cmp(&other.hand) } } -impl FromStr for Line { +impl Ord for LineTwo { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.hand.cmp(&other.hand) + } +} + +impl FromStr for LineOne { type Err = AdventError; fn from_str(s: &str) -> Result { let mut split = s.trim().split_ascii_whitespace(); - let hand = Hand::from_str(split.nth(0).ok_or(AdventError("no hand found".into()))?)?; + let hand = Box::new(HandOne::from_str(split.nth(0).ok_or(AdventError("no hand found".into()))?)?); let bid = split.nth(0).ok_or(AdventError("no score found".into()))?.parse::()?; - Ok(Line { hand, bid }) + Ok(Self { hand, bid }) + } +} + +impl FromStr for LineTwo { + type Err = AdventError; + + fn from_str(s: &str) -> Result { + let mut split = s.trim().split_ascii_whitespace(); + let hand = Box::new(HandTwo::from_str(split.nth(0).ok_or(AdventError("no hand found".into()))?)?); + let bid = split.nth(0).ok_or(AdventError("no score found".into()))?.parse::()?; + Ok(Self { hand, bid }) } } pub fn one() -> Result { - let mut lines = read_into_vec::(Path::new("resources/input7.txt".into()))?; + let mut lines = read_into_vec::(Path::new("resources/input7.txt".into()))?; lines.sort(); Ok(lines.iter().enumerate().fold(0, |acc, (rank, hand)| { acc + (rank as u32 + 1) * hand.bid @@ -178,7 +345,7 @@ pub fn one() -> Result { } pub fn two() -> Result { - let mut lines = read_into_vec::(Path::new("resources/input7.txt".into()))?; + let mut lines = read_into_vec::(Path::new("resources/input7.txt".into()))?; lines.sort(); Ok(0) } \ No newline at end of file