From e326f572304876af6223eae53c43632c9217aee1 Mon Sep 17 00:00:00 2001 From: Flashky Date: Tue, 17 Dec 2024 15:31:12 +0100 Subject: [PATCH] feat: day 17 WIP --- .../flashk/day17/ChronospatialComputer.java | 180 ++++++++++++++++-- .../flashk/day17/ProgramState.java | 9 + .../adventofcode/flashk/day17/Day17Test.java | 22 ++- src/test/resources/inputs | 2 +- 4 files changed, 191 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/adventofcode/flashk/day17/ProgramState.java diff --git a/src/main/java/com/adventofcode/flashk/day17/ChronospatialComputer.java b/src/main/java/com/adventofcode/flashk/day17/ChronospatialComputer.java index 9865d39..d5109ee 100644 --- a/src/main/java/com/adventofcode/flashk/day17/ChronospatialComputer.java +++ b/src/main/java/com/adventofcode/flashk/day17/ChronospatialComputer.java @@ -1,7 +1,9 @@ package com.adventofcode.flashk.day17; import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.StringJoiner; @@ -13,21 +15,24 @@ public class ChronospatialComputer { private static final Pattern NUMBER_PATTERN = Pattern.compile("(\\d*)*"); - private int a; - private int b; - private int c; + private long a; + private long b; + private long c; - private int[] program; + private final int[] program; private int instructionPointer; private StringJoiner outJoiner; + private final String expectedProgram; + + private List programStates = new ArrayList<>(); public ChronospatialComputer(List inputs) { a = Integer.parseInt(inputs.get(0).substring(12)); b = Integer.parseInt(inputs.get(1).substring(12)); c = Integer.parseInt(inputs.get(2).substring(12)); - String programValues = inputs.get(4).replace("Program: ", ""); - program = Arrays.stream(programValues.split(",")).mapToInt(Integer::valueOf).toArray(); + expectedProgram = inputs.get(4).replace("Program: ", ""); + program = Arrays.stream(expectedProgram.split(",")).mapToInt(Integer::valueOf).toArray(); } @@ -55,6 +60,149 @@ public String solveA() { return outJoiner.toString(); } + public long solveB() { + + // TODO Posible problema de memoization + // Brainstorming + // programStates.stream().sorted().toList() + // + // En el sample: + // Al generar un conjunto de estados, se observa algo interesante + // - Cada 8 valores diferenes de a, se repite el mismo out. + // - Por lo tanto, podemos reducir el espacio de búsqueda en el sample para i+8. + + // https://www.reddit.com/r/adventofcode/s/6H6hRO2M9r + + long originalB = this.b; + long originalC = this.c; + // + // Idea: 2^48 + // La primera solución de programa que tiene exactamente 16 elementos empieza en + // el índice 2^48: + + // 2^3 = 8 -> 1 elemento + // 2^6 = 64 -> 3 elementos + // 2^9 = 512 -> 4 elementos + // 2^12 = 1024 -> 5 elementos + // 16 elementos? + // 2^48 = 281474976710656 + // 1 elementos -> 0+3=3 + // 3 elementos -> 3+3=6 + // 4 elementos -> 6+3=9 + // 5 elementos -> 9+3=12 + // + // Fórmula = 3+(3*(n-1)) + // Por lo tanto: + // 16 elementos -> 3+(3*(16-1)) = 3+(3*15) = 3+45 = 48 + // Potencia: 2^48 + + //long initialValue = (long) Math.pow(2,48); + //long maxValue = (long) Math.pow(2,49); + // Cúantas iteraciones hay entre 2^48 y 2^49? + // Es algún número entre 2^48 y 2^49 + + // Dígito 48: 6 + //List values = List.of(0L,1L,2L,3L,4L,5L,6L,7L); + + // Dígito 47: 0 + //List values = List.of(6L,16L, 26L, 36L, 46L, 56L, 66L, 76L); + + // Dígito 46: 0 + //List values = List.of(6L,106L, 206L, 306L, 406L, 506L, 606L, 706L); + + String[] binaryDigits = { "000", "001", "010", "011", "100", "101", "110", "111" }; + + //debug(46, 846, originalB, originalC); + + int index = 0; + List numberValues = new ArrayList<>(); + long realNumber = 0; + long previousNumber = 0; + for(int i = 0; i < 16; i++) { + programStates.clear(); + //realNumber += numberDigit * Math.pow(10, index); + for(int digit = 0; digit < 9; digit++) { + // Convertir realNumber a binario + + realNumber = previousNumber + (digit * (long) Math.pow(10, index)); + + //String binarySection = binaryDigits[digit]; + //String binaryNumber = StringUtils.rightPad(binarySection,3*(i+1),"0"); + //Long number = Long.valueOf(binaryNumber,2); + + debug(digit, realNumber, originalB, originalC); + } + index++; + + previousNumber = programStates.stream() + .filter(ps -> ps.a() == 0) + .filter(ps -> ps.b() == 0) + .filter(ps -> ps.c() == 0) + .mapToLong(ProgramState::number).findFirst().getAsLong(); + + + } + /* + List values = List.of(6L,1006L, 2006L, 3006L, 4006L, 5006L, 6006L, 7006L); + for(Long value : values) { + debug(value, originalB, originalC); + }*/ + /* + for(long i = 0; i < 8; i++) { + try { + if(expectedProgram.equals(debug(i, originalB, originalC))) { + System.out.println("Found: "+i); + return i; + } + } catch(IllegalArgumentException e) { + System.out.println("Invalid operator: "+i); + } + }*/ + System.out.println("Not found"); + return -1; + } + + public String debug(long number, long a, long b, long c) { + + //System.out.println("Testing a:"+a); + this.a = a; + this.b = b; + this.c = c; + + instructionPointer = 0; + outJoiner = new StringJoiner(","); + + + int opcode; + int operator; + + while(instructionPointer < program.length) { + opcode = program[instructionPointer]; + operator = program[instructionPointer+1]; + + execute(opcode, operator); + + if(opcode != 3) { + instructionPointer += 2; + } + + /* + if(opcode == 5) { + //System.out.println("Current: " + outJoiner.toString()); + //System.out.println("Expected: "+expectedProgram); + if(!expectedProgram.startsWith(outJoiner.toString())) { + programStates.add(new ProgramState(this.a, this.b, this.c, outJoiner.toString())); + return ""; + } + }*/ + + + } + programStates.add(new ProgramState(number, a, this.b, this.c, outJoiner.toString())); + //System.out.println("Completed: " + outJoiner.toString()); + return outJoiner.toString(); + } + private void execute(int opcode, int operator) { switch(opcode) { @@ -70,7 +218,7 @@ private void execute(int opcode, int operator) { } } - private int getComboOperand(int operator) { + private long getComboOperand(int operator) { switch(operator) { case 0,1,2,3: return operator; @@ -86,8 +234,8 @@ private int getComboOperand(int operator) { } private void adv(int operand) { - int comboOperand = getComboOperand(operand); - int power = (int) Math.pow(2, comboOperand); + long comboOperand = getComboOperand(operand); + long power = (long) Math.pow(2, comboOperand); a = a / power; } @@ -96,7 +244,7 @@ private void bxl(int operand) { } private void bst(int operand) { - int comboOperand = getComboOperand(operand); + long comboOperand = getComboOperand(operand); b = comboOperand % 8; } @@ -108,28 +256,28 @@ private void jnz(int operator) { } } - private void bxc(int operand) { + private void bxc(long operand) { // https://en.wikipedia.org/wiki/Bitwise_operation#XOR b = xor(b, c); } private void out(int operand) { - int comboOperand = getComboOperand(operand); - int mod = comboOperand % 8; + long comboOperand = getComboOperand(operand); + int mod = (int) comboOperand % 8; outJoiner.add(String.valueOf(mod)); } private void bdv(int operand) { - int comboOperand = getComboOperand(operand); + long comboOperand = getComboOperand(operand); b = a / (int) Math.pow(2, comboOperand); } private void cdv(int operand) { - int comboOperand = getComboOperand(operand); + long comboOperand = getComboOperand(operand); c = a / (int) Math.pow(2, comboOperand); } - private int xor(int a, int b) { + private long xor(long a, long b) { return a ^ b; } diff --git a/src/main/java/com/adventofcode/flashk/day17/ProgramState.java b/src/main/java/com/adventofcode/flashk/day17/ProgramState.java new file mode 100644 index 0000000..3c8c0cc --- /dev/null +++ b/src/main/java/com/adventofcode/flashk/day17/ProgramState.java @@ -0,0 +1,9 @@ +package com.adventofcode.flashk.day17; + +public record ProgramState(long number, long a, long b, long c, String out) implements Comparable { + + @Override + public int compareTo(ProgramState o) { + return Long.compare(a, o.a); + } +} diff --git a/src/test/java/com/adventofcode/flashk/day17/Day17Test.java b/src/test/java/com/adventofcode/flashk/day17/Day17Test.java index c08847d..37d83e5 100644 --- a/src/test/java/com/adventofcode/flashk/day17/Day17Test.java +++ b/src/test/java/com/adventofcode/flashk/day17/Day17Test.java @@ -2,6 +2,7 @@ import java.util.List; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; import org.junit.jupiter.api.Order; @@ -67,8 +68,6 @@ void part1Debug3Test() { ChronospatialComputer chronospatialComputer = new ChronospatialComputer(inputs); - // TODO único test que se queda pillado. - // Register A: 2024 // Register B: 0 // Register C: 0 @@ -152,9 +151,12 @@ public void testSolvePart1Input() { public void testSolvePart2Sample() { // Read input file - List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE); + List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE_SAMPLE_PART_2); + + ChronospatialComputer chronospatialComputer = new ChronospatialComputer(inputs); + + assertEquals(117440L ,chronospatialComputer.solveB()); - assertEquals(0L,0L); } @Test @@ -162,12 +164,22 @@ public void testSolvePart2Sample() { @Tag(TestTag.PART_2) @Tag(TestTag.INPUT) @DisplayName(TestDisplayName.PART_2_INPUT) + @Disabled public void testSolvePart2Input() { // Read input file List inputs = Input.readStringLines(INPUT_FOLDER, TestFilename.INPUT_FILE); - System.out.println("Solution: "); + ChronospatialComputer chronospatialComputer = new ChronospatialComputer(inputs); + + // Algunas consideraciones: + // La primera operación con los datos reales es 2,4 + // Esto es, opcode 2, operator 4: + // - opcode 2 implica BST, esto es b = comboOperand % 8; + // - operator 4 implica que el valor de comboOperand va a ser el registro A + // Por lo tanto, valga lo que valga A, b adquirirá el valor de A % 8 + + System.out.println("Solution: "+chronospatialComputer.solveB()); assertEquals(0L,0L); } diff --git a/src/test/resources/inputs b/src/test/resources/inputs index 9992c68..0409a49 160000 --- a/src/test/resources/inputs +++ b/src/test/resources/inputs @@ -1 +1 @@ -Subproject commit 9992c6886c6ceeb16a74b9e0a54c73c655b73e6e +Subproject commit 0409a49b0608255f25aa12354e97432a1fa0e4d0