Advent of Code 2022: Day 14

Да, «тетрис» был определённо приятней вчерашних «скобочек». И концептуально, и в реализации. Старые-добрые циклы-в-циклах — что может быть лучше!? 🙂

Только циклы, приправленные щепоткой стримов, конечно! Впрочем, попытки решить вторую часть через стрим — не увенчались успехом, увы. Приступ стримоза отступил и циклы вошли в свои права.

Песок и камни, или — камни и песок

static int drawRock(String scanLine, boolean[][] gameField) {
    int maxY = 0;
    String[] XY = scanLine.split(" -> ");
    for (int i = 0; i < XY.length - 1; i++) {
        int[] rocks = IntStream.rangeClosed(i, i + 1).mapToObj(idx -> XY[idx].split(","))
            .flatMap(Arrays::stream).mapToInt(Integer::parseInt).toArray();
        for (int j = Math.min(rocks[0], rocks[2]); j <= Math.max(rocks[0], rocks[2]); j++) {
            for (int k = Math.min(rocks[1], rocks[3]); k <= Math.max(rocks[1], rocks[3]); k++) {
                gameField[j][k] = true;
            }
        }
        maxY = Math.max(maxY, Math.max(rocks[1], rocks[3]));
    }
    return maxY;
}

static boolean pourSand(int maxY, boolean[][] gameField) {
    if (gameField[500][0]) return false;
    int x = 500;
    int y = 0;
    while (y <= maxY + 3) {
        if (!gameField[x][y + 1]) {
            y++;
            continue;
        } else if (!gameField[x - 1][y + 1]) {
            x--;
            y++;
            continue;
        } else if (!gameField[x + 1][y + 1]) {
            x++;
            y++;
            continue;
        }
        return gameField[x][y] = true;
    }
    return false;
}

Обратная засыпка по самое горлышко

static void day14(String puzzleInputUri) throws IOException, InterruptedException {
    boolean[][] gameField = new boolean[1000][1000];
    var maxY = client.send(request.uri((URI.create(puzzleInputUri))).build(), HttpResponse.BodyHandlers.ofLines())
        .body()
        .mapToInt(scanLine -> drawRock(scanLine, gameField))
        .max().orElse(0);

    int answer = 0;
    drawRock( "0," + (maxY + 2) + " -> " + (gameField[0].length - 1) + "," + (maxY + 2), gameField);
    while (pourSand(maxY, gameField)) {
        answer++;
    }
    System.out.println(answer);
}

Капля стримоза

Первая часть загадки через стрим решилась без особых проблем, и даже выглядела не слишком страшно:

var sandCnt = client.send(request.uri((URI.create(puzzleInputUri))).build(), HttpResponse.BodyHandlers.ofLines())
        .body()
        .mapToInt(scanLine -> drawRock(scanLine, gameField))
        .max()
        .stream().mapToObj(mY ->
            IntStream.rangeClosed(0, gameField.length)
                .mapToObj(i -> pourSand(mY, gameField))
                .takeWhile(Boolean.TRUE::equals)
                .count()
        )
        .findAny()
        .orElseThrow();
    System.out.println(sandCnt);

А вот со второй — возникли проблемы. Попытки подсунуть в стрим «пол пещеры» в таком виде:

.peek(maxY -> drawRock( "0," + (maxY + 2) + " -> " + (gameField[0].length - 1) + "," + (maxY + 2), gameField))

не приводили к успеху — ответ никак не сходился. Пришлось вернуться к циклам.

Исходные данные: https://adventofcode.com/2022/day/14/input

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *