From 8c7567b21bcbfa41125290ddd071f836b119f6d4 Mon Sep 17 00:00:00 2001 From: Cassandra de la Cruz-Munoz Date: Thu, 7 Dec 2023 21:42:34 +0100 Subject: [PATCH] Do day 7 challenge --- src/07part1.rs | 196 +++++++++++++++++++++++++++++++++++++++++++++++ src/07part2.rs | 203 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 399 insertions(+) create mode 100644 src/07part1.rs create mode 100644 src/07part2.rs diff --git a/src/07part1.rs b/src/07part1.rs new file mode 100644 index 0000000..1401a13 --- /dev/null +++ b/src/07part1.rs @@ -0,0 +1,196 @@ +use std::{fs, cmp::Ordering}; + +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] +enum Card { + None = 0, + Two = 2, + Three = 3, + Four = 4, + Five = 5, + Six = 6, + Seven = 7, + Eight = 8, + Nine = 9, + Ten = 10, + Jack = 11, + Queen = 12, + King = 13, + Ace = 14 +} + +impl Copy for Card {} + +impl Clone for Card { + fn clone(&self) -> Self { + *self + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] +enum HandType { + FiveOfAKind = 6, + FourOfAKind = 5, + FullHouse = 4, + ThreeOfAKind = 3, + TwoPair = 2, + OnePair = 1, + HighCard = 0, +} + +#[derive(Eq, Debug)] +struct Hand { + bet: u128, + hand_type: HandType, + cards: Vec, +} + +impl Ord for Hand { + fn cmp(&self, other: &Self) -> Ordering { + if self.hand_type.ne(&other.hand_type) { + return self.hand_type.cmp(&other.hand_type); + } + if self.cards[0].ne(&other.cards[0]) { + return self.cards[0].cmp(&other.cards[0]); + } + if self.cards[1].ne(&other.cards[1]) { + return self.cards[1].cmp(&other.cards[1]); + } + if self.cards[2].ne(&other.cards[2]) { + return self.cards[2].cmp(&other.cards[2]); + } + if self.cards[3].ne(&other.cards[3]) { + return self.cards[3].cmp(&other.cards[3]); + } + return self.cards[4].cmp(&other.cards[4]); + } +} + +impl PartialOrd for Hand { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for Hand { + fn eq(&self, other: &Self) -> bool { + self.cards == other.cards + } +} + +fn main() { + let file_path = "input/07input.txt"; + let contents = fs::read_to_string(file_path).expect("should read file"); + let mut lines = contents.lines(); + let mut hands: Vec = Vec::new(); + loop { + let line = lines.next(); + if line.is_none() { + break; + } + let mut line_parts = line.unwrap().split_whitespace(); + let hand_cards: Vec = line_parts.next().unwrap().chars().map(|x| match x{ + '2' => Card::Two, + '3' => Card::Three, + '4' => Card::Four, + '5' => Card::Five, + '6' => Card::Six, + '7' => Card::Seven, + '8' => Card::Eight, + '9' => Card::Nine, + 'T' => Card::Ten, + 'J' => Card::Jack, + 'Q' => Card::Queen, + 'K' => Card::King, + 'A' => Card::Ace, + _ => Card::None, + }).collect(); + let bet = line_parts.next().unwrap().parse::().ok().unwrap(); + let hand = hand_from_cards(bet, hand_cards); + let loc_val: usize; + match hands.binary_search_by(|probe| probe.cmp(&hand)) { + Ok(v) => loc_val = v, + Err(v) => loc_val = v, + } + hands.insert(loc_val, hand); + } + let mut total_winnings: u128 = 0; + for i in 0..hands.len() { + total_winnings += hands[i].bet * (i + 1).to_string().parse::().ok().unwrap(); + } + println!("{}", total_winnings); +} + +fn hand_from_cards(bet: u128, cards: Vec) -> Hand { + let hand_type: HandType; + if cards[0] == cards[1] && cards[1] == cards[2] && cards[2] == cards[3] && cards[3] == cards[4] { // AAAAA + hand_type = HandType::FiveOfAKind; + } else if + (cards[0] == cards[1] && cards[1] == cards[2] && cards[2] == cards[3]) || // AAAAB + (cards[0] == cards[2] && cards[2] == cards[3] && cards[3] == cards[4]) || // ABAAA + (cards[0] == cards[1] && cards[1] == cards[3] && cards[3] == cards[4]) || // AABAA + (cards[0] == cards[1] && cards[1] == cards[2] && cards[2] == cards[4]) || // AAABA + (cards[1] == cards[2] && cards[2] == cards[3] && cards[3] == cards[4]) // BAAAA + { + hand_type = HandType::FourOfAKind; + } else if + (cards[0] == cards[1] && cards[1] == cards[2] && cards[3] == cards[4]) || // AAABB + (cards[0] == cards[1] && cards[1] == cards[3] && cards[2] == cards[4]) || // AABAB + (cards[0] == cards[1] && cards[1] == cards[4] && cards[2] == cards[3]) || // AABBA + (cards[0] == cards[2] && cards[2] == cards[3] && cards[1] == cards[4]) || // ABAAB + (cards[0] == cards[2] && cards[2] == cards[4] && cards[1] == cards[3]) || // ABABA + (cards[0] == cards[3] && cards[3] == cards[4] && cards[1] == cards[2]) || // ABBAA + (cards[1] == cards[2] && cards[2] == cards[3] && cards[0] == cards[4]) || // BAAAB + (cards[1] == cards[2] && cards[2] == cards[4] && cards[0] == cards[3]) || // BAABA + (cards[1] == cards[3] && cards[3] == cards[4] && cards[0] == cards[2]) || // BABAA + (cards[2] == cards[3] && cards[3] == cards[4] && cards[0] == cards[1]) // BBAAA + { + hand_type = HandType::FullHouse; + } else if + (cards[0] == cards[1] && cards[1] == cards[2]) || // AAABC + (cards[0] == cards[1] && cards[1] == cards[3]) || // AABAC + (cards[0] == cards[1] && cards[1] == cards[4]) || // AABCA + (cards[0] == cards[2] && cards[2] == cards[3]) || // ABAAC + (cards[0] == cards[2] && cards[2] == cards[4]) || // ABACA + (cards[0] == cards[3] && cards[3] == cards[4]) || // ABCAA + (cards[1] == cards[2] && cards[2] == cards[3]) || // BAAAC + (cards[1] == cards[2] && cards[2] == cards[4]) || // BAACA + (cards[1] == cards[3] && cards[3] == cards[4]) || // BACAA + (cards[2] == cards[3] && cards[3] == cards[4]) // BCAAA + { + hand_type = HandType::ThreeOfAKind; + } else if + (cards[0] == cards[1] && cards[2] == cards[3]) || // AABBC + (cards[0] == cards[1] && cards[2] == cards[4]) || // AABCB + (cards[0] == cards[1] && cards[3] == cards[4]) || // AACBB + (cards[0] == cards[2] && cards[1] == cards[3]) || // ABABC + (cards[0] == cards[2] && cards[1] == cards[4]) || // ABACB + (cards[0] == cards[2] && cards[3] == cards[4]) || // ACABB + (cards[0] == cards[3] && cards[1] == cards[2]) || // ABBAC + (cards[0] == cards[3] && cards[1] == cards[4]) || // ABCAB + (cards[0] == cards[3] && cards[2] == cards[4]) || // ACBAB + (cards[0] == cards[4] && cards[1] == cards[2]) || // ABBCA + (cards[0] == cards[4] && cards[1] == cards[3]) || // ABCBA + (cards[0] == cards[4] && cards[2] == cards[3]) || // ACBBA + (cards[1] == cards[2] && cards[3] == cards[4]) || // CAABB + (cards[1] == cards[3] && cards[2] == cards[4]) || // CABAB + (cards[1] == cards[4] && cards[2] == cards[3]) // CABBA + { + hand_type = HandType::TwoPair; + } else if + cards[0] == cards[1] || // AABCD + cards[0] == cards[2] || // ABACD + cards[0] == cards[3] || // ABCAD + cards[0] == cards[4] || // ABCDA + cards[1] == cards[2] || // BAACD + cards[1] == cards[3] || // BACAD + cards[1] == cards[4] || // BACDA + cards[2] == cards[3] || // BCAAD + cards[2] == cards[4] || // BCADA + cards[3] == cards[4] // BCDAA + { + hand_type = HandType::OnePair; + } else { // ABCDE + hand_type = HandType::HighCard; + } + return Hand {bet, hand_type, cards}; +} diff --git a/src/07part2.rs b/src/07part2.rs new file mode 100644 index 0000000..c43aca1 --- /dev/null +++ b/src/07part2.rs @@ -0,0 +1,203 @@ +use std::{fs, cmp::Ordering, collections::HashMap}; + +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum Card { + None = 0, + Joker = 1, + Two = 2, + Three = 3, + Four = 4, + Five = 5, + Six = 6, + Seven = 7, + Eight = 8, + Nine = 9, + Ten = 10, + Queen = 12, + King = 13, + Ace = 14 +} + +impl Copy for Card {} + +impl Clone for Card { + fn clone(&self) -> Self { + *self + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] +enum HandType { + FiveOfAKind = 6, + FourOfAKind = 5, + FullHouse = 4, + ThreeOfAKind = 3, + TwoPair = 2, + OnePair = 1, + HighCard = 0, +} + +#[derive(Eq, Debug)] +struct Hand { + bet: u128, + hand_type: HandType, + cards: Vec, +} + +impl Ord for Hand { + fn cmp(&self, other: &Self) -> Ordering { + if self.hand_type.ne(&other.hand_type) { + return self.hand_type.cmp(&other.hand_type); + } + if self.cards[0].ne(&other.cards[0]) { + return self.cards[0].cmp(&other.cards[0]); + } + if self.cards[1].ne(&other.cards[1]) { + return self.cards[1].cmp(&other.cards[1]); + } + if self.cards[2].ne(&other.cards[2]) { + return self.cards[2].cmp(&other.cards[2]); + } + if self.cards[3].ne(&other.cards[3]) { + return self.cards[3].cmp(&other.cards[3]); + } + return self.cards[4].cmp(&other.cards[4]); + } +} + +impl PartialOrd for Hand { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for Hand { + fn eq(&self, other: &Self) -> bool { + self.cards == other.cards + } +} + +fn main() { + let file_path = "input/07input.txt"; + let contents = fs::read_to_string(file_path).expect("should read file"); + let mut lines = contents.lines(); + let mut hands: Vec = Vec::new(); + loop { + let line = lines.next(); + if line.is_none() { + break; + } + let mut line_parts = line.unwrap().split_whitespace(); + let hand_cards: Vec = line_parts.next().unwrap().chars().map(|x| match x{ + '2' => Card::Two, + '3' => Card::Three, + '4' => Card::Four, + '5' => Card::Five, + '6' => Card::Six, + '7' => Card::Seven, + '8' => Card::Eight, + '9' => Card::Nine, + 'T' => Card::Ten, + 'J' => Card::Joker, + 'Q' => Card::Queen, + 'K' => Card::King, + 'A' => Card::Ace, + _ => Card::None, + }).collect(); + let bet = line_parts.next().unwrap().parse::().ok().unwrap(); + let hand = hand_from_cards(bet, hand_cards); + let loc_val: usize; + match hands.binary_search_by(|probe| probe.cmp(&hand)) { + Ok(v) => loc_val = v, + Err(v) => loc_val = v, + } + hands.insert(loc_val, hand); + } + let mut total_winnings: u128 = 0; + for i in 0..hands.len() { + total_winnings += hands[i].bet * (i + 1).to_string().parse::().ok().unwrap(); + } + println!("{}", total_winnings); +} + +fn hand_from_cards(bet: u128, cards: Vec) -> Hand { + let hand_type: HandType; + let mut cards_map = HashMap::new(); + for card in cards.iter() { + if cards_map.get(&card).is_none() { + cards_map.insert(card, 0); + } + cards_map.insert(&card, 1+cards_map.get(&card).unwrap()); + } + let mut hand_cards: Vec = Vec::new(); + let mut hand_card_counts = Vec::new(); + for card in cards_map.keys() { + for _i in 0..cards_map[card] { + let mut matched = false; + for j in 0..hand_card_counts.len() { + if hand_card_counts[j] > cards_map[card] { + hand_card_counts.insert(j, cards_map[card]); + hand_cards.insert(j, *card.to_owned()); + matched = true; + break; + } + } + if !matched && hand_card_counts.len() > 0 { + hand_card_counts.insert(hand_card_counts.len()-1, cards_map[card]); + hand_cards.insert(hand_card_counts.len()-1, *card.to_owned()); + } else if !matched { + hand_card_counts.insert(0, cards_map[card]); + hand_cards.insert(0, *card.to_owned()); + } + } + } + hand_cards.reverse(); + if + (hand_cards[0] == hand_cards[1] && hand_cards[1] == hand_cards[2] && hand_cards[2] == hand_cards[3] && hand_cards[3] == hand_cards[4]) || // AAAAA + (hand_cards[4] == Card::Joker && hand_cards[0] == hand_cards[1] && hand_cards[1] == hand_cards[2] && hand_cards[2] == hand_cards[3]) || // AAAAJ + (hand_cards[3] == Card::Joker && hand_cards[4] == Card::Joker && hand_cards[0] == hand_cards[1] && hand_cards[1] == hand_cards[2]) || // AAAJJ + (hand_cards[0] == Card::Joker && hand_cards[1] == Card::Joker && hand_cards[2] == Card::Joker && hand_cards[3] == hand_cards[4]) || // JJJAA + (hand_cards[2] == Card::Joker && hand_cards[3] == Card::Joker && hand_cards[0] == Card::Joker && hand_cards[1] == Card::Joker) // JJJJA + { + hand_type = HandType::FiveOfAKind; + } else if + (hand_cards[0] == hand_cards[1] && hand_cards[1] == hand_cards[2] && hand_cards[2] == hand_cards[3]) || // AAAAB + (hand_cards[3] == Card::Joker && hand_cards[1] == hand_cards[2] && hand_cards[2] == hand_cards[0]) || // AAAJB + (hand_cards[4] == Card::Joker && hand_cards[1] == hand_cards[2] && hand_cards[2] == hand_cards[0]) || // AAABJ + (hand_cards[2] == Card::Joker && hand_cards[3] == Card::Joker && hand_cards[0] == hand_cards[1]) || // AAJJB + (hand_cards[0] == Card::Joker && hand_cards[1] == Card::Joker && hand_cards[2] == hand_cards[3]) || // JJAAB + (hand_cards[1] == Card::Joker && hand_cards[2] == Card::Joker && hand_cards[0] == Card::Joker) // JJJAB + { + hand_type = HandType::FourOfAKind; + } else if + (hand_cards[0] == hand_cards[1] && hand_cards[1] == hand_cards[2] && hand_cards[3] == hand_cards[4]) || // AAABB + (hand_cards[0] == hand_cards[1] && hand_cards[2] == hand_cards[3] && hand_cards[4] == Card::Joker) // AABBJ + { + hand_type = HandType::FullHouse; + } else if + (hand_cards[0] == hand_cards[1] && hand_cards[1] == hand_cards[2]) || // AAABC + (hand_cards[0] == hand_cards[1] && hand_cards[2] == Card::Joker) || // AAJBC + (hand_cards[0] == hand_cards[1] && hand_cards[3] == Card::Joker) || // AABJC + (hand_cards[0] == hand_cards[1] && hand_cards[4] == Card::Joker) || // AABCJ + (hand_cards[0] == Card::Joker && hand_cards[1] == Card::Joker) // JJABC + { + hand_type = HandType::ThreeOfAKind; + } else if + hand_cards[0] == hand_cards[1] && hand_cards[2] == hand_cards[3] // AABBC + { + hand_type = HandType::TwoPair; + } else if + hand_cards[0] == hand_cards[1] || // AABCD + hand_cards[0] == Card::Joker || // JABCD + hand_cards[1] == Card::Joker || // AJBCD + hand_cards[2] == Card::Joker || // ABJCD + hand_cards[3] == Card::Joker || // ABCJD + hand_cards[4] == Card::Joker // ABCDJ + { + hand_type = HandType::OnePair; + } else { // ABCDE + hand_type = HandType::HighCard; + } + // println!("{:?} {:?}", hand_cards, hand_type); + return Hand {bet, hand_type, cards}; +}