Advent of Code 2022: Day 9

Вариация на тему змейки — это любопытно. Задачка решилась бы быстро, если бы не моя невнимательность.

Проклятая невнимательность! Она стоила мне пары часов бесплодных поисков ошибок в формулах перемещения узла.

К счастью, решение второй части не потребовало каких-то кардинальных изменений — просто больше узлов, больше хвостов. Но, сколь веревочке ни виться, — ответ будет найден!

Для начала — сделал узелки — «головы» и «хвосты» (и это я не про самогоноварение сейчас).

class RopeKnot {
    public Set<List<Integer>> visited = new HashSet<>();
    public int x;
    public int y;
}

class Head extends RopeKnot {
    public void doStep(String direction) {
        if ("R".equals(direction)) this.x++;
        if ("L".equals(direction)) this.x--;
        if ("U".equals(direction)) this.y++;
        if ("D".equals(direction)) this.y--;
    }
}

class Tail extends RopeKnot {
    private final RopeKnot head;
    public Tail(RopeKnot head) {
        this.head = head;
    }
    public void doFollow() {
        int dX = head.x - this.x;
        int dY = head.y - this.y;
        if (Math.abs(dX) == 2 && dY == 0) {
            this.x += dX > 0 ? 1 : -1;
        } else if (Math.abs(dY) == 2 && dX == 0) {
            this.y += dY > 0 ? 1 : -1;
        } else if (Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2)) > 2d) {
            this.x += dX > 0 ? 1 : -1;
            this.y += dY > 0 ? 1 : -1;
        }
        visited.add(List.of(this.x, this.y));
    }
}

Вот где здесь можно ошибиться? Инкремент, декремент, три вида перемещения — положительно — негде! Однако — именно здесь я и пытался безуспешно найти сбой.

Сам алгоритм плетения узлов тоже не поражает сложностью:

static void day9(String puzzleInputUri) throws IOException, InterruptedException {
    Head h = new Head();
    Tail t1 = new Tail(h);
    List<Tail> knots = new ArrayList<>(List.of(t1));
    for (int i = 1; i < 9; i++) {
        knots.add(new Tail(knots.get(i-1)));
    }

    client.send(request.uri((URI.create(puzzleInputUri))).build(), HttpResponse.BodyHandlers.ofLines()).body()
        .map(line -> line.split(" "))
        .forEachOrdered(command -> {
            for (int i = 0; i < Integer.parseInt(command[1]); i++) {
                h.doStep(command[0]);
                knots.forEach(tail -> tail.doFollow());
            }
        });

    System.out.println(knots.get(0).visited.size());
    System.out.println(knots.get(knots.size() - 1).visited.size());
}

Но именно в нём крылась досадная ошибка! Парсинг количества перемещений я скопипастил с решения восьмого дня, и он представлял собой такую конструкцию: command[1].charAt(0) - '0'. Всё это прекрасно работало на тестовом примере и ни в какую не хотело выдавать верный ответ на рабочем наборе данных 🙁

Проверил на бумажке в клетку несколько перемещений. Распечатал историю движения хвоста. Всё совпадает, всё верно! Уже было думал переписать на вложенных циклах и двигать не «точки по карте», а «карту под точками». К счастью — не пришлось.

Бесплодные мучения продолжались до тех пор, пока я не пролистал весь входной набор и не заметил, наконец (как индеец «Зоркий глаз»), что шаги бывают заданы двузначными числами.

«Эврика!» — воскликнул Архимед. А я воскликнул — «Идиот!». Быстренько поправил парсинг и, с глубоким облегчением, отправил верные ответы на загадку!

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

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

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