Solitaire.java [src/java/m/example/solitaire] Revision: Date:
package m.example.solitaire;
import csip.utils.CheckPointing;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author od
*/
public class Solitaire {
static final int FROM = 0;
static final int OVER = 1;
static final int TO = 2;
static final int[][] JUMPS = {
{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}
};
int numBoards = 0;
int[] solutions = new int[15];
boolean[] initialBoard = {
true,
true, true,
true, true, true,
true, true, true, true,
true, true, true, true, true
};
int missing;
public Solitaire(int missing) {
initialBoard[missing] = false;
this.missing = missing;
}
static class Board {
boolean[] board;
int from;
int to;
Board prev;
Board(boolean[] board, int from, int to, Board prev) {
this.board = board;
this.from = from;
this.to = to;
this.prev = prev;
}
Board jump(int from, int over, int to) {
if (board[from] && board[over] && !board[to]) {
boolean b[] = (boolean[]) board.clone();
b[from] = b[over] = false;
b[to] = true;
return new Board(b, from, to, this);
}
return null;
}
List<Board> allJumps() {
List<Board> bs = new LinkedList<>();
Board b;
for (int[] j : JUMPS) {
if ((b = jump(j[FROM], j[OVER], j[TO])) != null)
bs.add(b);
}
return bs;
}
int getCount() {
int count = 0;
for (boolean pin : board) {
if (pin)
count++;
}
return count;
}
@Override
public String toString() {
return new StringBuffer().append(from)
.append('\u2192').append(to).toString();
}
}
void solve(Board b) {
List<Board> boards = b.allJumps();
if (boards.isEmpty()) {
// no more moves
// if (b.getCount() == 1)
// System.out.println(allMoves(b));
solutions[b.getCount()]++;
return;
}
numBoards += boards.size();
for (Board b1 : boards) {
solve(b1);
}
}
void solveAll() {
solve(new Board(initialBoard, 0, 0, null));
}
StringBuffer allMoves(Board b) {
if (b.prev == null)
return new StringBuffer();
return allMoves(b.prev).append(b).append(", ");
}
public void stats() {
System.out.println("Start pos: " + missing);
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]
/ Arrays.stream(solutions).sum());
System.out.println("# Boards: " + numBoards);
System.out.println();
}
// layout
//
// x
// x x
// x _ x
// x x x x
// x x x x x
//
// Board position ids (for moves):
//
// 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 missing = 0; missing < 15; missing++) {
Solitaire s = new Solitaire(missing);
s.solveAll();
s.stats();
}
cp.check("done");
System.out.println(cp);
}
}