15. des. 2024 - 5 minutter å lese

Advent of Code 2024 - Luke 15

Advent of Code 2024 - Luke 15

Full kode finner du her.

Main metode

For alle oppgavene i 2024 bruker jeg Java, og dette vil være metoden jeg bruker for å hente input for de ulike oppgavene. Input blir lagret i en txt fil og hentes via denne metoden.

Oppgave 1 (og 2)

For luke 15 i kalenderen er skal vi hjelpe “lanternfish” med å finne frem til mat. Vi skal simulere en robot basert på en gitt grid, start posisjon og instrukser roboten følger. Roboten vil flytte på esker (O) dersom den kolliderer med dem, og så stille dersom den kolliderer med en vegg. Etter å ha gjennomført instruksjonene vil roboten og boksene ende opp på nye lokasjoner. Det er vår oppgave å kalkulere score for hver boks gitt formelen Y * 100 + X * 1, for så å summere disse. Oppgave 2 går ut på å gjøre det samme, alt blir dobbelt så stort sidelengs. Altså blir O til [] og # til ## osv. Robot er enda kun 1 felt, og som @. Det betyr at vi må sjekke for om roboten kolliderer med en boks, og om den boksen sin kant altså enten ”]” eller ”[” kolliderer med en vegg eller en annen boks. Den fullstendige koden jeg kom frem til blir slik:

Opprette grids:

int size = lines.getFirst().length();
char[][] grid = new char[size][size];
char[][] grid2 = new char[size][size*2];
int fx = 0, fy = 0, fy2 = 0, fx2 = 0;
boolean isBoard = true;

for(int i = 0; i < lines.size(); i++){
    String line = lines.get(i);
    if(line.isEmpty()){
        isBoard = false;
        continue;
    }
    if(isBoard) {
        for(int x = 0; x < size; x++){
            char c = line.charAt(x);
            grid[i][x] = c;
            if(c == 'O') {
                grid2[i][x * 2] = '[';
                grid2[i][x * 2 + 1] = ']';
            } else {
                grid2[i][x * 2] = c;
                grid2[i][x * 2 + 1] = c;
            }
            if(c == '@') {
                fy = i;
                fx = x;
                fy2 = i;
                fx2 = x * 2;
                grid2[i][x * 2 + 1] = '.';
            }
        }
    } else {
        for(int c = 0; c < line.length(); c++){
            int[] newLoc = move(line.charAt(c), grid, fx, fy);
            int[] newLoc2 = move(line.charAt(c), grid2, fx2, fy2);
            fy = newLoc[0];
            fx = newLoc[1];
            fy2 = newLoc2[0];
            fx2 = newLoc2[1];
        }
    }
}

int part1 = 0;
int part2 = 0;
for(int y = 0; y < size; y++){
    for(int x = 0; x < size; x++){
        if(grid[y][x] == 'O') part1 += y * 100 + x;
        if(grid2[y][x] == '[') part2 += y  * 100 + x;
    }
    for(int x = size; x < size * 2; x++){
        if(grid2[y][x] == '[') part2 += y  * 100 + x;
    }
}

Simulere robot:

 private static int[] move(char direction, char[][] grid, int x, int y){
    if (direction == '^') return walkVertical(grid, x, y, -1);
    else if (direction == 'v') return walkVertical(grid, x, y, 1);
    else if (direction == '<') return walkHorizontal(grid, x, y, -1);
    else if (direction == '>') return walkHorizontal(grid, x, y, 1);
    return new int[]{y, x};
}

private static int[] walkVertical(char[][] grid, int x, int y, int deltaRow) {
    int futureRow = y + deltaRow;
    char futureSpot = grid[futureRow][x];

    if (futureSpot == '#') return new int[]{y, x};

    if (futureSpot == '.') {
        grid[y][x] = '.';
        y = futureRow;
        grid[y][x] = '@';
        return new int[]{y, x};
    }

    if (canMoveVertical(grid, x, futureRow, deltaRow)) return new int[]{y, x};

    moveBoxVertical(grid, x, futureRow, deltaRow);
    grid[y][x] = '.';
    y = futureRow;
    grid[y][x] = '@';

    return new int[]{y, x};
}

public static boolean canMoveVertical(char[][] grid, int x, int y, int deltaRow) {
    if (grid[y][x] == ']') x -= 1;

    int futureRow = y + deltaRow;

    char futureSpotLeft = grid[futureRow][x];
    char futureSpotRight = grid[futureRow][x + 1];

    if (futureSpotLeft == '#' || futureSpotRight == '#') return true;

    if (canMoveVertical(grid, x, futureRow, deltaRow) && (futureSpotLeft == '[' || futureSpotLeft == ']')) return true;
    return futureSpotRight == '[' && canMoveVertical(grid, x + 1, futureRow, deltaRow);
}

public static void moveBoxVertical(char[][] grid, int x, int y, int deltaRow) {
    if (grid[y][x] == ']') x -= 1;

    int futureRow = y + deltaRow;

    char futureSpotLeft = grid[futureRow][x];
    char futureSpotRight = grid[futureRow][x + 1];

    if ((futureSpotLeft == '[' || futureSpotLeft == ']') && futureRow != y) moveBoxVertical(grid, x, futureRow, deltaRow);

    if (futureSpotRight == '[' && futureRow != y) moveBoxVertical(grid, x + 1, futureRow, deltaRow);

    grid[y][x] = '.';
    grid[y][x + 1] = '.';

    grid[futureRow][x] = '[';
    grid[futureRow][x + 1] = ']';
}

private static int[] walkHorizontal(char[][] grid, int x, int y, int deltaCol) {
    int futureCol = x;

    while (true) {
        futureCol += deltaCol;
        char futureSpot = grid[y][futureCol];
        if (futureSpot == '#') return new int[]{y, x};
        if (futureSpot == '.') break;

    }

    do {
        int previousCol = futureCol - deltaCol;
        grid[y][futureCol] = grid[y][previousCol];
        futureCol = previousCol;

    } while (futureCol != x);

    grid[y][x] = '.';
    x += deltaCol;
    return new int[]{y, x};
}