• # Jour 24

    Posté par . En réponse au journal Advent of code 2024. Évalué à 1.

    Pour la partie 1, il suffit de suivre les instructions et valider les TU.

    Pour la partie 2, je pense que je n'ai pas choisie la solution la plus rapide. Je mets environ 1min pour trouver la solution.

    Je fais une fonction recursive qui va descendre à une profondeur de 44.

    En gros, je vais valider l'addition de 2 entiers en commençant par les bits de poids faible jusqu'au bit de poids fort.
    Quand j'identifie une erreur j'applique une permutation de sortie.

    Pour valider, l'addition de 2 entiers, je ne considère pas tous les entiers 244. çà serait trop long.
    Je construits des additions particulières en binaires qui vont valider toutes les retenus à la profondeur ou je suis. A chaque addition , je valide la commutativité de mon addition.
    Par exemple , à la profondeur 3
    1
    1

    1
    11

    1
    111

    Mais je vais aussi valider le merge de nombre binaire sans retenu et je vérifie encore la commutativité.
    1
    0

    10
    101


    Bien paramétré cette fonction de validation a été déterminant car c'est elle qui garantit qu'au fur et à mesure de l'exploration des combinatoire possible , je n'engendre pas de régression dans les chiffres et çà me permet de déterminer rapidement une impasse dans le choix de la permutation

    L'autre point important, c'est quand on détecte une anomalie, je vais déterminer les bits concernés et en déduire les portes éligibles à la permutation.
    çà limite mon exploration.

     public static long wrongBit(long expected , long result) {
     return (expected ^ result);
     }
     public static long isOk(long current) {
     report.start("isOk");
     long wrong = 0;
     long mask = current;
     long x = 0;
     long r ;
     while(current > 0) {
     long expectedAddOne = 1l + current; 
     r = evaluateNetwork(1l, current);
     if(r < 0) {
     return -1;
     }
     wrong = wrong | wrongBit(expectedAddOne, r);
     r = evaluateNetwork( current, 1l);
     if(r < 0) {
     return -1;
     }
     wrong = wrong | wrongBit(expectedAddOne, r);
     r = evaluateNetwork( current, 0l);
     if(r < 0) {
     return -1;
     }
     wrong = wrong | wrongBit(current, r);
     r = evaluateNetwork( 0l, current);
     if(r < 0) {
     return -1;
     }
     wrong = wrong | wrongBit(current, r);
     long a = 1l << x;
     long b = mask - a;
     r = evaluateNetwork( a, b);
     if(r < 0) {
     return -1;
     }
     wrong = wrong | wrongBit(mask, r);
     r = evaluateNetwork( b, a);
     if(r < 0) {
     return -1;
     }
     wrong = wrong | wrongBit(mask, r);
     current = current >> 1l;
     x++;
     }
     report.end("isOk");
     return mask & wrong;
     }
     private static void recurseFixGates(Set<String> validated, int x) {
     if(x > maxDepth) {
     System.out.println(x + " " + validated.size() );
     maxDepth = x;
     }
     if(validated.size() % 2 == 1) {
     System.out.println("Whats");
     }
     if (x == 44) { 
     if(validate()) { 
     String resultsAsString = validated.stream().sorted().collect(Collectors.joining(","));
     if (!availablesResults.contains(resultsAsString)) {
     availablesResults.add(resultsAsString);
     System.out.println(resultsAsString);
     }
     System.exit(0);
     }
     return;
     }
     if(validated.size() > 8) {
     return;
     }
     long right = 1l << (x+1);
     // System.out.println(x + ":" + left.toString(2) + " + " + right.toString(2) + "
     // =>" + z.toString(2));
     long wrong = isOk(right);
     if(wrong < 0) {
     System.out.println("There is a loop : " +x);
     return;
     }
     if (wrong != 0) {
     // System.out.println("Need fix to get " + expect.toString(2));
     Set<Gate> changes = computeRelated(wrong);
     for (Gate a : changes) {
     if (validated.contains(a.wireOutput)) {
     continue;
     }
     for (Gate b : gates) {
     if (a.equals(b) || validated.contains(b.wireOutput) || lessZ(b.wireOutput, x)) {
     continue;
     }
     String tmp = b.wireOutput;
     b.wireOutput = a.wireOutput;
     a.wireOutput = tmp;
     try {
     if (isOk(right) == 0l || (x <= 2 && isOk(right) == -1)) {
     validated.add(a.wireOutput);
     validated.add(b.wireOutput);
     recurseFixGates(validated, x + 1);
     validated.remove(a.wireOutput);
     validated.remove(b.wireOutput);
     if(validated.size() % 2 == 1) {
     System.out.println("Whats");
     }
     }
     } finally {
     tmp = b.wireOutput;
     b.wireOutput = a.wireOutput;
     a.wireOutput = tmp;
     }
     }
     }
     } else {
     recurseFixGates(validated, x + 1);
     }
     }
     private static boolean validate() {
     for(long x=0;x < 43;x++) {
     long a = (1l << x)-1;
     long b = 13; 
     if((a+b) != evaluateNetwork(a, b)) {
     return false;
     }
     }
     return true;
     }
     public static boolean lessZ(String name, int x) {
     if(! name.startsWith("z")) {
     return false;
     }
     return Integer.valueOf(name.substring(1)) <= x;
     }
     public static Gate findByOutput(String name) {
     return gates.stream().filter(g->g.wireOutput.equals(name)).findFirst().orElse(null);
     }
     private static Set<Gate> computeRelated(long wrong) {
     if(wrong == -1) {
     return new HashSet<Aoc2024s24p2.Gate>(gates);
     }
     Set<Gate> related = new HashSet<Aoc2024s24p2.Gate>();
     for(int x=0;x < 45;x++) {
     long mask = 1l << x;
     if((wrong & mask)> 0) {
     Gate gate = findByOutput(zindex(x));
     recurseRelated(related, gate); 
     }
     }
     return related;
     }
     private static void recurseRelated(Set<Gate> related, Gate gate) {
     if(related.contains(gate) || gate == null) {
     return;
     }
     related.add(gate); 
     recurseRelated(related, findByOutput(gate.wireLeft.name));
     recurseRelated(related, findByOutput(gate.wireRight.name));
     }
     private static long evaluateNetwork(Long left, Long right) {
     report.start("evaluateNetwork");
     if(left != null) {
     initiate("x", left);
     }
     if(right != null) {
     initiate("y", right);
     }
     Map<Gate, AtomicInteger> updated = new HashMap<Aoc2024s24p2.Gate, AtomicInteger>();
     /*for(Wire wire : wireByName.values()) {
     if(! (wire.name.startsWith("x") || wire.name.startsWith("y"))) {
     wire.state = null;
     }
     }*/
     boolean haveUpdate = false;
     do {
     haveUpdate = false;
     for (Gate gate : gates) {
     if (gate.update()) {
     int count = updated.computeIfAbsent(gate, k->new AtomicInteger()).incrementAndGet(); 
     if (count > 2) {
     report.end("evaluateNetwork");
     return -1;
     }
     haveUpdate = haveUpdate || true; 
     }
     }
     } while (haveUpdate);
     int x = 0;
     long z = 0;
     while(wireByName.get(zindex(x)) != null) {
     //System.out.println(x + " => " + wireByName.get(zindex(x)).state );
     Wire wire = wireByName.get(zindex(x));
     if(wire.state != null && wire.state) {
     long v = 1l << x;
     //System.out.println(v);
     z = z + v;
     }
     x++;
     }
     report.end("evaluateNetwork");
     return z;
     }
     private static void initiate(String s, long left) {
     for (long x = 0; x < 45; x++) {
     long mask = 1l << x;
     if ((mask & left) > 0) {
     wireByName.get(index(s, x)).state = true;
     } else {
     wireByName.get(index(s, x)).state = false;
     }
     }
     }
     public static String index(String s, long x) {
     return (x < 10 ? s + "0" : s) + x;
     }
     public static String zindex(long x) {
     return (x < 10 ? "z0" : "z") + x;
     }