syj a écrit 647 commentaires

  • # Solution en Java 403ms

    Posté par  . En réponse au message Advent of Code, jour 14. Évalué à 1.

    Ci-dessous ma soluce en Java pour la partie 2. Elle met 403ms une fois Java lancé (c'est comme un bon diesel Java). Et encore, j'ai une vilaine boucle qui compte jusqu'à avant le milliard.
    J'optimise en utilisant des objets mutable & un bon vieux cache basé sur un Record.

    package aoc2023;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class Aoc2023s14v2 {     
        enum Type {
            SPHERE,
            ROCK;
        }
    
        public static class Point {
            int x;
            int y;
            Type type;
    
            public Point(int x, int y, Type type) {
                this.x= x;
                this.y=y;
                this.type = type;
            }
        }
    
        public static class World {
            int width;
            int height;
    
            Point[][] map;
            List<Point> spheres = new ArrayList<>();
    
    
            public World(List<String> rows) {
                map = new Point[rows.size()][rows.get(0).length()];
                for(int y=0;y < rows.size();y++) {
                    addRow(rows.get(y), y);
                }
                this.height = rows.size();
            }
    
            public void addRow(String row, int y) {
                this.width = row.length();
    
                for(int x=0;x < row.length();x++) {
                    Point p = null;
                    if(row.charAt(x) == 'O') {
                        p =new Point(x, y, Type.SPHERE);
                        spheres.add(p);
                    } else if(row.charAt(x) == '#') {
                        p = new Point(x, y, Type.ROCK);
                    }
    
                    map[y][x] =p;
                }
            }
    
            public boolean isFree(int x, int y) {
                if(x < 0 || x >= width || y < 0 || y >= height ) {
                    return false;
                }
    
                return this.map[y][x] == null;          
            }
    
            public Point find(int x, int y) {
                if(x < 0 || x >= width || y < 0 || y >= height ) {
                    return null;
                }
                return this.map[y][x];      
            }
    
            public void move(int dx, int dy) {
                boolean change = false;
                do {
                    change =false;
                    for(Point p : spheres) {
                        if(isFree(p.x + dx, p.y +dy)) {
                            map[p.y][p.x] = null;
                            p.x += dx;
                            p.y += dy;
                            map[p.y][p.x] = p;
                            change =true;
                        }
                    }               
                } while(change);            
            }
    
            public int computeWeight() {
                int sum = 0;
                for(Point sphere :spheres) {
                    sum += (height-sphere.y);
                }
                return sum;
            }
    
    
            public List<String> toRows() {
                List<String> rows = new ArrayList<>();
                StringBuilder sb = new StringBuilder();
                for(int y=0;y < height;y++) {
                    sb.setLength(0);
                    for(int x=0;x < width;x++) {
                        Point p = find(x, y);
                        if(p == null) {
                            sb.append('.');
                        } else if(p.type == Type.ROCK) {
                            sb.append('#');
                        } else {
                            sb.append('O');
                        }
                    }
                    rows.add(sb.toString());
                }
                return rows;
            }
        }
    
        public static void main(String[] args) {        
            long startMs = System.currentTimeMillis();          
            try (Scanner in = new Scanner(Aoc2023s14v2.class.getResourceAsStream("res/t14.txt"))) {
                List<String> rows = new ArrayList<>();
                while (in.hasNext()) {
                    rows.add(in.nextLine());
                }
    
                Integer startCycle = null;
                Integer cycleCount = null;
                World world = null;
                final long LOOPS = 1_000_000_000L;
                for(long x = 0 ;x < LOOPS;x++) {
                    CacheKey current = new CacheKey(rows);
                    if(keys[current.cacheIndex()] != null && keys[current.cacheIndex()].equals(current)) {
                        if(startCycle == null) {
                            startCycle = current.cacheIndex();
                            cycleCount = 0;
                        } else if(startCycle == current.cacheIndex()) {
                            System.out.println("Make cycle: " + cycleCount);
                            // Could be more elegant :)
                            while(x < (LOOPS-cycleCount)) {
                                x += (cycleCount+1);
                            }
                        } else {
                            cycleCount++;
                        }
                        world = cache_worlds[current.cacheIndex()];
                    } else {
                        world = computeWorld(rows);
                        keys[current.cacheIndex()] = current;
                        cache_worlds[current.cacheIndex()] = world;
                        System.out.println("miss " + x);
    
                        startCycle = null;
                        cycleCount = null;
                    }
                    rows = world.toRows();              
                }
    
                System.out.println(world.computeWeight());
            }   
            System.out.println((System.currentTimeMillis() - startMs) + "ms");
        }
    
        private static World computeWorld(List<String> rows) {
            World world;
            world = new World(rows);
            world.move(0, -1);
            world.move(-1, 0);
            world.move(0, 1);
            world.move(1, 0);
            return world;
        }
    
        public static record CacheKey(List<String> rows) {
    
            public int cacheIndex() {
                return Math.abs(this.hashCode()) % CACHE_SIZE;
            }
        }
    
        public static final int CACHE_SIZE = 1_000_000;
        public static  CacheKey[] keys = new CacheKey[CACHE_SIZE];
        public static  World[] cache_worlds = new World[CACHE_SIZE];
    
    }
  • # J'en ai bavé.

    Posté par  . En réponse au message Advent of Code 2023, jour 12. Évalué à 1.

    6h au total ! J'ai commencé par prendre le problème de travers.

    J'ai fait substitution récursive des '?' ,c'était mon erreur.

    C'est après que j'ai compris qu'il fallait distribuer les espaces restant entre les groupes.

    çà permet d'exprimer le problème avec une fonction recursive pour lequel on peut mettre en place un cache des valeurs par rapport au reste à évaluer.

    Environ 414ms sur ma machine (après avoir commenté les println)

    package aoc2023;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Scanner;
    import java.util.concurrent.atomic.AtomicLong;
    
    public class Aoc2023s12v4 { 
        public static record Evaluation(List<Integer> groupes, int totalDot, String dstSpring) {                    
        }
    
        public static Evaluation[] cache = new Evaluation[1_000_000];
        public static long[] cacheValue = new long[1_000_000];
    
        public static void main(String[] args) {                        
            assert (countExpandedPossibility("??# 2") == 16L);
    
            assert (countExpandedPossibility("???.### 1,1,3") == 1L); 
            assert (countExpandedPossibility(".??..??...?##. 1,1,3") == 16384L);
            assert (countExpandedPossibility("????.#...#... 4,1,1") == 16L);
            assert (countExpandedPossibility("????.######..#####. 1,6,5") == 2500L);
            assert (countExpandedPossibility("?###???????? 3,2,1") == 506250L);
            //assert (countExpandedPossibility("???.?#?????##?#????? 1,2,7,1") == 506250L);
    
            System.out.println("-----------          -----------");
            System.out.println("----------- END TEST -----------");
            System.out.println("-----------          -----------");
    
    
            try (Scanner in = new Scanner(Aoc2023s12v4.class.getResourceAsStream("res/t12.txt"))) {
                List<String> map = new ArrayList<>();
    
                while (in.hasNext()) {
                    String row = in.nextLine();
                    map.add(row);
                }
    
                long count = 0;
    
                for (String row : map) {
                    count += countExpandedPossibility(row);
                }
                System.out.println(count);
            }
        }
        private static long countExpandedPossibility(String row) {
            String srcSprings = row.split(" ")[0];
            int[] srcRules = Arrays.stream(row.split(" ")[1].split(",")).mapToInt(s -> Integer.parseInt(s)).toArray();
    
            long r = countExpanded(srcSprings, srcRules, 5);
            System.out.println(r);
            return r;
        }
        private static long countExpanded(String srcSprings, int[] srcRules, int i) {
            int[] dstRules = new int[srcRules.length * 5];
            for (int x = 0; x < i; x++) {
                for (int y = 0; y < srcRules.length; y++) {
                    dstRules[x * srcRules.length + y] = srcRules[y];
                }
            }
    
            String dstSpring = srcSprings;
            for(int x=0;x < i-1;x++) {
                dstSpring += '?' + srcSprings;
            }               
            System.out.println("Pattern:");
            System.out.println(dstSpring);
    
            int total = Arrays.stream(dstRules).sum();
            int totalDot = dstSpring.length() - total;
    
            System.out.println(total + " + " + totalDot + " => " + dstSpring.length());
    
    
            return distributeDotBetweenGroup(
                    Arrays.stream(dstRules).mapToObj(Integer::valueOf).toList(),
                    true,
                    totalDot,               
                    dstSpring);             
        }
        private static long distributeDotBetweenGroup(List<Integer> groupes, boolean first, int totalDot, String dstSpring) {           
            if(0 == groupes.size() ) {
                String current = "";
                for(int j=0;j < totalDot;j++) {
                    current += '.';
                }
                //System.out.println(sb);
                if(match(current, dstSpring)) {             
                    return 1;           
                }
                return 0;
            }
    
            int size = groupes.get(0);
    
            StringBuilder sb = new StringBuilder();
            long sum  = 0;
            for(int ud=(first? 0:1);ud <= totalDot;ud++) {
                sb.setLength(0);            
                for(int j=0;j < ud;j++) {
                    sb.append('.');             
                }           
                for(int j=0;j < size;j++) {
                    sb.append('#');
                }
    
    
                if(! match(sb, dstSpring, sb.length())) {
                    continue;
                }
    
                Evaluation eva= new Evaluation(groupes.subList(1, groupes.size()), totalDot-ud, dstSpring.substring(sb.length()));
    
                int indexCache =Math.abs(eva.hashCode())% cache.length;
                if(cache[indexCache] !=null && cache[indexCache].equals(eva)) {
                    sum += cacheValue[indexCache];
                } else {
                    long i= distributeDotBetweenGroup(eva.groupes, false, eva.totalDot, eva.dstSpring);
                    cache[indexCache] = eva;
                    cacheValue[indexCache] = i;
                    sum += i;
                }           
    
            }
            return sum;
    
        }
        private static boolean match(String test, String refPattern) {
            if(test.length() != refPattern.length()) {
                return false;
            }
            for (int x = 0; x < test.length(); x++) {
                char c = refPattern.charAt(x);
                if (c != '?') {
                    if (test.charAt(x) != c) {
                        return false;
                    }
                }
            }
            return true;
        }
        private static boolean match(StringBuilder test, String refPattern, int wi) {       
            for (int x = 0; x < wi; x++) {
                char c = refPattern.charAt(x);
                if (c != '?') {
                    if (test.charAt(x) != c) {
                        return false;
                    }
                }
            }
            return true;
        }
    }
  • # Ma solution

    Posté par  . En réponse au message Advent of Code 2023 : Jour 10. Évalué à 1.

    Pour la deuxième partie, j'ai opté pour une solution où je remplace les tuiles de base par des tuiles de 3x3
    Je remplie ensuite en faisant les cellules en bordure de la map.

    Note: Ce code doit être utilisée --Xms2G pour avoir une stack plus grande que celle par défaut.

    package aoc;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Scanner;
    import java.util.Set;
    import java.util.Stack;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.stream.Collectors;
    
    import aoc.Aoc2023s10p1.Direction;
    import aoc.Aoc2023s10p1.Maze;
    import aoc.Aoc2023s10p1.Pipe;
    
    public class Aoc2023s10p2 {
        public enum Direction {
            N(0, -1), S(0, 1), E(1, 0), W(-1, 0);
    
            int dx;
            int dy;
    
            Direction(int dx, int dy) {
                this.dx = dx;
                this.dy = dy;
            }
    
            Direction comeFrom() {
                if (this == N) {
                    return S;
                } else if (this == E) {
                    return W;
                } else if (this == W) {
                    return E;
                } else if (this == S) {
                    return N;
                }
                throw new RuntimeException();
            }
        }
        public enum Pipe {
    
            V('|', Arrays.asList(Direction.N, Direction.S),
                    new int[][] {new int[]{0, 1, 0}, new int[]{0, 1, 0}, new int[]{0, 1, 0}}
                    ), // is a vertical pipe connecting north and south.
            H('-', Arrays.asList(Direction.E, Direction.W),
                    new int[][] {new int[]{0, 0, 0}, new int[]{1, 1, 1}, new int[]{0, 0, 0}}
                    ), // is a horizontal pipe connecting east and west.
            L('L', Arrays.asList(Direction.N, Direction.E),
                    new int[][] {new int[]{0, 1, 0}, new int[]{0, 1, 1}, new int[]{0, 0, 0}}
                    ), // , is a 90-degree bend connecting north and east.
            J('J', Arrays.asList(Direction.N, Direction.W),
                    new int[][] {new int[]{0, 1, 0}, new int[]{1, 1, 0}, new int[]{0, 0, 0}}
                    ), // is a 90-degree bend connecting north and west.
            _7('7', Arrays.asList(Direction.S, Direction.W),
                    new int[][] {new int[]{0, 0, 0}, new int[]{1, 1, 0}, new int[]{0, 1, 0}}
                    ), // is a 90-degree bend connecting south and west.
            F('F', Arrays.asList(Direction.S, Direction.E),
                    new int[][] {new int[]{0, 0, 0}, new int[]{0, 1, 1}, new int[]{0, 1, 0}}
                    ), // is a 90-degree bend connecting south and east.
            D('.', Collections.emptyList(),
                    new int[][] {new int[]{0, 0, 0}, new int[]{0, 0, 0}, new int[]{0, 0, 0}}
                    ), // is ground; there is no pipe in this tile.
            S('S', Arrays.asList(Direction.N, Direction.S, Direction.E, Direction.W),
                    new int[][] {new int[]{0, 1, 0}, new int[]{1, 1, 1}, new int[]{0, 1, 0}}
                    ),// is the starting position of the
                                                                                        // animal; there is a pipe on this
                                                                                        // tile, but your sketch doesn't
                                                                                        // show what shape the pipe has.
            ;
    
            char c;
            List<Direction> directions;
            int[][] matrix;
    
            Pipe(char c, List<Direction> directions, int[][] matrix) {
                this.c = c;
                this.directions = directions;
                this.matrix = matrix;
            }
    
            boolean acceptFrom(Direction d) {
                return directions.contains(d);
            }
        }
        public static class Maze2 {
            List<List<Pipe>> maze;
            final int heightMap;
            final int widthMap;
            final int[][] map;
            final int[][] weights;
    
            final int[][] externs;
    
            Maze2(List<List<Pipe>> maze) {
                this.maze = maze;
    
                int height = maze.size();
                int width = maze.get(0).size();     
                weights = new int[height][width];
                computeWeight();
    
                heightMap = height*3;
                widthMap = width*3;
                map = new int[heightMap][widthMap];
                externs = new int[heightMap][widthMap];
                for (int x = 0; x < width; x++) {
                    for (int y = 0; y < height; y++) {
    
                        if(weights[y][x] != Integer.MAX_VALUE) {
                            writeMatrix(maze, x, y);
                        }
                    }
                }
    
                for (int x = 0; x < widthMap; x++) {
                    for (int y = 0; y < heightMap; y++) {
                        externs[y][x] = -1;
                        if (map[y][x] == 1) {
                            externs[y][x] = 0;
                        }
    
                    }
                }
    
                for (int x = 0; x < widthMap; x++) {
                    fillEnclosed(x, 0);
                    fillEnclosed(x, heightMap - 1);
                }
    
                for (int y = 0; y < heightMap; y++) {
                    fillEnclosed(0, y);
                    fillEnclosed(widthMap - 1, y);
                }
    
            }
    
            private void writeMatrix(List<List<Pipe>> maze, int x, int y) {
                Pipe p = maze.get(y).get(x);
                for (int dy = 0; dy < 3; dy++) {
                    for (int dx = 0; dx < 3; dx++) {
                        int m = p.matrix[dy][dx];
                        map[y*3 +dy][x*3 + dx] = m;
                    }
                }
            }
    
            private void fillEnclosed(int x, int y) {
                if (x < 0 
                        || x >= widthMap 
                        || y < 0 
                        || y >= heightMap) {
                    return;
                }
                if (map[y][x] == 1) {
                    return;
                }
    
                if (externs[y][x] < 0) {
                    externs[y][x] = 1;
    
                    for (Direction d : Direction.values()) {
                        fillEnclosed(x + d.dx, y + d.dy);
                    }               
                }
            }
    
            public void print() {
                for(int y=0;y < heightMap;y++) {
                    for(int x=0;x < widthMap;x++) {
                        System.out.print(map[y][x]);
                    }
                    System.out.println();
                }
    
                for(int y=0;y < heightMap;y++) {
                    for(int x=0;x < widthMap;x++) {
                        int i = externs[y][x];
                        if(i < 0) {
                            System.out.print("I");
                        } else if(i == 0) {
                            System.out.print("#");
                        } else {
                            System.out.print(".");
                        }
    
                    }
                    System.out.println();
                }
            }
    
            public int countEnclosed() {
                int max = 0;
                int height = maze.size();
                int  width= maze.get(0).size(); 
                for (int y = 0; y < height; y++) {
                    for (int x = 0; x < width; x++) {
    
                        if(emptyTile(x, y)) {
                            max++;
                        }       
                    }
                }
                return max;
            }
    
            public boolean emptyTile(int x, int y) {
                for (int dy = 0; dy < 3; dy++) {
                    for (int dx = 0; dx < 3; dx++) {
    
                        if(externs[y*3+dy][x*3+dx] >= 0) {
                            return false;
                        }
                    }
                }
                return true;
            }
    
            public void computeWeight() {
                int height = maze.size();
                int width = maze.get(0).size(); 
    
                int sx = 0;
                int sy = 0;
                for(int x=0;x < width;x++) {
                    for(int y=0;y < height;y++) {
                        weights[y][x] = Integer.MAX_VALUE;
                        if(maze.get(y).get(x) == Pipe.S) {
                            weights[y][x] = 0;
                            sx = x;
                            sy = y;
                        }
                    }
                }
    
                fillWeightFrom(sx, sy);
            }
    
            private void fillWeightFrom(int cx, int cy) {
                int w = weights[cy][cx];
                Pipe currentPipe = this.maze.get(cy).get(cx);
    
                for(Direction d : Direction.values()) {
    
                    if(currentPipe.directions.contains(d)) {
                        int dx = cx+ d.dx;
                        int dy = cy+ d.dy;
                        Pipe nextPipe = next(dx, dy);
                        if(nextPipe != null) {
                            if(nextPipe.acceptFrom(d.comeFrom())) {
                                int wn = weights[dy][dx];
                                if(wn > (w+1)) {
                                    weights[dy][dx] = w+1;
                                    fillWeightFrom(dx, dy);
                                }
                            }
                        }
                    }               
                }       
            }
    
            public Pipe next(int cx, int cy) {
                int height = maze.size();
                int width = maze.get(0).size(); 
                if(cx < 0 || cx >= width) {
                    return null;
                }
                if(cy < 0 || cy >= height) {
                    return null;
                }
    
                return this.maze.get(cy).get(cx);
            }
        }
        public static Map<String, Pipe> pipeBySymbol = Arrays.stream(Pipe.values())
                .collect(Collectors.toMap(p -> "" + p.c, p -> p));
        public static void main(String[] args) {
    
            try (Scanner in = new Scanner(Aoc2023s10p2.class.getResourceAsStream("res/Aoc2023s10p1.txt"))) {
                String row;
                List<List<Pipe>> maze = new ArrayList<>();
                while (in.hasNext()) {
                    row = in.nextLine();
    
                    maze.add(row.chars().mapToObj(i -> pipeBySymbol.get(String.valueOf((char) i))).toList());
    
                }
    
                Maze2 mazeSolve = new Maze2(maze);
                mazeSolve.print();
                System.out.println(mazeSolve.countEnclosed());
            }
        }
    
    }
  • # Je me lance ma soluce en Java

    Posté par  . En réponse au message Advent of Code 2023 : Day 3. Évalué à 1.

    Un peu long à coder, j'ai passé plus de temps sur la première partie que sur la deuxième partie.

    Partie 1 :

    public class Aoc2023s3p1 {
        public static void main(String[] args) {
            try(Scanner in = new Scanner(Aoc2023s3p1.class.getResourceAsStream("res/Aoc2023s3p1.txt"))) {
                    String row;
                    int sum =0;
    
                    List<String> rows = new ArrayList<>();
    
                    while(in.hasNext()) {
                        row = in.nextLine();
                        rows.add(row);
                    }
    
                    for(int x=0;x < rows.size();x++) {
                        sum += check(x, rows);
                    }
    
    
                    System.out.println(sum);
            }
        }
    
        public static record Num(int start, int end, String data) {
        }
    
    
        public static int check(int rowIndex, List<String> rows) {
    
            String row = rows.get(rowIndex);
    
            List<Num> list = new ArrayList<>();
            Integer start = null;
            for(int x=0;x < row.length();x++) {
                int c = row.charAt(x) - '0';
                if(Character.isDigit(row.charAt(x))) {
                    if(start == null) {
                        start = x;
                    }
                } else {
                    if(start != null) {
                    list.add(new Num(start, x, row.substring(start, x)));
                    start = null;
                    }
                }
            }
    
            if(start !=null) {
                list.add(new Num(start, row.length(), row.substring(start)));
            }
    
            int sum = 0;
            for(Num num : list) {
                System.out.println(num);
                if(checkNum(num, rowIndex, rows)) {
                    System.out.println("OK");
                    sum += Integer.parseInt(num.data());
                }
            }
    
            return sum;
        }
    
    
        private static boolean checkNum(Num num, int rowIndex, List<String> rows) {
            int before = num.start-1;
            if(checkCharacter(rowIndex, before, rows)) {
                return true; 
            }
    
            if(checkCharacter(rowIndex, num.end, rows)) {
                return true; 
            }
    
    
            for(int x = num.start-1;x < num.end+1;x++) {
                if(checkCharacter(rowIndex - 1, x, rows)
                        || checkCharacter(rowIndex + 1, x, rows)) {
                    return true;
                }
            }
            return false;
        }
    
        private static boolean checkCharacter(int rowIndex, int colIndex, List<String> rows) {
            if(rowIndex < 0 || rowIndex >= rows.size()) {
                return false;
            }
            String row = rows.get(rowIndex);
    
            if(colIndex < 0 || colIndex >= row.length()) {
                return false;
            }
    
            char c = row.charAt(colIndex);
            if(Character.isDigit(c) || c == '.') {
                return false;
            }
    
            return true;
        }
    
    }

    Pour la partie 2, l'idée est assez simple. J'identifie les engrenages '*' par leurs coordonnées et je stocke sur chaque coordonnée la liste des nombres associés (numsById)

    public class Aoc2023s3p2 {
        public static Map<Coord, List<Num>> numsById = new HashMap<>();
    
        public static void main(String[] args) {
    
            try(Scanner in = new Scanner(Aoc2023s3p2.class.getResourceAsStream("res/Aoc2023s3p1.txt"))) {
                    String row;
    
    
                    List<String> rows = new ArrayList<>();
    
                    while(in.hasNext()) {
                        row = in.nextLine();
                        rows.add(row);
                    }
    
                    for(int x=0;x < rows.size();x++) {
                        check(x, rows);
                    }
    
    
                    int sum =0;
                    for(List<Num> nums: numsById.values()) {
    
                        if(nums.size() <= 1) {
                            continue;
                        }
                        System.out.println("=====");
                        int prod = 1;
                        for(Num num : nums) {
                            prod *= Integer.parseInt(num.data);
                            System.out.println(num.data);
                        }
                        System.out.println("=>" + prod);
                        sum += prod;
                    }
    
                    System.out.println(sum);
            }
        }
    
        public static record Num(int start, int end, String data) {
        }
    
    
        public static void check(int rowIndex, List<String> rows) {
            String row = rows.get(rowIndex);
    
            List<Num> list = new ArrayList<>();
            Integer start = null;
            for(int x=0;x < row.length();x++) {
                int c = row.charAt(x) - '0';
                if(Character.isDigit(row.charAt(x))) {
                    if(start == null) {
                        start = x;
                    }
                } else {
                    if(start != null) {
                    list.add(new Num(start, x, row.substring(start, x)));
                    start = null;
                    }
                }
            }
    
            if(start !=null) {
                list.add(new Num(start, row.length(), row.substring(start)));
            }
    
            for(Num num : list) {
                System.out.println(num);
                if(isGearPart(num, rowIndex, rows)) {
                    System.out.println("OK");
                }
            }
    
    
        }
    
    
        private static boolean isGearPart(Num num, int rowIndex, List<String> rows) {
    
    
            int before = num.start-1;
            checkGear(num, rowIndex, before, rows);
            checkGear(num, rowIndex, num.end, rows);
    
    
            for(int x = num.start-1;x < num.end+1;x++) {
                checkGear(num, rowIndex - 1, x, rows);
                checkGear(num, rowIndex + 1, x, rows);
            }
    
    
    
            return false;
        }
    
    
        public static record Coord(int rowIndex, int colIndex) {
    
        }
    
        private static boolean checkGear(Num num, int rowIndex, int colIndex, List<String> rows) {
            if(rowIndex < 0 || rowIndex >= rows.size()) {
                return false;
            }
            String row = rows.get(rowIndex);
    
            if(colIndex < 0 || colIndex >= row.length()) {
                return false;
            }
    
            char c = row.charAt(colIndex);
            if(c == '*') {
                numsById.computeIfAbsent(new Coord(rowIndex, colIndex),k->new ArrayList<>()).add(num);
    
            }
    
            return false;
        }
    
    }
  • [^] # Re: Plusieurs leaderboards privés ?

    Posté par  . En réponse au journal Advent of code 2023. Évalué à 3.

    Je confirme. On a un leadboard interne à ma boite. Plus celui-ci.

  • [^] # Re: J'y retourne !

    Posté par  . En réponse au journal Advent of code 2023. Évalué à 4.

    J'aurai du te laisser faire la news :-p

  • # Personnellement, je préfère les tomates aux pattates

    Posté par  . En réponse au journal Il est temps que la communauté internationale fasse un choix. Évalué à 2.

    Alors pour moi, une bonne raclette:
    - Bcp de fromages
    - Des Tomates
    - De l'oignon coupé finement.
    - Un gouse d'ail cuite en même que les patates
    - Un peu de patates (pas plus d'une pour moi)
    - Un peu de jambon fumé et du bacon

    Et sinon pour la problématique de l'appareil à Raclette , il y a ceux de GIFI qui se branche les un les autres. Donc tout le monde peut venir avec ses appareils à raclette.

  • # J'adore

    Posté par  . En réponse au journal Grandbrothers. Évalué à 2.

    J'adore :) Merci pour cette belle découverte.

  • # Ça dépend

    Posté par  . En réponse à la dépêche Pétition de Mozilla pour protéger Firefox. Évalué à 1.

    Si, c'est comme dans l'article, c'est à dire:
    - le navigateur récupère une black list du gouvernement , çà me va.

    Par contre, si le système est du type. Quand on consulte un site, on vient demander au site du gouvernement si on a le droit d'y accéder, c'est plus ennuyeux.
    Pour 3 raisons:
    - le gouvernement connaitra ton historique de navigation
    - ça risque de tuer les perf de navigation
    - une ddos sur site , on ne navigue plus

    Après, c'est le genre de feature qui pourra se désactiver. Vu qu'elle ne sera pas appliquable dans tous les pays.

    Après pour l histoiriques de navigation, les antivirus, google, ils ont déjà cette historique avec l antiphishing d activés donc c est plutôt le risque 2 et 3 qui gène

  • # embrace - extend - extinguish

    Posté par  . En réponse au journal Wayland dans windows 10 et 11. Évalué à 2.

    J'ai découvert moi aussi WSL 2 sur Windows. çà me permet de faire tourner un Linux & plein d'instance docker pour mes dev.

    Je n'ai pas encore essayé de faire tourner des apps graphique mais je ne suis pas surpris que çà marche.

    Ce qui me terrifie, c'est la stratégie historique de Microsoft: Embrace - Extend - Extinguish.

    Avec, ils ont réussi à bouffer : OS/2 , Netscape, …

  • [^] # 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.