use std::convert::TryInto; #[path = "../lib.rs"] mod lib; fn parse_line(line: &str) -> Option<([u8; 5], usize)> { let (hand, bid) = line.split_once(" ")?; let h = hand .chars() .map(|c| match c { '2' => 1, '3' => 2, '4' => 3, '5' => 4, '6' => 5, '7' => 6, '8' => 7, '9' => 8, 'T' => 9, 'J' => 10, 'Q' => 11, 'K' => 12, 'A' => 13, _ => unreachable!(), }) .collect::>() .try_into() .ok()?; let b = bid.parse().ok()?; return Some((h, b)); } fn replace_jokers(hand: [u8; 5]) -> [u8; 5] { let mut new_hand = [0; 5]; for i in 0..5 { new_hand[i] = match hand[i] { 10 => 0, x => x, }; } return new_hand; } fn key(hand: [u8; 5]) -> (u8, [u8; 5]) { let mut counts = [0; 14]; let mut jokers = 0; for i in 0..5 { if hand[i] == 0 { jokers += 1; } else { counts[hand[i] as usize] += 1; } } counts.sort(); counts[13] += jokers; let type_ = match counts { [.., 0, 0, 0, 0, 5] => 6, [.., 0, 0, 0, 1, 4] => 5, [.., 0, 0, 0, 2, 3] => 4, [.., 0, 0, 1, 1, 3] => 3, [.., 0, 0, 1, 2, 2] => 2, [.., 0, 1, 1, 1, 2] => 1, [.., 1, 1, 1, 1, 1] => 0, _ => unreachable!(), }; return (type_, hand); } fn count(lines: &Vec<([u8; 5], usize)>) -> usize { return lines .iter() .enumerate() .map(|(rank, (_, bid))| bid * (rank + 1)) .sum(); } fn main() { let mut lines = vec![]; for line in lib::iter_input() { lines.push(parse_line(&line).unwrap()); } lines.sort_by_cached_key(|(hand, _)| key(*hand)); let sum1 = count(&lines); println!("part1: {}", sum1); lines.sort_by_cached_key(|(hand, _)| key(replace_jokers(*hand))); let sum2 = count(&lines); println!("part2: {}", sum2); }