diff --git a/2023/src/day7.rs b/2023/src/day7.rs index 74cdddc..25656b4 100644 --- a/2023/src/day7.rs +++ b/2023/src/day7.rs @@ -6,11 +6,12 @@ use std::{ const INPUT: &str = include_str!("../data/day7.txt"); pub fn day7a() -> String { - format!("{}", calculate_game(INPUT)) + // format!("{}", calculate_game(INPUT)) + format!("card values changed in part 2") } pub fn day7b() -> String { - unimplemented!() + format!("{}", calculate_game(INPUT)) } fn calculate_game(game: &str) -> u64 { @@ -52,24 +53,27 @@ fn parse_line(s: &str) -> (Hand, u64) { } #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Hash, Eq, Ord)] -struct Card(u32); +enum Card { + Joker, + Card(u32), +} impl From for Card { fn from(s: char) -> Card { match s { - '2' => Card(2), - '3' => Card(3), - '4' => Card(4), - '5' => Card(5), - '6' => Card(6), - '7' => Card(7), - '8' => Card(8), - '9' => Card(9), - 'T' => Card(10), - 'J' => Card(11), - 'Q' => Card(12), - 'K' => Card(13), - 'A' => Card(14), + 'J' => Card::Joker, + '2' => Card::Card(2), + '3' => Card::Card(3), + '4' => Card::Card(4), + '5' => Card::Card(5), + '6' => Card::Card(6), + '7' => Card::Card(7), + '8' => Card::Card(8), + '9' => Card::Card(9), + 'T' => Card::Card(10), + 'Q' => Card::Card(11), + 'K' => Card::Card(12), + 'A' => Card::Card(13), _ => unreachable!(), } } @@ -89,16 +93,28 @@ enum HandType { #[derive(Clone, Debug, PartialEq, Eq)] struct Hand(Vec); +fn remove_highest(set: &mut HashSet) -> Card { + let mut lst = set.iter().cloned().collect::>(); + lst.sort(); + lst.reverse(); + let highest = lst.first().unwrap().clone(); + set.remove(&highest); + highest +} + impl Hand { fn classify(&self) -> HandType { let mut cards: HashSet = HashSet::new(); + let mut jokers: u32 = 0; let mut pairs: HashSet = HashSet::new(); let mut triples: HashSet = HashSet::new(); let mut quads: HashSet = HashSet::new(); let mut quints: HashSet = HashSet::new(); for card in self.0.iter() { - if quads.contains(card) { + if *card == Card::Joker { + jokers += 1; + } else if quads.contains(card) { quads.remove(card); quints.insert(*card); } else if triples.contains(card) { @@ -115,6 +131,26 @@ impl Hand { } } + if jokers == 5 { + return HandType::FiveOfAKind; + } + + for _ in 0..jokers { + if quads.len() > 0 { + let highest = remove_highest(&mut quads); + quints.insert(highest); + } else if triples.len() > 0 { + let highest = remove_highest(&mut triples); + quads.insert(highest); + } else if pairs.len() > 0 { + let highest = remove_highest(&mut pairs); + triples.insert(highest); + } else if cards.len() > 0 { + let highest = remove_highest(&mut cards); + pairs.insert(highest); + } + } + if quints.len() > 0 { HandType::FiveOfAKind } else if quads.len() > 0 { @@ -172,11 +208,12 @@ mod test { T55J5 684 KK677 28 KTJJT 220 -QQQJA 483"; +QQQJA 483 +JJJJJ 1"; #[test] fn it_calculates_test_data() { - assert_eq!(calculate_game(INPUT), 6440); + assert_eq!(calculate_game(INPUT), 5906); } #[test] @@ -184,23 +221,53 @@ QQQJA 483"; let test_cases = [ ( "32T3K", - Hand(vec![Card(3), Card(2), Card(10), Card(3), Card(13)]), + Hand(vec![ + Card::Card(3), + Card::Card(2), + Card::Card(10), + Card::Card(3), + Card::Card(12), + ]), ), ( "T55J5", - Hand(vec![Card(10), Card(5), Card(5), Card(11), Card(5)]), + Hand(vec![ + Card::Card(10), + Card::Card(5), + Card::Card(5), + Card::Joker, + Card::Card(5), + ]), ), ( "KK677", - Hand(vec![Card(13), Card(13), Card(6), Card(7), Card(7)]), + Hand(vec![ + Card::Card(12), + Card::Card(12), + Card::Card(6), + Card::Card(7), + Card::Card(7), + ]), ), ( "KTJJT", - Hand(vec![Card(13), Card(10), Card(11), Card(11), Card(10)]), + Hand(vec![ + Card::Card(12), + Card::Card(10), + Card::Joker, + Card::Joker, + Card::Card(10), + ]), ), ( "QQQJA", - Hand(vec![Card(12), Card(12), Card(12), Card(11), Card(14)]), + Hand(vec![ + Card::Card(11), + Card::Card(11), + Card::Card(11), + Card::Joker, + Card::Card(13), + ]), ), ]; @@ -213,33 +280,85 @@ QQQJA 483"; fn classifies_a_hand() { let test_cases = [ ( - Hand(vec![Card(12), Card(11), Card(10), Card(9), Card(8)]), - HandType::HighCard, - ), - ( - Hand(vec![Card(3), Card(2), Card(10), Card(3), Card(13)]), + Hand(vec![ + Card::Card(11), + Card::Joker, + Card::Card(10), + Card::Card(9), + Card::Card(8), + ]), HandType::OnePair, ), ( - Hand(vec![Card(10), Card(5), Card(5), Card(11), Card(5)]), - HandType::ThreeOfAKind, + Hand(vec![ + Card::Card(3), + Card::Card(2), + Card::Card(10), + Card::Card(3), + Card::Card(12), + ]), + HandType::OnePair, ), ( - Hand(vec![Card(13), Card(13), Card(6), Card(7), Card(7)]), + Hand(vec![ + Card::Card(10), + Card::Card(5), + Card::Card(5), + Card::Joker, + Card::Card(5), + ]), + HandType::FourOfAKind, + ), + ( + Hand(vec![ + Card::Card(12), + Card::Card(12), + Card::Card(6), + Card::Card(7), + Card::Card(7), + ]), HandType::TwoPair, ), ( - Hand(vec![Card(13), Card(10), Card(11), Card(11), Card(10)]), - HandType::TwoPair, + Hand(vec![ + Card::Card(12), + Card::Joker, + Card::Card(10), + Card::Card(10), + Card::Joker, + ]), + HandType::FourOfAKind, ), ( - Hand(vec![Card(12), Card(12), Card(12), Card(11), Card(14)]), - HandType::ThreeOfAKind, + Hand(vec![ + Card::Card(11), + Card::Card(11), + Card::Card(11), + Card::Joker, + Card::Card(13), + ]), + HandType::FourOfAKind, ), ( - Hand(vec![Card(12), Card(12), Card(12), Card(11), Card(11)]), + Hand(vec![ + Card::Card(11), + Card::Card(11), + Card::Card(11), + Card::Card(10), + Card::Card(10), + ]), HandType::FullHouse, ), + ( + Hand(vec![ + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + Card::Joker, + ]), + HandType::HighCard, + ), ]; for (hand, classification) in test_cases {