I may be pushing the definition of parse

No Nvim homework section today. Kinda short on time, unfortunately.

The task itself

Code

Relatively pleasant and simple today. For the first part, I wrote a parse that returned two Vecs for every line of input—one for the numbers on the card, and one for the draws. From there it was easy to calculate a score for each and sum it.

When I saw part 2, however, I realized that both parts only care about the number of matches on each card, the numbers themselves are irrelevant. So I refactored it so that the whole number intersection logic is part of parse:

fn parse(input: &str) -> impl Iterator<Item = usize> + '_ {
    fn to_numbers(s: &str) -> impl Iterator<Item = i32> + '_ {
        s.split_whitespace().filter_map(|n| n.parse().ok())
    }

    input.lines().filter_map(|line| {
        let (_, numbers) = line.split_once(": ")?;
        let (card, draws) = numbers.split_once(" | ")?;

        let card: Vec<_> = to_numbers(card).collect();
        Some(to_numbers(draws).filter(|n| card.contains(n)).count())
    })
}

So I simply return an iterator of usizes now (match count for each card), which simplifies both of the solutions. I technically have a chunk of non-text-parsing logic in parse now, but in my defense, it is still "extracting relevant information from a text file"...

My part 2 solution uses a trick I already used in the past; every time I see this sort of recursive counting exercise, I know it's built specifically to foil solutions that try to go through every branch and sum them up one by one.

Instead of doing that, I have two arrays (well, Vecs.): scores and counts. scores[i] contains the number of matches for the ith card, and counts[i] contains how many of that card I have. Then it becomes a simple double for loop:

pub fn two(input: &str) -> crate::Result<usize> {
    let scores: Vec<_> = parse(input).collect();
    let mut counts = vec![1; scores.len()];

    for i in 0..scores.len() {
        for n in 1..=scores[i] {
            counts[i + n] += counts[i];
        }
    }

    Ok(counts.into_iter().sum())
}

Whenever I get a solution to run in less than a millisecond, I feel like I truly solved it. c: