6. des. 2024 - 4 minutter å lese

Advent of Code 2024 - Luke 6

Advent of Code 2024 - Luke 6

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

Oppgave 1 for luke 6 går ut på å forutse vakten sin rute inntil vakten går ut av det planlagte feltet. Kodemessig vil dette da si når vakten sin neste x eller y posisjon vil være mindre enn 0 eller større enn lengden av feltet. Vakten vil alltid gå i en rett linje inntil den treffer en vegg, indikert av #. Ved krasj snur vakten 90 grader og fortsetter rett frem igjen. For å finne når vakten går ut av feltet kan vi simulerere vaktens gange. For å gjøre dette setter vi først opp feltet vakten går innenfor. Ved denne metoden:

int x = 0;
int y = 0;

for (int i = 0; i < lines.size(); i++) {
    String line = lines.get(i);
    if (line.contains("^")) {
        y = i;
        for (int j = 0; j < line.length(); j++) {
            if (line.charAt(j) == '^') {
                x = j;
                break;
            }
        }
        break;
    }
}

HashSet<String> visited = walk(lines, x, y);

Metode for å simulere vaktens gange:

private static HashSet<String> walk(List<String> lines, int x, int y) {
    HashSet<String> visited = new HashSet<>();
    visited.add(y + "," + x);
    int[][] directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    int i = 0;

    while (x > 0 && y > 0 && y < lines.size() - 1 && x < lines.getFirst().length() - 1) {
        if (lines.get(y + directions[i][0]).charAt(x + directions[i][1]) == '#') i++;
        else {
            y += directions[i][0];
            x += directions[i][1];
        }
        visited.add(y + "," + x);
        if(i == 4) i = 0;
    }

    return visited;
}

I main metoden printer vi størrelsen på HashSettet. Vi bruker HashSet siden vi kun ønsker de unike feltene.

Oppgave 2

For oppgave 2 skal vi finne når vakten vil ende opp med å gå i loop dersom vi plasserer flere vegger/bygninger. Vi ønsker å finne ut hvor mange potensielle loops det finnes i feltet for vakten. For dette oppretter vi en ekstra for loop i main for å kun plassere vegger/bygninger der vakten ville gått, ettersom alle andre steder vil være unødvendig.

int possibleLoops = 0;

for (int i = 0; i < lines.size(); i++) {
    for (int j = 0; j < lines.getFirst().length(); j++) {
        if (lines.get(i).charAt(j) != '^'
                && visited.contains(i + "," + j)) {
            if (walkObstacle(lines, x, y, j, i) == 0) possibleLoops++;
        }
    }
}

Vi kjører så en oppdatert walk for å sjekke om det resulterer i en loop eller om vakten går ut av feltet.

private static int walkObstacle(List<String> lines, int x, int y, int obstacleX, int obstacleY) {
    String obstacleLine = lines.get(obstacleY);
    lines.set(obstacleY, obstacleLine.substring(0, obstacleX) + "#" + obstacleLine.substring(obstacleX + 1));

    HashSet<String> obstacles = new HashSet<>();
    int[][] directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    int i = 0;

    while (x > 0 && y > 0 && y < lines.size() - 1 && x < lines.getFirst().length() - 1) {
        if (lines.get(y + directions[i][0]).charAt(x + directions[i][1]) == '#'){
            if(!obstacles.add(x + "," + y + " - " + directions[i][0] + directions[i][1])){
                lines.set(obstacleY, obstacleLine);
                return 0;
            }
            i++;
        }
        else {
            y += directions[i][0];
            x += directions[i][1];
        }
        if(i == 4) i = 0;
    }
    lines.set(obstacleY, obstacleLine);
    return (obstacles.size());
}

I main metoden printer vi så antallet potensielle loops.