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