Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package stackexchange;
- import java.util.*;
- /**
- * V W X Y Z [
- * . . U . . .
- * . . . T . .
- * . Q R S . .
- * . P O . . .
- * . . N . . .
- * . . . M L .
- * . . . J K .
- * . . I . . .
- * . . H . . .
- * . G . . . .
- * F E D C B A
- */
- public class TileLabyrinth1 {
- /** NUmber of tiles */
- public static int SIZE = 27;
- /** Groups of tiles belonging to the same "ray". Left, center and right */
- public static String[][] GROUPS =
- { { "AI", "BH", "C", "DG", "E", "F", "J", "KMNP", "LOQ", "R", "SV", "TUW", "X", "Y", "Z", "[" }
- , { "A[", "BKLZ", "CJMSTY", "DHINORUX", "EGPQW", "FV" }
- , { "A", "B", "C", "D", "E", "FGHK", "IJL", "M", "N", "OS", "PRT[", "QZ", "UY", "V", "W", "X" }
- };
- public static int[][][] raysByDir;
- public static String uniqueKey(int[] board){
- StringBuilder sb = new StringBuilder();
- for( int i=0 ; i<board.length ; i++ ){
- sb.append(String.valueOf((char)('A' + i)).repeat(board[i]));
- }
- return sb.toString();
- }
- public static String boardToString(int[] board){
- StringBuilder sb = new StringBuilder();
- for( int i=0 ; i<board.length ; i++ ){
- sb.append((board[i] == 0) ? '.' : (char)('A'+i));
- }
- return sb.toString();
- }
- /** Initialize the rays index by direction */
- public static void initLaby(){
- raysByDir = new int[SIZE][GROUPS.length][];
- for( int iFrom=0 ; iFrom < SIZE ; iFrom++ ){
- for( int dir=0 ; dir<GROUPS.length ; dir++ ){
- int[] rayDir = new int[SIZE];
- int p = 0;
- for( String group : GROUPS[dir] ){
- String[] tiles = group.split("");
- for( String from : tiles ){
- if( from.equals("" + (char)('A'+iFrom)) ){
- for( String to : tiles ){
- if( !from.equals(to) ){
- rayDir[p++] = (char)(to.charAt(0) - 'A');
- }
- }
- }
- }
- }
- raysByDir[iFrom][dir] = Arrays.copyOf(rayDir, p);
- }
- }
- }
- public static boolean[] calcSolid(int[] board){
- boolean[] solid = new boolean[board.length];
- for( int i=0 ; i<6 ; i++ ){
- solid[i] = true;
- }
- for( int i=6 ; i<board.length-6 ; i++ ){
- boolean[] crossDir = new boolean[3];
- for( int dir=0 ; dir<3 ; dir++ ){
- for( int j : raysByDir[i][dir] ){
- crossDir[dir] |= board[j] > 0;
- }
- }
- solid[i] = (crossDir[0]?1:0) + (crossDir[1]?1:0) + (crossDir[2]?1:0) >= 2;
- }
- for( int i=board.length-6 ; i<board.length ; i++ ){
- solid[i] = true;
- }
- return solid;
- }
- public static void printSol(Pos pos){
- List<Pos> solution = new ArrayList<>();
- while( pos != null ){
- solution.add(pos);
- pos = pos.prev;
- }
- Pos prevPos = null;
- for( int s=solution.size() ; s-->0 ; ){
- pos = solution.get(s);
- StringBuilder sb = new StringBuilder();
- if( prevPos == null ){
- sb.append("solution: ");
- } else {
- sb.append(" ");
- for( int i=0 ; i<pos.board.length ; i++ ){
- if( pos.board[i] < prevPos.board[i] ) sb.append((char)('A'+i));
- }
- sb.append(" -> ");
- for( int i=0 ; i<pos.board.length ; i++ ){
- if( pos.board[i] > prevPos.board[i] ) sb.append((char)('A'+i));
- }
- sb.append(": ");
- }
- System.out.println(sb.toString() + boardToString(pos.board));
- prevPos = pos;
- }
- }
- /** Breadth-first search for all positions reachable from the start */
- public static void searchPath(){
- int bestProgress = 0;
- Pos bestPos = null;
- int[] startBoard = new int[] { 1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
- Map<String,Pos> positionsDone = new HashMap<>();
- List<Pos> positionsTodo = new LinkedList<>();
- Pos startPos = new Pos(startBoard, null, 0);
- positionsDone.put(uniqueKey(startBoard), startPos);
- positionsTodo.add(startPos);
- while( !positionsTodo.isEmpty() && bestProgress%100 <= 20 ){
- Pos posFrom = positionsTodo.remove(0);
- int[] board = posFrom.board.clone();
- for( int i = 0 ; i < board.length ; i++ ){
- if( board[i] == 0 ) continue;
- board[i]--;
- boolean[] solid = calcSolid(board);
- boolean valid = true;
- for( int j=0 ; j<board.length ; j++ ){
- valid &= (board[j] == 0 || solid[j]);
- }
- if( valid ){
- int j0 = i;
- while( j0>0 && solid[j0-1] ) j0--;
- int j1 = i;
- while( j1<solid.length-1 && solid[j1+1] ) j1++;
- for( int j = j0 ; j <= j1 ; j++ ){
- if( j == i || !solid[j] ) continue;
- board[j]++;
- Pos newPos = new Pos(board, posFrom, posFrom.dist+1);
- Pos oldPos = positionsDone.get(uniqueKey(board));
- if( oldPos == null || oldPos.dist > newPos.dist ){
- positionsDone.put(uniqueKey(board), newPos);
- positionsTodo.add(newPos);
- int last = -1;
- int first = 0;
- for( int k=0 ; k<board.length ; k++ ){
- if( board[k] != 0 ){
- if( last<0 ) last = k;
- first = k;
- }
- }
- int progress = last*100 + first;
- if( progress > bestProgress ){
- System.out.println("progress " + progress + " todo " + positionsTodo.size() + " done " + positionsDone.size());
- bestProgress = progress;
- bestPos = newPos;
- }
- }
- board[j]--;
- }
- } // if valid
- board[i]++;
- }
- }
- printSol(bestPos);
- }
- public static void main(String[] args) {
- initLaby();
- searchPath();
- }
- static class Pos {
- int[] board;
- Pos prev;
- int dist;
- public Pos(int[] board, Pos prev, int dist){
- this.board = board.clone();
- this.prev = prev;
- this.dist = dist;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement