syj a écrit 612 commentaires

  • [^] # Re: Mailcow ?

    Posté par  . En réponse au message Serveur smtp/map. Évalué à 1.

    Merci pour l'info.

    Au final, je pense que je vais partir avec une image docker de postfix maison ou de sendmail maison.

  • [^] # Re: Mailcow ?

    Posté par  . En réponse au message Serveur smtp/map. Évalué à 1.

    Merci pour le lien.
    J'aurai préféré un témoignage genre çà marche chez moi :)

    çà a l'air de faire trop de truc pour moi. Mon besoin est beaucoup plus simple.

  • # Perso, j'y connais rien Ruby mais ...

    Posté par  . En réponse au lien OneTimeSecret. Évalué à 0.

    Je trouve que l'idée est bonne.

    Par contre, ce qui me gène, c'est que je n'y connais rien Ruby & que pour utiliser ce genre de service.
    il faut que je sois sur que cela soit Safe. il faut donc que je l'audit.

    Il faudrait le même service dans un code qui tient en quelques fichiers facilement auditable sans dépendance tiers.
    - 1 fichier sources serveur
    - 1 form HTML
    - 1 JS
    - 1 form CSS
    - 1 Dockerfile

  • [^] # Re: J'ai galéré :)

    Posté par  . En réponse au message Avent du code jour 25. Évalué à 2.

    Yes bien joué Yth

    Bien joué tt le monde.

    Je trouve qu il etait vraiment plus simple que l'an dernier.

    Le prochain challenge sympa dans ce genre, c est ctf de l Ansi en mai.

  • # J'ai galéré :)

    Posté par  . En réponse au message Avent du code jour 25. Évalué à 2. Dernière modification le 25 décembre 2022 à 11:52.

    Environ 2h40 pour faire ce fichu dernier problème. Je genre d'éxercice, ce n'est vraiment pas mon truc.

    J'y suis allé à la méthode ajustement test unitaire.

    Le parsing est assez simple à réaliser. En gros, c'est comme une conversion d'une base 5 avec des -1 , et -2 :)

    Le problème, c'est l'opération inverse. Mon algo est tellement tordu que je n'arrive pas à l'expliquer :)
    Je n'ai même pas l'excuse de l'alcool car je suis sous antibiotique. Résultat, c'est mon premier noël sans une goutte d'alcool.

    Joyeux noël à tous.

        static String toSnafu(long v) {
            String s  =Long.toString(v, 5);
            if(s.indexOf("3") < 0 && s.indexOf("4") < 0) {
                return s;
            }
            long[] seek = prepareSeek(v);
            long seekValue = seek[0] * ((long)Math.pow(5, seek.length-1));
    
            for(int x=1;x < seek.length;x++) {
                long lowestGreater = 2;
                for(int e=VALUES.length-1;e >= 0;e--) {
    
    
                    long add = VALUES[e] * ((long)Math.pow(5, seek.length-1-x));
    
                    long s1 = seekValue + add + maxWithOnly2(seek.length-1-x) ;
                    long s2 = v;
    
    
                    if(s1 < s2) {                   
                        break;
                    }
    
                    lowestGreater = VALUES[e];
    
                }
    
    
    
                seek[x] = lowestGreater;
                //System.out.println(Arrays.stream(seek).mapToObj(i->Long.toString(i)).collect(Collectors.joining(",")));
                long add = lowestGreater * ((long)Math.pow(5, seek.length-1-x));
                seekValue += add;
            }
    
    
    
    
            return seekToString(seek);
        }
    
    
        private static String seekToString(long[] seek) {
            StringBuilder sb = new StringBuilder();
            for(int x=0;x < seek.length;x++) {
                if(seek[x] == 0 && x == 0) {
                    continue;
                }
    
                if(seek[x] == -2) {
                    sb.append('=');
                } else if(seek[x] == -1) {
                    sb.append('-');
                } else {
                    sb.append(Long.valueOf(seek[x]));
                }
    
            }
    
            return sb.toString();
        }
    
        static long[] prepareSeek(long v) {
            if(v == 0) {
                return new long[] {0};
            }
            long power = 0;
            boolean greater = false;
            long greaterNb = 0;
            while(! greater) {
                long max = maxWithOnly2(power);
    
                for(long x=1; x <= 2;x++) {
                    long l = (x* ((long)Math.pow(5, power))) +max ;
                    if(l >= v) {
                        greater =true;
                        greaterNb = x;
                        break;
                    }
                }
                power += 1;
            }
    
            long[] mask = new long[(int)power];
            mask[0]=greaterNb;
            return mask;
        }
    
    
        private static long maxWithOnly2(long power) {
            long max = 0;
            for(int j=0; j < power;j++) {
                max += 2* Math.pow(5, j);
            }
            return max;
        }
  • # Parcours en largeur.

    Posté par  . En réponse au message Avent du Code, jour 24. Évalué à 5.

    On est dans le cas typique d'un parcours en largeur d'un arbre des possibles.

    A chaque round, on regarde l'ensemble des actions possibles et on calcule les états suivants en fonction de ses possibilités
    il y a des branches qui s'élimine d'elle-même car il n'y a plus d'action possible pour le joueur.
    il y aussi des branches qui se rejoingne car il y a plusieurs chemin pour arriver à un même état.
    J'utilise le hashCode/equals de mon State pour les dédupliquer sinon çà explose grave.

    Au total,j'ai mis 1h50 pour debug les différentes conneries que j'ai fait à mon réveille.

    Je mets 40s pour calculer la solution de la 2ème étoiles

    Maintenant, je vais aller braver les magasins car j'ai plein de cadeau à acheter :-).
    Joyeux Noël à tous.

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Objects;
    import java.util.Scanner;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    public class A2022D24 {
        public enum Move {
            EAST(1, 0, '>'),
    
            SOUTH(0, 1, 'v'), WEST(-1, 0, '<'), WAIT(0, 0, 'W'), NORTH(0, -1, '^');
    
            int dx;
            int dy;
            char d;
    
            private Move(int dx, int dy, char d) {
                this.dx = dx;
                this.dy = dy;
                this.d = d;
            };
    
        }
    
        public static class Point {
            int x;
            int y;
    
            public Point() {
            }
    
            public Point(int x, int y) {
                this.x = x;
                this.y = y;
            }
    
            public String toString() {
                return x + "," + y;
            }
    
            public void copyInto(Point p) {
                p.x = this.x;
                p.y = this.y;
            }
    
            @Override
            public int hashCode() {
                return Objects.hash(x, y);
            }
    
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                Point other = (Point) obj;
                return x == other.x && y == other.y;
            }
    
    
        }
    
        public static class Wind extends Point {
            Move m;
    
            public Wind(int x, int y) {
                this.x = x;
                this.y = y;
            }
    
            public void copyInto(Wind wind) {
                super.copyInto(wind);
                wind.m = m;
    
            }
    
        }
    
        public static class State {
            List<Wind> winds = new ArrayList<>();
            Point pos = new Point(1, 0);
            int round = 0;
    
            public void copyInto(State state) {
                state.winds.clear();
                for (Wind w : this.winds) {
                    Wind newWind = new Wind(0, 0);
                    w.copyInto(newWind);
                    state.winds.add(newWind);
                }
    
                this.pos.copyInto(state.pos);
                state.round = this.round;
    
            }
    
            public char count(int x, int y) {
                char c = '.';
                int count = 0;
                for (Wind wind : this.winds) {
                    if (wind.x == x && wind.y == y) {
                        count++;
                        c = wind.m.d;
                    }
                }
                if(count > 1) {
                    c = ("" + count).charAt(0);
                }
                return c;
    
            }
    
            public boolean isFree(int x, int y) {
                if ((x == WIDTH - 2) && (y == HEIGHT - 1)) {
                    return true;
                }
    
                if ((x == 1) && (y == 0)) {
                    return true;
                }
    
                if (y <= 0 || x <= 0 || x >= (WIDTH - 1) || y >= (HEIGHT - 1)) {
                    return false;
                }
    
                for (Wind wind : this.winds) {
                    if (wind.x == x && wind.y == y) {
                        return false;
                    }
                }
                return true;
    
            }
    
            public List<A2022D24.Move> getAvailables() {
                return Arrays.stream(Move.values()).filter(m -> isFree(pos.x + m.dx, pos.y + m.dy))
                        .collect(Collectors.toList());
            }
    
            public void moveWind() {
                for (Wind wind : winds) {
                    wind.x = wind.x + wind.m.dx;
                    wind.y = wind.y + wind.m.dy;
    
                    if (wind.x == 0) {
                        wind.x = WIDTH - 2;
                    } else if (wind.x == WIDTH - 1) {
                        wind.x = 1;
                    }
    
                    if (wind.y == 0) {
                        wind.y = HEIGHT - 2;
                    } else if (wind.y == HEIGHT - 1) {
                        wind.y = 1;
                    }
                }
            }
    
            public void print() {
                for (int y = 0; y < HEIGHT; y++) {
                    for (int x = 0; x < WIDTH; x++) {
    
                        if (x == pos.x && y == pos.y) {
                            System.out.print("E");
                        } else if (isFree(x, y)) {
                            System.out.print(".");
                        } else if(x == 0 || x == (WIDTH-1) || y == 0 || y == HEIGHT-1) {
                            System.out.print("#");
                        } else {
                            System.out.print(count(x, y));
                        }
    
                    }
                    System.out.println();
                }
            }
    
            @Override
            public int hashCode() {
                return Objects.hash(pos, round);
            }
    
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                State other = (State) obj;
                return Objects.equals(pos, other.pos) && round == other.round;
            }
        }
    
        public static void main(String[] args) {
            step1();
        }
    
        public static int WIDTH = 0;
        public static int HEIGHT = 0;
    
        private static void step1() {
            List<Wind> winds = new ArrayList<>();
    
            try (Scanner in = new Scanner(A2022D24.class.getResourceAsStream("/res/i24.txt"))) {
                int y = 0;
                while (in.hasNext()) {
                    String row = in.nextLine();
    
                    for (int x = 0; x < row.length(); x++) {
                        final char d = row.charAt(x);
    
                        Move blizzard = Arrays.stream(Move.values()).filter(c -> {
                            return c.d == d;
                        }).findAny().orElse(null);
    
                        if(blizzard != null) {
                            Wind wind = new Wind(x, y);
                            wind.m = blizzard;
                            winds.add(wind);
                        }
    
                    }
                    WIDTH = row.length();
                    y++;
                }
    
                HEIGHT = y;
    
    
    
                State state = new State();
                state.pos = new Point(1, 0);
                state.winds = winds;
    
    
                int round = 0;
                int targetX = WIDTH-2;
                int targetY = HEIGHT-1;
                state = foundSolution(state, targetX, targetY);
    
                state = foundSolution(state, 1, 0);
                state = foundSolution(state, targetX, targetY);
                System.out.println(state.round);
            }
        }
    
        private static State foundSolution(State start, int targetX, int targetY) {
            Set<State> previous = new HashSet<>();
    
            previous.add(start);
            Set<State> next = new HashSet<>(); 
    
            Set<State> tmp;
            State state;
            while(true) {
                System.out.println("States stack:" + previous.size() + " round:" + previous.iterator().next().round);
                next.clear();
                for(State s :previous) {
                    if(s.pos.x == targetX && s.pos.y == targetY)  {
                        return s;
    
                    }
    
    
                    explore(next, s);
                }
    
                tmp = previous;
                previous = next;
                next = tmp;
            }
        }
    
        private static void explore(Set<State> next,  A2022D24.State state) {
    
            //state.print();
            state.moveWind();
            List<Move> moves = state.getAvailables();
            if(moves.size() == 0) {
                //System.out.println("empty");
            }
    
            for (Move move : moves) {
                State newState = new State();
                state.copyInto(newState);
                newState.pos.x += move.dx;
                newState.pos.y += move.dy;
                newState.round++;
    
                if (!newState.isFree(newState.pos.x, newState.pos.y)) {
                    throw new RuntimeException(); 
                }
    
                next.add(newState);
            }
    
        }
    }
  • # Dans l'ensemble, c'est plus simple que l'an dernier

    Posté par  . En réponse au message Avent du Code, jour 23. Évalué à 2.

    Dans l'ensemble, ils sont tous beaucoup plus simple que l'an dernier.

    Environ 1h40 après 12h de voiture + ma crève qui ne me lâche pas, on va dire que çà aurait pu être pire.

    Dans l'ensemble , il n'y a rien de compliqué aujourd'hui. Il faut juste conserver à l'esprit toutes les petites règles qui ne sont pas flag en gras dans la description.

    Résultat, j'ai perdu 30min à comprendre que quand il n'y a pas d'Elf autour. Il ne bouge pas.

    La deuxième partie, elle ne rajoute rien de dur, je m'attendais à une règle genre distance, ou un truc qui faisait exploser la volumétrie.

    Mais non rien, j'ai juste lancé mon programme pas du tout optimisé en me disant il va falloir que je trouve une opti.
    Je n'ai pas eu le temps de finir d'écrire la première opti que j'avais déjà la solution.

    1min20 pour 1014 round

  • # Il était vraiment sympa celui-ci :-)

    Posté par  . En réponse au message Avent du Code, jour 22. Évalué à 1.

    Environ 4h-4h30 effectif dessus.
    La première partie est fastidieuse, mais çà se code bien (~2h)

    La deuxième partie est encore plus fastidieuse.
    J'ai opté pour une classe "Arrete" agrégeant 2 segments caractérisés par une direction.

    Si on est dans un de ces 2 segments en matchant la direction de ce dernier, j'applique la transformation de changement d’arête.
    J'ai donc pris le temps d'identifier manuellement les arêtes du jeu de test pour valider mon algo. Je me suis aidé d'un petit découpage papier
    pour faciliter l'opération.

    Puis, j'ai fait pareil pour mon jeu de données. C'est le plus long.

    Par exemple pour le Jeu de test, elle donne ceci.
    9,9->9,12L 8,8->5,8D
    5,5->8,5U 9,1->9,4L
    13,9->16,9U 12,8->12,5R
    1,5->4,5U 12,1->9,1U
    4,8->1,8D 9,12->12,12D
    13,12->16,12D 1,8->1,5L
    12,4->12,1R 16,9->16,12R

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Scanner;
    
    
    
    public class A2022D22V2 {
    
    
        public static List<String> memory = new ArrayList<>();
        public static class Point  {
            int x;
            int y;
    
            public String toString() {
                return x + "," + y;
            }
        }
    
        public static class Segment {
            Point start;
            Point end;
            Direction direction;
    
            Segment(String part) {
                String[] points=  part.split("->");
                start = parsePoint(points[0]);
                end = parsePoint(points[1].substring(0, points[1].length()-1));
    
                char dir = points[1].charAt(points[1].length()-1);
                direction = Arrays.stream(Direction.values()).filter(a->a.name().charAt(0) == dir).findAny().orElse(null);
            }
    
            public Point parsePoint(String point) {
    
                String[] coords = point.split(",");
                Point p = new Point();
                p.x = Integer.valueOf(coords[0]);           
                p.x -= 1 ;
    
                p.y = Integer.valueOf(coords[1]);
                p.y -= 1;
    
                return p;
            }
    
            public String toString() {
                return start + " -> " + end + " " + direction;
            }
    
            public boolean include(int s, int v, int e) {
                if(s > e) {
                    int t = s;
                    s = e;
                    e = t;
                }
                return s <= v && v <= e;
            }
    
            public boolean include(A2022D22V2.Point p) {
                return include(start.x, p.x, end.x)
                        && include(start.y, p.y , end.y); 
            }
        }
    
        public static class Arrete {
            Segment a;      
            Segment b;
    
            public Arrete(String row) {
                String[] part = row.split(" ");
                a = new Segment(part[0]);
                b = new Segment(part[1]);           
            }       
    
            public String toString() {
                return a + " <=> " + b;
            }
    
            public static int normalize(int dx) {
                if(dx < 0 ) {
                    return -1;
                }
                if(dx == 0) {
                    return 0;
                }
                return 1;
            }
    
            public boolean moveTo(List<String> rowMap, A2022D22V2.Segment src, A2022D22V2.Segment dst, Monkey p) {
                int dx = normalize(src.end.x - src.start.x);
                int dy = normalize(src.end.y - src.start.y);
    
                int sx = src.start.x;
                int sy = src.start.y;
    
                int i = 0;
    
                while (sx != p.x || sy != p.y) {
                    sx += dx;
                    sy += dy;
                    i++;
                }
    
                dx = normalize(dst.end.x - dst.start.x);
                dy = normalize(dst.end.y - dst.start.y);
    
                sx = dst.start.x;
                sy = dst.start.y;
    
                while(i > 0) {
                    sx += dx;
                    sy += dy;
                    i--;                
                }
    
                System.out.println("Move:" + p.x + "," + p.y);
                System.out.println("====>" + sx + "," + sy);
                if(getChar(rowMap, sx ,sy) == '#') {
                    System.out.println("Blocked");
                    return false;
    
                }
                System.out.println("Ok!");
    
    
                p.x = sx;
                p.y = sy;
                p.direction = dst.direction.left().left();
    
                displayMap(p, true);
                return true;
            }
        }
    
        public enum Direction {
            RIGHT(1, 0, "UP", "DOWN",0),
            DOWN(0, 1, "RIGHT", "LEFT", 1),
            LEFT(-1,0, "DOWN", "UP", 2),
            UP(0, -1, "LEFT", "RIGHT", 3),
    
            ;
            int dx;
            int dy;
            int score;
    
            String rotateLeft;
            String rotateRight;
            private Direction(int dx, int dy, String rotateLeft,String rotateRight, int score) {
                this.dx = dx;
                this.dy = dy;
                this.rotateLeft = rotateLeft;
                this.rotateRight = rotateRight;
                this.score =score;
            };
    
            Direction left() {
                return Direction.valueOf(rotateLeft);
            }
    
            Direction right() {
                return Direction.valueOf(rotateRight);
            }
        }
    
    
        public static class Monkey extends Point{
    
    
            Direction direction = Direction.RIGHT;
    
        }
    
        public static void main(String[] args) {
            step1();
        }
    
        private static void step1() {
            List<String> rowMap = new ArrayList<>();
            String path = "";
            int maxWidth = 0;
            try (Scanner in = new Scanner(A2022D22V2.class.getResourceAsStream("/res/i22V2.txt"))) {            
                while (in.hasNext()) {
                    String row = in.nextLine();
                    if(row.isEmpty()) {
                        path = in.nextLine();
                    } else {
                        maxWidth = Math.max(maxWidth, row.length());
                        rowMap.add(row);
                    }
                }
            }
    
            List<Arrete> arretes = new ArrayList<>();
    
    
            try (Scanner in = new Scanner(A2022D22V2.class.getResourceAsStream("/res/i22V2rf.txt"))) {
                boolean parse = false;
                while (in.hasNext()) {
                    String row = in.nextLine().trim();
                    if("Parse".equals(row)) {
                        parse = true;
                    } else if(parse) {
                        System.out.println(row);
                        Arrete arrete  =new Arrete(row);
                        arretes.add(arrete);
                        System.out.println(arrete);
                    }
    
                }
            }
    
            normalizeMap(rowMap, maxWidth);
    
            Monkey monkey = new Monkey();
            monkey.x = rowMap.get(0).indexOf("."); 
            monkey.y = 0;
    
            System.out.println(path);
    
            int index = 0;
            while(index < path.length() && index >= 0) {
                if(path.charAt(index) == 'L') {
                    System.out.println("Left");
                    monkey.direction = monkey.direction.left();
                    index+=1;
                } else if(path.charAt(index) == 'R') {
                    System.out.println("Right");
                    monkey.direction = monkey.direction.right();
                    index+=1;
                } else {
    
                    int i = Integer.valueOf(path.substring(index).replaceAll("^([0-9]*).*", "$1"));
                    System.out.println("Move " + i);
                    index += (""+i).length();
                    do {                    
                        if(!translateToValid(rowMap, arretes, monkey))  {
                            break;
                        }                   
                        i--;
                        displayMap(monkey, false);
                    } while(i > 0);
    
                }
                displayMap(monkey, false);
            }
            displayMap(monkey, true);
            System.out.println(monkey.y+1);
            System.out.println(monkey.x+1);
            System.out.println(monkey.direction);
            int result = (monkey.y+1)*1000+(monkey.x+1)*4+monkey.direction.score;
            System.out.println(result);
        }
    
        private static void normalizeMap(List<String> rowMap, int maxWidth) {
    
            for(int y=0;y < rowMap.size();y++) {
                if(rowMap.get(y).length() < maxWidth) {
    
                    String row = rowMap.get(y);
                    while(row.length() < maxWidth) {
                        row += " ";
                    }
                    rowMap.set(y, row);
                }
                memory.add(new String(rowMap.get(y)));
            }
        }
    
        public static char getChar(List<String> rowMap, int sx, int sy) {
            String row = rowMap.get(sy);
            return row.charAt(sx);
        }
    
        private static boolean translateToValid(List<String> rowMap, List<Arrete> arretes, Monkey monkey) {     
            for(Arrete arrete: arretes) {           
                //System.out.println(arrete.a);
                if(arrete.a.include(monkey) && arrete.a.direction == monkey.direction) {
                    System.out.println(arrete.a + " " + monkey.direction);
                    return arrete.moveTo(rowMap, arrete.a, arrete.b, monkey);
    
    
                }
    
    
                if(arrete.b.include(monkey) && arrete.b.direction == monkey.direction) {
                    System.out.println(arrete.b + " " + monkey.direction);
                    return arrete.moveTo(rowMap, arrete.b, arrete.a, monkey);
    
                }
    
            }
    
            if(getChar(rowMap, monkey.x + monkey.direction.dx , monkey.y + monkey.direction.dy) == '#') {
                return false;
            }
    
            monkey.x += monkey.direction.dx;
            monkey.y += monkey.direction.dy;
            return true;
        }
    
        private static void displayMap(Monkey monkey, boolean print) {
            System.out.println();
            for(int y=0;y < memory.size();y++) {
                String row = memory.get(y);
                for(int x=0;x < row.length(); x++) {
                    if(monkey.x == x && monkey.y== y) {
                        char c;
                        switch (monkey.direction) {
                                case UP: 
                                    c = '^';
                                    break;                              
                                case DOWN: 
                                    c = 'u';
                                    break;                  
                                case RIGHT: 
                                    c = '>';
                                    break;                  
                                case LEFT: 
                                    c = '<';
                                    break;                      
                                default:
                                    throw new IllegalArgumentException("Unexpected value: " + monkey.direction);
                        }
                        if(print) System.out.print(c);
                        StringBuilder sb = new StringBuilder(row);
                        sb.setCharAt(x, c);
                        row = sb.toString();
                        memory.set(y, row);
                    } else {
                        if(print) System.out.print(row.charAt(x));
                    }
    
                }
                if(print) System.out.println();
            }
        }
    
    }
  • # Aujourd'hui, on fait dans le sale.

    Posté par  . En réponse au message Avent du Code, jour 21. Évalué à 2. Dernière modification le 21 décembre 2022 à 23:56.

    J'ai mis grosso modo 1h15.
    Pour faire l'éval, j'ai utilisé un parser JEXL. Le problème est qu'il travaille en double & qu'il m'a fallut passer en BigDecimal pour éviter les pertes de précisions du au double.
    Résultat, j'ai été obligé de transformer les expression pour utiliser des BigDecimal.
    çà m'a permit de trouver rapidement la première étoile.

    La deuxième étoile.
    J'ai déjà commencé par réduire l'arbre d'évaluation, en gros tout ce qui ne dépend pas de humn.

    Puis, j'ai rapidement vu que la fonction décroissé. J'aurai pu tenter une recherche dichotomique dans l'espace d'entier.
    Mais j'étais trop fatigué pour coder un truc intelligent.
    Résultat, j'ai monté une boucle qui permet de suivre l'évolution, j'ai joué manuellement sur les paramétres pour trouver la valeur

    C'est tellement sale que je partage mon code pour une fois :-p

    import java.math.BigDecimal;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    import org.apache.commons.jexl3.JexlBuilder;
    import org.apache.commons.jexl3.JexlContext;
    import org.apache.commons.jexl3.JexlEngine;
    import org.apache.commons.jexl3.JexlExpression;
    import org.apache.commons.jexl3.MapContext;
    
    
    
    public class A2022D21S2 {
        private static final JexlEngine jexl = new JexlBuilder().cache(512).strict(true).silent(false).create();
    
        public static void main(String[] args) {                
            step1();
        }
    
        private static void step1() {
            Map<String, String> mapMonkey = new HashMap<>();
            try (Scanner in = new Scanner(A2022D21S2.class.getResourceAsStream("/res/i21.txt"))) {
    
                while (in.hasNext()) {
                    String row = in.nextLine();
                    String[] part = row.split(":");
                    if(part.length > 2) {
                        throw new RuntimeException();
                    }
                    if(part[0].equals( "root")) {
                        part[1] = part[1].replaceAll(" ", "").replaceAll("\\+", "-");
                        System.out.println("root:" + part[1]);
                    }
                    mapMonkey.put(part[0], part[1]);
                }
    
            }
    
            for (Map.Entry<String, String> entry : mapMonkey.entrySet()) {
                if (canReduce(mapMonkey, entry.getKey())) {
                    BigDecimal d = evalMonkey(mapMonkey, entry.getKey());
                    System.out.println("Reduce " + entry.getKey() + ":" + d.toPlainString());
                    mapMonkey.put(entry.getKey(), d.toPlainString());
                }
            }
    
            System.out.println("=========================");
    
            Double previous = null;
            for(long x=3876907167000L;x < 3876907168000L;x+= 1L) {
                BigDecimal bdx = new BigDecimal(x);
                mapMonkey.put("humn", bdx.toString());
                BigDecimal currentResult = evalMonkey(mapMonkey, "root");
                if(currentResult.doubleValue() == 0.0) {
                    System.out.println("Found:" + x);
                    break;
                }
                System.out.println(x + "=>" + currentResult.toPlainString());
                if(previous != null) {
                    System.out.println(previous > currentResult.doubleValue() ? "diminue" : "augmente");
                }
                previous = currentResult.doubleValue();
            }
        }
    
        private static boolean canReduce(Map<String, String> mapMonkey, String key) {
            String expr = mapMonkey.get(key);
            if(expr.matches("[ 0-9.]*")) {
                return true;
            }
    
            for(String other: mapMonkey.keySet()) {
    
                if(expr.contains(other)) {
                    if("root".equals(other) || "humn".equals(other)) {
                        return false;
                    } 
    
                    boolean r = canReduce(mapMonkey, other);
                    if(! r) {
                        return false;
                    }                           
                }
            }
            return true;
        }
    
        public static final BigDecimal MINUS_ONE = BigDecimal.valueOf(-1L);
        public static final BigDecimal ZERO = BigDecimal.valueOf(0L);
        public static final BigDecimal ONE = BigDecimal.valueOf(1L);
        private static BigDecimal evalMonkey(Map<String, String> mapMonkey, String name) {
            String expr = mapMonkey.get(name);
            if(expr.matches("[ 0-9.]*")) {
                return new BigDecimal(expr.replaceAll(" " , ""));
            }
    
            JexlContext context = new MapContext();
            context.set("MINUS_ONE", MINUS_ONE);
            for(String other: mapMonkey.keySet()) {
                if(expr.contains(other)) {
                    context.set(other, evalMonkey(mapMonkey, other));               
                }
            }
            expr = expr.replaceAll(" ", "");
            //System.out.println("Eval:" + expr);
            JexlExpression e = jexl.createExpression( expr );
    
            BigDecimal bdBigDecimal;
    
            expr = expr.replaceAll("\\+([a-z]*)", ".add($1)"); 
            expr = expr.replaceAll("\\*([a-z]*)", ".multiply($1)");
            expr = expr.replaceAll("\\/([a-z]*)", ".divide($1)");
            expr = expr.replaceAll("\\-([a-z]*)", ".add($1.mulitply(MINUS_ONE))");
    
            //System.out.println("Eval2:" + expr);
    
            Object o  =e.evaluate(context);
            if(o instanceof BigDecimal) {
                return (BigDecimal)o;
            }
    
            if(o instanceof Boolean) {
                return Boolean.TRUE.equals(o) ? ONE : ZERO;
            }
    
            throw new RuntimeException();
        }
    }
  • # il était vraiment null celui-ci

    Posté par  . En réponse au message Avent du Code, jour 20. Évalué à 2.

    J'ai pris le problème du mauvais sens, il m'a fallut plus de 3h pour comprendre qu'il ne fallait pas appliquer la transformation 3000 fois pour avoir la réponse.

    J'ai réecris 3 ou 4 fois mon code. J'ai commencé par un tableau avec des modulos au final, j'ai terminé par une liste doublement chainés comme quasiment tout le monde.

    J'ai remis une bonne 1h30 pour caler le modulo pour éviter d'appliquer les millions de déplacement.

    Bref, un très mauvaise journée. En plus, vous êtes plein à y être arrivé avant moins résultat.
    Je n'ai plus aucun espoir de rafler la seconde place.

  • [^] # Re: Modélisation trop longue à débugger

    Posté par  . En réponse au message Avent du Code, jour 19. Évalué à 1.

    Petite amélioration, je descends à 6s en modifiant mon DFS

    L'idée est de ne pas aller jusqu'au bout si on sait déjà qu'on sera en-dessous du meilleur temps.
    ```
    public static void executeDFS(State state) {
    int leftTurn = NB_TURN_32- state.index;
    int expGeode = state.geode+(NB_TURN_32-state.index) * (state.geodeRobot) + (leftTurn+1) * (leftTurn + 0) / 2;

    if(bestMap.get(state.bp) != null && expGeode < bestMap.get(state.bp)) {
    return;
    }

    if(state.index == NB_TURN_32) {
        if(bestMap.get(state.bp) == null || state.geode > bestMap.get(state.bp)) {              
            bestMap.put(state.bp, state.geode);                         
            System.out.println("Best:" + state.bp.index +";" + state.geode);                                            
        }
        return;
    }
    List<String> actions =state.availablesAction();
    State newState = new State(state.bp);
    for(String action : actions) {          
        state.copyInto(newState);
        newState.transform(action);
        executeDFS(newState);
    }
    

    }
    ```

  • [^] # Re: Modélisation trop longue à débugger

    Posté par  . En réponse au message Avent du Code, jour 19. Évalué à 2. Dernière modification le 19 décembre 2022 à 21:01.

    Au final, J'aurai mis 35min de plus.

    Le problème venait que j'avais mis une règle qui réduisait le nombre d'action possible pendant mon parcours en profondeur

    Il met 1min3s pour calculer le 2ème.

    Pour une fois , mon code n'est pas trop moche :)

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    import java.util.Scanner;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    public class A2022D19 {
        private static final String BUILD_ORE = "BUILD_ORE";
        private static final String BUILD_CLAY = "BUILD_CLAY";
        private static final String BUILD_OBSIDIAN = "BUILD_OBSIDIAN";
        private static final String BUILD_GEODE = "BUILD_GEODE";
        private static final String WAIT = "WAIT";
    
        static Map<BluePrint, Integer> bestMap = new HashMap<>();
    
        public static class Cost {
            int costOre;
            int costClay;
            int costObsidian;
    
            public String toString() {
                return costOre +";" + costClay + ";" + costObsidian;
            }                   
        }   
    
        public static class BluePrint {
            int index;
            Cost buildOreRobot;
            Cost buildClayRobot;
            Cost obsidianRobot; 
            Cost geodeRobot;
    
            public BluePrint(String row, int index) {
                this.index = index;
                String[] robots =  row.split("\\.");
    
                buildOreRobot = buildCost(robots[0]);
                buildClayRobot = buildCost(robots[1]);
                obsidianRobot = buildCost(robots[2]);
                geodeRobot = buildCost(robots[3]);
    
            }
    
            private Cost buildCost(String row) {
                Cost cost = new Cost();
                String regex;
                regex = ".* ([0-9]*) ore.*";
                if(row.matches(regex)) {
                    String s = row.replaceAll(regex, "$1");
                    cost.costOre = Integer.valueOf(s);
                }
    
    
                regex = ".* ([0-9]*) clay.*";
                if(row.matches(regex)) {
                    String s = row.replaceAll(regex, "$1");
                    cost.costClay = Integer.valueOf(s);
                }
    
                regex = ".* ([0-9]*) obsidian.*";
                if(row.matches(regex)) {
                    String s = row.replaceAll(regex, "$1");
                    cost.costObsidian = Integer.valueOf(s);
                }
    
                System.out.println(cost.toString());
    
                return cost;
            }
        }   
    
        public static class Action {
            int buildOreRobot = 0;
            int buildClayRobot = 0;
            int buildObsidianRobot = 0;
            int buildGeodeRobot = 0;
        }
    
        public static class State {
    
    
            BluePrint bp;
            int oreRobot = 1;
            int clayRobot = 0;
            int obsidianRobot = 0;
            int geodeRobot = 0;
    
            int ore = 0;
            int clay = 0;
            int obsidian = 0;
            int geode = 0;
            int index=0;
    
            public State(BluePrint bp) {
                this.bp = bp;
            }
    
            public boolean canPaid(Cost cost) {
                return ore >= cost.costOre
                    && clay >= cost.costClay
                    && obsidian >= cost.costObsidian;                                   
            }
    
            public void paid(Cost cost ) {
                ore -= cost.costOre;
                clay -= cost.costClay;
                obsidian -= cost.costObsidian;
            }
    
            public List<String> availablesAction() {
                List<String> actions  = new ArrayList<>();
                if(canPaid(bp.geodeRobot)) {                
                    actions.add(BUILD_GEODE);
                    return actions;
                }
    
                if(canPaid(bp.obsidianRobot)) {             
                    actions.add(BUILD_OBSIDIAN);
                    return actions;
                }
    
                if(canPaid(bp.buildClayRobot) && max(bp.buildOreRobot.costClay, bp.buildClayRobot.costClay, bp.obsidianRobot.costClay, bp.geodeRobot.costClay) >  this.clayRobot) {             
                    actions.add(BUILD_CLAY);                
                }
    
                if(canPaid(bp.buildOreRobot) && max(bp.buildOreRobot.costOre, bp.buildClayRobot.costOre, bp.obsidianRobot.costOre, bp.geodeRobot.costOre) >  this.oreRobot) {               
                    actions.add(BUILD_ORE);             
                }
    
                actions.add(WAIT);
                return actions;
    
            }
    
            private int max(int costOre, int costOre2, int costOre3, int costOre4) {
                return Math.max(Math.max(Math.max(costOre, costOre2), costOre3), costOre4);
            }
    
            public void transform(String command) {
                ++index;
                //System.out.println(index);
                //System.out.println(command);      
                this.ore += this.oreRobot;
                this.clay += this.clayRobot;
                this.obsidian += this.obsidianRobot;            
                this.geode += this.geodeRobot;      
    
                if(command.equals(BUILD_GEODE)) {
                    paid(bp.geodeRobot);
                    this.geodeRobot++;
                }
    
                if(command.equals(BUILD_OBSIDIAN)) {
                    paid(bp.obsidianRobot);
                    this.obsidianRobot++;
                }
    
                if(command.equals(BUILD_CLAY)) {
                    paid(bp.buildClayRobot);
                    this.clayRobot++;
                }
    
                if(command.equals(BUILD_ORE)) {
                    paid(bp.buildOreRobot);
                    this.oreRobot++;
                }
    
                //System.out.println("S:" + this.ore + ";"  + this.clay + ";" + this.obsidian + ";" + this.geode);
                //System.out.println("R:" + this.oreRobot + ";"  + this.clayRobot + ";" + this.obsidianRobot + ";" + this.geodeRobot);
    
            }
    
            public void copyInto(A2022D19.State newState) {
                newState.bp = this.bp;
                newState.oreRobot = this.oreRobot;
                newState.clayRobot = this.clayRobot;
                newState.obsidianRobot = this.obsidianRobot;
                newState.geodeRobot = this.geodeRobot;
    
                newState.ore = this.ore;
                newState.clay = this.clay;
                newState.obsidian = this.obsidian;
                newState.geode = this.geode;
                newState.index= this.index;
    
            }
        }
    
        public static void main(String[] args) {
            step1();
        }
    
    
        public static void executeDFS(State state) {
            if(state.index == 32) {
                if(bestMap.get(state.bp) == null || state.geode > bestMap.get(state.bp)) {              
                    bestMap.put(state.bp, state.geode);                         
                    System.out.println("Best:" + state.bp.index +";" + state.geode);                                            
                }
                return;
            }
            List<String> actions =state.availablesAction();
            State newState = new State(state.bp);
            for(String action : actions) {          
                state.copyInto(newState);
                newState.transform(action);
                executeDFS(newState);
            }
        }
    
        private static void step1() {
            try (Scanner in = new Scanner(A2022D19.class.getResourceAsStream("/res/i19.txt"))) {
                List<BluePrint> listBp = new ArrayList<>(); 
                while (in.hasNext()) {
                    String row = in.nextLine();
                    BluePrint bp = new BluePrint(row, listBp.size()+1);             
                    listBp.add(bp);
    
                }
    
                State state;    
                for(BluePrint bp: listBp) {
                    state =new State(bp);
                    executeDFS(state);
                }               
    
                int sum  = 0;
                int prod = 1;
                for(Map.Entry<BluePrint, Integer> e : bestMap.entrySet()) {
                    System.out.println("Final:" + e.getKey().index + "," + e.getValue());   
                    prod *= e.getValue();
                    sum += (e.getKey().index  * e.getValue());
                }
    
                System.out.println(sum);
                System.out.println(prod);
    
    
            }
    
        }
    
    }
  • [^] # Re: Modélisation trop longue à débugger

    Posté par  . En réponse au message Avent du Code, jour 19. Évalué à 1.

    Est ce qu'on peut construire plusieurs robots en un tour ?

    C'est probablement çà mon erreur ?

  • [^] # Re: Modélisation trop longue à débugger

    Posté par  . En réponse au message Avent du Code, jour 19. Évalué à 1.

    Gg, Perso, j'y ai passé 2h ce matin et je bloque sur le fait que je ne trouve pas comment arriver à 12 sur le 2ème du test unit.
    Je dois avoir un bug qui m'echape.

    Malheureusement, j'ai 2 truc urgent qui sont tombé aujourd'hui. Pas sur que je puisse y rebosser aujourd'hui.
    et la fin de semaine risque d'être compliqué, je suis en vacances jeudi soir.

  • # Plus cool que les jours précédents

    Posté par  . En réponse au message Avent du Code, jour 18. Évalué à 2.

    J'ai mis 45min pour les 2 étoiles.

    La première étape stockés les cubes dans un HashSet puis compter les faces non adjacente à une autre en checkant la présence dans le HashSet.

    Pour la deuxième, j'ai monté un dijkstra en partant d'un espace à l'extérieur à la structure de cube. Au final, je check si le côté du cube est adjacent à une zone accessible depuis l'air.

  • # Tetris style

    Posté par  . En réponse au message Avent du Code, jour 17. Évalué à 3.

    J'ai bien galéré encore sur celui-ci ~ 4h.

    La première partie est relativement simple. Je joue à Tetris dans un tableau de char.

    La deuxième partie est galère car si j'utilise la méthode de la première partie ,avec un clear du tableau quand c'est possible après une ligne pleine.
    Il me fallait ~20j de calcul pour approcher 1000000000000L piece.

    J'ai donc identifié quand le pattern d'empilement se répète. De cette manière, j'ai rapidement le test unit de la 2eme partie qui marchait.
    pour trouver 1514285714288.

    Seulement, quand j'appliquais la méthode sur mon input, çà ne marchait pas.
    Je suis revenu sur un jeu plus petite et j'ai comparé la première méthode et la deuxième méthode avec le raccourcis quand je détecte la répétition.
    J'ai constaté qu'il me manquait 9 à chaque application de la répétition.

    En ajoutant, le nombre de répétition fois 9 ,j'ai obtenu le résultat attendu.

  • [^] # Re: Ça chauffe, ça chauffe !

    Posté par  . En réponse au message Avent du Code jour 16. Évalué à 1.

    Gg.
    Je n'ai pas pensé à simplifier les chemin.
    Résultat, j'ai fait un AG. il met 1h pour trouver l'optimum de la 2ème réponse :o)

  • # Le 16/12

    Posté par  . En réponse au journal Calendrier de l'Avent du code. Évalué à 2.

    çà me rassure de voir que tout le monde a ramé sur celui d'aujourd'hui.

    Perso, j'y ai bien passé 4h en cumulé. J'ai commencé vers 10h et au final, mon code met presque 1h pour trouver l'optimum de la 2ème réponse avec un AG.

    Je pense que j'ai du manquer une simplification du problème car normalement tous les problèmes doivent sortir sur une machine normal en moins de 10min.

  • [^] # Re: Vivement , le 1

    Posté par  . En réponse au journal Calendrier de l'Avent du code. Évalué à 1.

    Ce matin, tu étais devant moi et il y a l'air d'avoir eu un nouvelle inscrit. Résultat,je te suis repassé devant.

    Pour info, On est en mode Local Score

    Local Score, which awards users on this leaderboard points much like the global leaderboard. If you add or remove users, the points will be recalculated, and the order can change. For N users, the first user to get each star gets N points, the second gets N-1, and the last gets 1. This is the default.

    A priori, je te suis repassé devant car avec l'arrivé d'un nouveau , çà revalorise potentiellement le N des classements précédents.

  • [^] # Re: Vivement , le 1

    Posté par  . En réponse au journal Calendrier de l'Avent du code. Évalué à 3.

    C'est clair. L'an dernier, il y en a un ou j'y ai passé + d'une demi-journée pour arriver à le faire.

    C'était celui , où il fallait monter un interpréteur d'expression pour lequel, il fallait déduire le min et la max possible. J'avais beau avoir optimisé mon code avec de la mémoïsation & quelques optims. Il mettait 30min à sortir la réponse :-p.

  • [^] # Re: C'est parti !

    Posté par  . En réponse au journal Calendrier de l'Avent du code. Évalué à 2.

    Il y a moins de joueur que l'an dernier.

    https://adventofcode.com/2021/stats
    https://adventofcode.com/2022/stats

    et les sujets sont plus simple pour le moment.

  • [^] # Re: Vivement , le 1

    Posté par  . En réponse au journal Calendrier de l'Avent du code. Évalué à 5.

    J'ai créé un leadboard
    1844559-f65dbf07
    si vous vous voulez le rejoindre, il faut l'ajouter dans votre interface sur adventofcode

  • # Vivement , le 1

    Posté par  . En réponse au journal Calendrier de l'Avent du code. Évalué à 5.

    Mince, je voulais faire un journal dessus. Tu m'as devancé.

    Pour ma part, je compte les jours avant son lancement autant que j'attends d'ouvrir mon premier jour de mon calendrier Kinder :-p.

    Est-ce que çà vous dit d'ouvrir un groupe pour les lecteurs de LFR ? de cette manière , on aura un classement LFR :)

  • [^] # Re: Factice

    Posté par  . En réponse au lien vaccins ARNm : L’incidence des lésions myocardiques est 800 fois supérieure à l’incidence habituelle. Évalué à 0.

    L article est signé :
    Guillaume Le Pessec
    Membre du Collège des Cardiologues en Formation,
    Rouen

    En fait, ce n est pas un médecin, ni un professeur et il ne fait pas partie d un service de cardilogie…

  • [^] # Re: Factice

    Posté par  . En réponse au lien vaccins ARNm : L’incidence des lésions myocardiques est 800 fois supérieure à l’incidence habituelle. Évalué à 0.

    Juste pour comparer, un site officiel sur la cardiologie…
    Ça fait un peu moins amateur avec des titres moins accrocheurs.
    https://sfcardio.fr/actualites

    Il y a eu du taff pour faire le site du lien. Qui en est le commanditaire dans quel objectif ?