SolitaireBitSet.java [src/java/m/example/solitaire] Revision:   Date:
package m.example.solitaire;

import csip.utils.CheckPointing;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;

/**
 *
 * @author od
 */
public class SolitaireBitSet {

  static final int FROM = 0;
  static final int OVER = 1;
  static final int TO = 2;

  static final int[][] MOVES = new int[][]{
    {0, 2, 5},
    {0, 1, 3},
    {1, 4, 8},
    {1, 3, 6},
    {2, 5, 9},
    {2, 4, 7},
    {3, 1, 0},
    {3, 4, 5},
    {3, 7, 12},
    {3, 6, 10},
    {4, 8, 13},
    {4, 7, 11},
    {5, 9, 14},
    {5, 8, 12},
    {5, 4, 3},
    {5, 2, 0},
    {6, 3, 1},
    {6, 7, 8},
    {7, 4, 2},
    {7, 8, 9},
    {8, 7, 6},
    {8, 4, 1},
    {9, 8, 7},
    {9, 5, 2},
    {10, 6, 3},
    {10, 11, 12},
    {11, 7, 4},
    {11, 12, 13},
    {12, 8, 5},
    {12, 13, 14},
    {12, 11, 10},
    {12, 7, 3},
    {13, 12, 11},
    {13, 8, 4},
    {14, 13, 12},
    {14, 9, 5}
  };


  static void init() {
    boards = 0;
    solutions = new int[15];
  }

  static int boards = 0;
  static int[] solutions = new int[15];

  static class Board {

    BitSet board;
    int from;
    int to;
    Board prev;


    Board(BitSet board, int from, int to, Board prev) {
      this.board = board;
      this.from = from;
      this.to = to;
      this.prev = prev;
      boards++;
    }


    Board jump(int from, int over, int to) {
      if (board.get(from) && board.get(over) && !board.get(to)) {
        BitSet b = (BitSet) board.clone();
        b.set(from, false);
        b.set(over, false);
        b.set(to, true);
        return new Board(b, from, to, this);
      }
      return null;
    }


    List<Board> allJumps() {
      List<Board> bs = new ArrayList<>();
      Board b;
      for (int[] mv : MOVES) {
        if ((b = jump(mv[FROM], mv[OVER], mv[TO])) != null)
          bs.add(b);
      }
      return bs;
    }


    int getCount() {
      return (int) board.stream().count();
    }


    @Override
    public String toString() {
      return new StringBuffer().append(from)
          .append('\u2192').append(to).toString();
    }

  }

  static void solve(Board b) {
    List<Board> moves = b.allJumps();
    if (moves.isEmpty()) {
      // no more moves
      // if (b.getCount() == 1)
      //   System.out.println(allMoves(b));

      solutions[b.getCount()]++;
      return;
    }

    for (Board board : moves) {
      solve(board);
    }
  }


  static StringBuffer allMoves(Board b) {
    if (b.prev == null)
      return new StringBuffer();
    return allMoves(b.prev).append(b).append(", ");
  }


  // layout
  // 
  //       x
  //      x x
  //     x _ x
  //    x x x x
  //   x x x x x
  //
  //        0
  //       1 2
  //      3 4 5
  //     6 7 8 9 
  // 10 11 12 13 14
  //
  public static void main(String[] args) {
    CheckPointing cp = new CheckPointing();
    cp.check("start");
    for (int i = 0; i < 15; i++) {
      m(i);
    }
    cp.check("done");
    System.out.println(cp);
  }


  static BitSet fromArr(boolean[] bo) {
    BitSet b = new BitSet(bo.length);
    for (int i = 0; i < bo.length; i++) {
      b.set(i, bo[i]);
    }
    return b;
  }


  public static void m(int i) {

    boolean[] initialBoard = new boolean[]{
      true,
      true, true,
      true, true, true,
      true, true, true, true,
      true, true, true, true, true
    };

    initialBoard[i] = false;

    init();
    Board b = new Board(fromArr(initialBoard), 0, 0, null);
    solve(b);
//    cp.check("solve");

    System.out.println("start: " + i);
    System.out.println("# of Solutions per remaining pins (0..14): " + Arrays.toString(solutions));
    System.out.println("total # Solutions: " + Arrays.stream(solutions).sum());
    System.out.println("# of 'One remaining pin' Solutions: " + solutions[1]);
    System.out.println("% of 'One remaining pin' per total: " + (double) solutions[1] / (double) Arrays.stream(solutions).sum());
    System.out.println("Boards created on the way: " + boards);
    System.out.println();
//    cp.check("print");
//    System.out.println(cp);
  }

}