use std::cmp::Ordering; use std::collections::HashSet; use std::fs; static CARDS: &'static str = "23456789TJQKA"; static CARDS2: &'static str = "J23456789TQKA"; #[macro_use(c)] extern crate cute; #[derive(Debug, Clone)] struct Hand<'a> { cards: String, bid: u32, cards_ranking: &'a str, original_cards: String, } #[derive(Debug)] enum HandType { HighCard, OnePair, TwoPair, ThreeOfAKind, FullHouse, FourOfAKind, FiveOfAKind, } impl Hand<'_> { fn get_hand_type(&self) -> HandType { let uniq_cards: Vec = self .cards .chars() .into_iter() .collect::>() .into_iter() .collect::>(); let mut cards = c![(key,self.cards.chars().filter(|char| char == &key).collect::>().len()), for key in uniq_cards]; cards.sort_by(|a, b| a.1.cmp(&b.1)); match cards.last().unwrap().1 { 5 => HandType::FiveOfAKind, 4 => HandType::FourOfAKind, 3 if cards.len() == 2 => HandType::FullHouse, 3 => HandType::ThreeOfAKind, 2 if cards.len() == 3 => HandType::TwoPair, 2 => HandType::OnePair, 1 => HandType::HighCard, _ => panic!("Unknown card in {cards:?}"), } } fn replace_jokers(&mut self) { if self.cards.contains("J") { let mut tmp_vec: Vec = Vec::new(); for elem in CARDS.chars().filter(|letter| letter != &'J') { tmp_vec.push(Hand { cards: self.cards.clone().replace("J", elem.to_string().as_str()), bid: 0, cards_ranking: self.cards_ranking.clone(), original_cards: self.original_cards.clone() }); } tmp_vec.sort(); self.cards = tmp_vec.last().unwrap().cards.clone(); } } } impl PartialEq for Hand<'_> { fn eq(&self, other: &Self) -> bool { self.original_cards == other.original_cards } } impl Eq for Hand<'_> {} impl Ord for Hand<'_> { fn cmp(&self, other: &Self) -> Ordering { if self.get_hand_type() as u8 > other.get_hand_type() as u8 { return Ordering::Greater; } if (self.get_hand_type() as u8) < other.get_hand_type() as u8 { return Ordering::Less; } else { for i in 0..5 { let selfcard = self.original_cards.chars().collect::>()[i]; let othercard = other.original_cards.chars().collect::>()[i]; if self.cards_ranking.find(selfcard) > other.cards_ranking.find(othercard) { return Ordering::Greater; } if self.cards_ranking.find(selfcard) < other.cards_ranking.find(othercard) { return Ordering::Less; } } } Ordering::Equal } } impl PartialOrd for Hand<'_> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } fn main() { let content = fs::read_to_string("input").expect("Could not read the file"); let part1 = part1(content.clone()); println!("Part 1: {}", part1); let part2 = part2(content); println!("Part 2: {}", part2); } fn part1(content: String) -> i64 { let lines = content.split("\n").collect::>(); let mut hands = c![Hand{ cards: String::from(line.split(" ").collect::>()[0]), bid: line.split(" ").collect::>()[1].parse::().unwrap(), cards_ranking: CARDS, original_cards: String::from(line.split(" ").collect::>()[0]) }, for line in lines]; let mut score: i64 = 0; hands.sort(); for i in 0..hands.len() { let hand = hands.get(i).unwrap(); score += hand.bid as i64 * (i as i64 + 1); } return score; } fn part2(content: String) -> i64 { let lines = content.split("\n").collect::>(); let mut hands = c![Hand{ cards: String::from(line.split(" ").collect::>()[0]), bid: line.split(" ").collect::>()[1].parse::().unwrap(), cards_ranking: CARDS2, original_cards: String::from(line.split(" ").collect::>()[0]) }, for line in lines]; for h in &mut hands { h.replace_jokers(); } let mut score: i64 = 0; hands.sort(); for i in 0..hands.len() { let hand = hands.get(i).unwrap(); score += hand.bid as i64 * (i as i64 + 1); } for h in hands{ println!("{}:{}\twas\t{}", h.cards, h.bid, h.original_cards) } return score; }