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))

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

Начать дискуссию