17. des. 2024 - 3 minutter å lese

Advent of Code 2024 - Luke 17

Advent of Code 2024 - Luke 17

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

Luke 17 tar for seg en program der det blir gitt en input, med instruksjoner, som blir til en output. Vi skal finne outputen av programmet. Outputen til programmet er bestemt av hvilke instruksjoner som gis. For hver instruksjon øker pointer med 2. Først har vi combo som returnerer et tall basert på en “operand”:

  • operand 0 til 3 representerer det faktiske tallet
  • operand 4 representerer A
  • operand 5 representerer B
  • operand 6 representerer C
  • operand 7 er reservert og ikke i bruk

Instruksjonene er som følger:

  1. A = A delt på 2^combo(operand)
  2. B = B^operand
  3. B = combo(operand) % 8
  4. A != 0 -> Pointer += 1, ikke 2
  5. B = B^C
  6. Output += combo(operand) % 8
  7. B = B delt på 2^combo(operand)
  8. C = C delt på 2^combo(operand)

Metodene for å løse oppgaven ble slik:

public static List<Long> run(long[] registers, List<Integer> program){
    List<Long> output = new ArrayList<>();
    int pointer = 0;
    while(true) {
        if(pointer + 1 > program.size()) return output;
        long opcode = program.get(pointer);
        int operand = program.get(pointer + 1);
        if (opcode == 0 || opcode == 6 || opcode == 7) {
            if (opcode != 0) registers[(int) (opcode - 5)] = dpc(operand, registers);
            else registers[(int) opcode] = dpc(operand, registers);
        }
        else if (opcode == 2) registers[1] = combo(operand, registers) % 8;
        else if (opcode == 1) registers[1] = registers[1] ^ operand;
        else if (opcode == 4) registers[1] = registers[1] ^ registers[2];
        else if (opcode == 5) output.add(combo(operand, registers) % 8);
        if (opcode == 3 && registers[0] != 0) pointer = operand;
        else pointer += 2;

    }
}

public static long dpc(int operand, long[] registers){
    return (long) Math.floor(registers[0] / Math.pow(2, combo(operand, registers)));
}

public static long combo(int operand, long[] registers){
    if(operand < 4) return operand;
    return registers[operand - 4];
}

Oppgave 2

For oppgave 2 ønsker vi å finne når programmets output matcher instruksjonene. Altså om instruksjonene er 0, 2, 4, 4, 5, 6 vil vi at outputten skal bli det samme. For å finne dette måtte jeg google litt og fant ut at en kan ta for seg et og et siffer for å se hva som blir produsert. Vi vet fra før av at output sin A sitt siffer sin lengde == instruksjoner sin lengde. Dermed kan vi ta for oss et og et siffer og se om det matcher. Metoden for å løse oppgaven ble slik:

public static long find(long[] registers, List<Integer> program){
    List<Long> options = new ArrayList<>();
    options.add(0L);
    List<Long> compare = new ArrayList<>();
    for(int i = 0; i < 16; i++){
        compare.add((long) program.get(16 - i - 1));
        List<Long> real = new ArrayList<>();
        for(int j = compare.size() - 1; j >= 0; j--){
            real.add(compare.get(j));
        }
        List<Long> newOptions = new ArrayList<>();
        for(Long option: options){
            for(int j = 0; j < 8; j++){
                registers[0] = (option << 3) + j;
                List<Long> output = run(registers, program);
                if(output.equals(real)){
                    newOptions.add((option << 3) + j);
                }
            }
        }
        options = newOptions;
    }
    return options.getFirst();
}