use std::cmp::max; 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() .filter(|x| **x != 0) .copied() .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 max_type(count: &Vec, joker: u32) -> u32 { if joker == 0 { return card_type(count); } else { let mut mt = 0; for i in 0..count.len() { let mut c = count.to_vec(); c[i] += 1; mt = max(mt, max_type(&c, joker - 1)); } return mt; } } fn get_card_type(c: &Vec) -> u32 { let c_noj: Vec = c.iter().filter(|x| **x != 0).copied().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); max_type(&count, joker) } fn compare_cards(c1: &Vec, type1: u32, c2: &Vec, type2: u32) -> Ordering { if type1 > type2 { return Ordering::Greater; } else if type1 < type2 { return Ordering::Less; } else { for (e1, e2) in c1.iter().zip(c2.iter()) { if e1 > e2 { return Ordering::Greater; } else if e1 < e2 { return Ordering::Less; } } } Ordering::Equal } fn string_to_card(s: &str) -> Vec { // let map = [ // '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A', // ]; let map = [ 'J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A', ]; let mut out = Vec::new(); for c in s.chars() { out.push(map.iter().position(|x| x == &c).unwrap() as u8); } out } 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 mut hands: Vec = Vec::new(); for line in lines.iter() { let (cards, bid) = line.split_once(" ").unwrap(); let cards = string_to_card(cards); hands.push(Hand { cards: cards.clone(), bid: bid.parse().unwrap(), ct: get_card_type(&cards), }); } hands.sort_by(|x, y| compare_cards(&x.cards, x.ct, &y.cards, y.ct)); let mut res1 = 0; let mut res2 = 0; for (i, h) in hands.iter().enumerate() { // println!("{:?} {}", h.cards, h.ct); res2 += (i as u32 + 1) * h.bid; } println!("res1: {}", res1); println!("res2: {}", res2); }