use std::cmp::Ordering; use std::fs::File; use std::io::Read; #[derive(Debug)] struct Hand { cards: Vec, ct: u32, bid: u32, } fn count_cards(arr: &Vec) -> Vec { let mut count = [0; 256].to_vec(); for a in arr { count[*a as usize] += 1; } let mut count = count .iter() .copied() .filter(|x| *x != 0) .collect::>(); count.sort(); count.reverse(); count } fn card_type(count: &Vec) -> u32 { // returns card type from card count if count[0] == 5 { return 6; } else if count[0] == 4 { return 5; } else if count[0] == 3 && count[1] == 2 { return 4; } else if count[0] == 3 { return 3; } else if count[0] == 2 && count[1] == 2 { return 2; } else if count[0] == 2 { return 1; } else { return 0; } } fn get_card_type1(c: &Vec) -> u32 { card_type(&count_cards(&c)) } fn get_card_type2(c: &Vec) -> u32 { let c_noj: Vec = c.iter().copied().filter(|x| *x != 0).collect(); let joker = c .iter() .fold(0, |acc, x| if *x == 0 { acc + 1 } else { acc }); let mut count = count_cards(&c_noj); count.push(0); count[0] += joker; card_type(&count) } fn compare_hands(h1: &Hand, h2: &Hand) -> Ordering { if h1.ct > h2.ct { return Ordering::Greater; } else if h1.ct < h2.ct { return Ordering::Less; } else { for (e1, e2) in h1.cards.iter().zip(h2.cards.iter()) { if e1 > e2 { return Ordering::Greater; } else if e1 < e2 { return Ordering::Less; } } } Ordering::Equal } fn string_to_card(s: &str, map: &[char]) -> Vec { s.chars() .map(|c| map.iter().position(|x| x == &c).unwrap() as u8) .collect() } fn main() { // let filename = "in/day07.ref"; let filename = "in/day07.pzl"; let mut f = File::open(filename).expect("cannot open file"); let mut content = String::new(); f.read_to_string(&mut content).expect("cannot read file"); let lines: Vec<_> = content.trim_end().split('\n').collect(); let map1 = [ '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A', ]; let map2 = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A', ]; let mut hands1: Vec = Vec::new(); let mut hands2: Vec = Vec::new(); for line in lines.iter() { let (cards, bid) = line.split_once(" ").unwrap(); let cards1 = string_to_card(&cards, &map1); let cards2 = string_to_card(&cards, &map2); hands1.push(Hand { cards: cards1.clone(), bid: bid.parse().unwrap(), ct: get_card_type1(&cards1), }); hands2.push(Hand { cards: cards2.clone(), bid: bid.parse().unwrap(), ct: get_card_type2(&cards2), }); } hands1.sort_by(compare_hands); let mut res1 = 0; for (i, h) in hands1.iter().enumerate() { // println!("{:?} {}", h.cards, h.ct); res1 += (i as u32 + 1) * h.bid; } hands2.sort_by(compare_hands); let mut res2 = 0; for (i, h) in hands2.iter().enumerate() { // println!("{:?} {}", h.cards, h.ct); res2 += (i as u32 + 1) * h.bid; } println!("res1: {}", res1); println!("res2: {}", res2); assert_eq!(res1, 250232501); assert_eq!(res2, 249138943); }