diff --git a/2023/src/day07.rs b/2023/src/day07.rs index e2d0cc2..2734591 100644 --- a/2023/src/day07.rs +++ b/2023/src/day07.rs @@ -5,7 +5,7 @@ use nom::combinator::map_res; use nom::multi::many1; use nom::sequence::pair; use nom::sequence::terminated; -use nom::IResult; +use nom::Parser; use crate::common::parse_input; @@ -20,23 +20,42 @@ enum Kind { FiveOfAKind, } -impl<'a> From<&'a [u8; 5]> for Kind { - fn from(cards: &'a [u8; 5]) -> Self { - let mut counts = [0u8; 15]; - for &card in cards { - counts[card as usize] += 1; - } +fn kind_parser1(cards: &[u8; 5]) -> Kind { + let mut counts = [0u8; 15]; + for &card in cards { + counts[card as usize] += 1; + } - counts.sort_unstable(); - match (counts[14], counts[13]) { - (5, _) => Kind::FiveOfAKind, - (4, _) => Kind::FourOfAKind, - (3, 2) => Kind::FullHouse, - (3, _) => Kind::ThreeOfAKind, - (2, 2) => Kind::TwoPair, - (2, _) => Kind::Pair, - _ => Kind::HighCard, - } + counts.sort_unstable(); + match (counts[14], counts[13]) { + (5, _) => Kind::FiveOfAKind, + (4, _) => Kind::FourOfAKind, + (3, 2) => Kind::FullHouse, + (3, _) => Kind::ThreeOfAKind, + (2, 2) => Kind::TwoPair, + (2, _) => Kind::Pair, + _ => Kind::HighCard, + } +} + +fn kind_parser2(cards: &[u8; 5]) -> Kind { + let mut counts = [0u8; 15]; + for &card in cards { + counts[card as usize] += 1; + } + + let jokers = counts[11]; + counts[11] = 0; + + counts.sort_unstable(); + match (counts[14] + jokers, counts[13]) { + (5, _) => Kind::FiveOfAKind, + (4, _) => Kind::FourOfAKind, + (3, 2) => Kind::FullHouse, + (3, _) => Kind::ThreeOfAKind, + (2, 2) => Kind::TwoPair, + (2, _) => Kind::Pair, + _ => Kind::HighCard, } } @@ -46,7 +65,9 @@ struct Hand { kind: Kind, } -fn parse_hands(i: &[u8]) -> IResult<&[u8], Vec> { +fn hands_parser<'a>( + kind_parser: impl Fn(&[u8; 5]) -> Kind, +) -> impl Parser<&'a [u8], Vec, nom::error::Error<&'a [u8]>> { fn map_card(c: u8) -> anyhow::Result { Ok(match c { d @ b'2'..=b'9' => d - b'0', @@ -64,21 +85,19 @@ fn parse_hands(i: &[u8]) -> IResult<&[u8], Vec> { terminated(take(5usize), tag(" ")), terminated(nom::character::complete::u32, newline), ), - |(hand, bid)| -> anyhow::Result { + move |(hand, bid)| -> anyhow::Result { let mut cards = [0; 5]; for (t, &s) in cards.iter_mut().zip(hand) { *t = map_card(s)? } - let kind = Kind::from(&cards); + let kind = kind_parser(&cards); Ok(Hand { cards, bid, kind }) }, - ))(i) + )) } -pub fn part1(input: &[u8]) -> anyhow::Result { - let mut hands = parse_input(input, parse_hands)?; - +fn parts_common(hands: &mut [Hand]) -> anyhow::Result { hands.sort_unstable_by(|first, second| { first .kind @@ -95,8 +114,17 @@ pub fn part1(input: &[u8]) -> anyhow::Result { Ok(sum.to_string()) } -pub fn part2(_input: &[u8]) -> anyhow::Result { - anyhow::bail!("Not implemented") +pub fn part1(input: &[u8]) -> anyhow::Result { + let mut hands = parse_input(input, hands_parser(kind_parser1))?; + + parts_common(&mut hands) +} + +// Too high: 248859461 +pub fn part2(input: &[u8]) -> anyhow::Result { + let mut hands = parse_input(input, hands_parser(kind_parser2))?; + + parts_common(&mut hands) } #[cfg(test)] @@ -109,4 +137,9 @@ mod tests { fn sample_part1() { assert_eq!(part1(SAMPLE).unwrap(), "6440"); } + + #[test] + fn sample_part2() { + assert_eq!(part2(SAMPLE).unwrap(), "5905"); + } } diff --git a/2023/src/samples/07.txt b/2023/src/samples/07.txt new file mode 100644 index 0000000..e3500c3 --- /dev/null +++ b/2023/src/samples/07.txt @@ -0,0 +1,5 @@ +32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483