Advent of Code 2023: Day 4: Scratchcards

Про задачу четвертого дня сказать особенно нечего. По условию – проще третей. По парсингу ввода – проще второй. Решается быстро.

Сразу прикинул, что с использованием примитивов или оборачиванием в типы из стандартной библиотеки – будет портяночно. Поэтому – отдельный класс с логикой:

public class Card {
    private static final Predicate<String> EMPTY = s -> " ".equals(s) || "".equals(s);
    Integer cardN, winCnt;
    Set<Integer> win, have;
    List<Card> nextCards = new ArrayList<>(); // added for part 2
    public Card(String cardN, String[] win, String[] have) {
        this.cardN = Integer.parseInt(cardN.replaceAll("^Card\\s+", ""));
        this.win = parseNums(win);
        this.have = parseNums(have);
        this.winCnt = (int) this.have.stream().filter(h -> this.win.contains(h)).count();
    }
    void addNext(List<Card> nextCards) { // added for part 2
        this.nextCards.addAll(nextCards);
    }
    Stream<Card> flat() { // added for part 2
        return Stream.concat(Stream.of(this),
                this.nextCards.stream().flatMap(Card::flat));
    }
    private static Set<Integer> parseNums(String[] nums) {
        return Arrays.stream(nums).filter(not(EMPTY)).map(Integer::parseInt)
                .collect(Collectors.toSet());
    }
};

И короткое решение с его помощью:

static void day4(String puzzleInputUri) throws IOException, InterruptedException {
    var cards = client.send(request.uri((URI.create(puzzleInputUri))).build(),
                    HttpResponse.BodyHandlers.ofLines()).body()
            .map(it -> it.split(":", 2))
            .map(it -> Map.entry(it[0], it[1].split("\\|", 2)))
            .map(it -> new Card(it.getKey(), it.getValue()[0].split(" "),
                    it.getValue()[1].split(" ")))
            .toList();

    var answer1 = cards.stream()
            .filter(card -> card.winCnt > 0)
            .mapToInt(card -> card.winCnt)
            .mapToDouble(win -> Math.pow(2, (win - 1)))
            .reduce(Double::sum).orElseThrow();
    System.out.println(answer1); // 20117

    var answer2 = IntStream.iterate(cards.size() - 1, i -> i >= 0, i -> i - 1)
            .mapToObj(cards::get)
            .peek(card -> card.addNext(cards.subList(card.cardN, card.cardN + card.winCnt)))
            .flatMap(card -> card.flat())
            .count();
    System.out.println(answer2); // 13768818
}
https://adventofcode.com/2023/day/4