use std::cmp::Ordering; #[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] enum HandType { FiveOfAKind, FourOfAKind, FullHouse, ThreeOfAKind, TwoPair, OnePair, HighCard, } #[derive(Debug)] struct Hand { cards: Vec, bid: usize, r#type: Option, } static CARD_ORDER: &[char] = &[ 'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2', ]; static CARD_ORDER2: &[char] = &[ 'A', 'K', 'Q', 'T', '9', '8', '7', '6', '5', '4', '3', '2', 'J', ]; impl Hand { fn get_type(&self, allow_joker: bool) -> HandType { // Five of a kind for card in &self.cards { let mut good = 0; for card2 in &self.cards { if *card == *card2 || (allow_joker && *card2 == 'J') { good += 1; } } if good == 5 { return HandType::FiveOfAKind; } } // Four of a kind for card in &self.cards { let mut good = 0; for card2 in &self.cards { if *card == *card2 || (allow_joker && *card2 == 'J') { good += 1; } } if good == 4 { return HandType::FourOfAKind; } } // Full house for card in &self.cards { for card2 in &self.cards { let mut good = 0; let mut good2 = 0; let mut used_jokers = vec![false; 5]; for (i, card3) in self.cards.iter().enumerate() { if *card == *card3 || (allow_joker && *card3 == 'J') { good += 1; if allow_joker && *card3 == 'J' { used_jokers[i] = true; } } } for (i, card4) in self.cards.iter().enumerate() { if *card2 == *card4 || (allow_joker && !used_jokers[i] && *card4 == 'J') { good2 += 1; } } if ((good == 3 && good2 == 2) || (good == 2 && good2 == 3)) && *card != *card2 && (!allow_joker || (allow_joker && *card != 'J' && *card2 != 'J')) { return HandType::FullHouse; } } } // Three of a kind for card in &self.cards { let mut good = 0; for card2 in &self.cards { if *card == *card2 || (allow_joker && *card2 == 'J') { good += 1; } } if good == 3 { return HandType::ThreeOfAKind; } } // Two pair for card in &self.cards { for card2 in &self.cards { let mut good = 0; let mut good2 = 0; let mut used_jokers = vec![false; 5]; for (i, card3) in self.cards.iter().enumerate() { if *card == *card3 || (allow_joker && *card3 == 'J') { good += 1; if allow_joker && *card3 == 'J' { used_jokers[i] = true; } } } for (i, card4) in self.cards.iter().enumerate() { if *card2 == *card4 || (allow_joker && !used_jokers[i] && *card4 == 'J') { good2 += 1; } } if ((good == 2 && good2 == 2) || (good == 2 && good2 == 2)) && card != card2 { return HandType::TwoPair; } } } // One pair for card in &self.cards { let mut good = 0; for card2 in &self.cards { if *card == *card2 || (allow_joker && *card2 == 'J') { good += 1; } } if good == 2 { return HandType::OnePair; } } HandType::HighCard } } fn main() { let stdin = std::io::stdin(); let mut hands = Vec::new(); for line in stdin.lines() { let line = line.unwrap(); let (cards, bid) = line.split_once(" ").unwrap(); let cards = cards.chars().collect(); let bid = bid.parse().unwrap(); hands.push(Hand { cards, bid, r#type: None, }) } // Part1 let mut part1 = 0; for hand in &mut hands { hand.r#type = Some(hand.get_type(false)); } hands.sort_by(cmp); for (i, hand) in hands.iter().enumerate() { part1 += (i + 1) * hand.bid; } println!("{}", part1); // Part2 let mut part2 = 0; for hand in &mut hands { hand.r#type = Some(hand.get_type(true)); } hands.sort_by(cmp2); for (i, hand) in hands.iter().enumerate() { part2 += (i + 1) * hand.bid; } println!("{}", part2); } fn cmp(hand1: &Hand, hand2: &Hand) -> Ordering { if hand1.r#type.unwrap() == hand2.r#type.unwrap() { for (card1, card2) in hand1.cards.iter().zip(hand2.cards.iter()) { let mut card1_idx = 0; let mut card2_idx = 0; for i in 0..CARD_ORDER.len() { if CARD_ORDER[i] == *card1 { card1_idx = i; } } for i in 0..CARD_ORDER.len() { if CARD_ORDER[i] == *card2 { card2_idx = i; } } if card1_idx == card2_idx { continue; } return card2_idx.cmp(&card1_idx); } } return hand2.r#type.cmp(&hand1.r#type); } fn cmp2(hand1: &Hand, hand2: &Hand) -> Ordering { if hand1.r#type.unwrap() == hand2.r#type.unwrap() { for (card1, card2) in hand1.cards.iter().zip(hand2.cards.iter()) { let mut card1_idx = 0; let mut card2_idx = 0; for i in 0..CARD_ORDER2.len() { if CARD_ORDER2[i] == *card1 { card1_idx = i; } } for i in 0..CARD_ORDER2.len() { if CARD_ORDER2[i] == *card2 { card2_idx = i; } } if card1_idx == card2_idx { continue; } return card2_idx.cmp(&card1_idx); } } return hand2.r#type.cmp(&hand1.r#type); }