• # 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());
     }
     }
    }