Task: Solve triangle solitare puzzle





Java: import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

public class IQPuzzle {

    public static void main(String[] args) {
        System.out.printf("  ");
        for ( int start = 1 ; start < Puzzle.MAX_PEGS ; start++ ) {
            System.out.printf("  %,6d", start);
        }
        System.out.printf("%n");
        for ( int start = 1 ; start < Puzzle.MAX_PEGS ; start++ ) {
            System.out.printf("%2d", start);
            Map<Integer,Integer> solutions = solve(start);    
            for ( int end = 1 ; end < Puzzle.MAX_PEGS ; end++ ) {
                System.out.printf("  %,6d", solutions.containsKey(end) ? solutions.get(end) : 0);
            }
            System.out.printf("%n");
        }
        int moveNum = 0;
        System.out.printf("%nOne Solution:%n");
        for ( Move m : oneSolution ) {
            moveNum++;
            System.out.printf("Move %d = %s%n", moveNum, m);
        }
    }
    
    private static List<Move> oneSolution = null;
    
    private static Map<Integer, Integer> solve(int emptyPeg) {
        Puzzle puzzle = new Puzzle(emptyPeg);
        Map<Integer,Integer> solutions = new HashMap<>();
        Stack<Puzzle> stack = new Stack<Puzzle>();
        stack.push(puzzle);
        while ( ! stack.isEmpty() ) {
            Puzzle p = stack.pop();
            if ( p.solved() ) {
                solutions.merge(p.getLastPeg(), 1, (v1,v2) -> v1 + v2);
                if ( oneSolution == null ) {
                    oneSolution = p.moves;
                }
                continue;
            }
            for ( Move move : p.getValidMoves() ) {
                Puzzle pMove = p.move(move);
                stack.add(pMove);
            }
        }
        
        return solutions;
    }
    
    private static class Puzzle {
        
        public static int MAX_PEGS = 16;
        private boolean[] pegs = new boolean[MAX_PEGS];  
        
        private List<Move> moves;

        public Puzzle(int emptyPeg) {
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                pegs[i] = true;
            }
            pegs[emptyPeg] = false;
            moves = new ArrayList<>();
        }

        public Puzzle() {
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                pegs[i] = true;
            }
            moves = new ArrayList<>();
        }

        private static Map<Integer,List<Move>> validMoves = new HashMap<>(); 
        static {
            validMoves.put(1, Arrays.asList(new Move(1, 2, 4), new Move(1, 3, 6)));
            validMoves.put(2, Arrays.asList(new Move(2, 4, 7), new Move(2, 5, 9)));
            validMoves.put(3, Arrays.asList(new Move(3, 5, 8), new Move(3, 6, 10)));
            validMoves.put(4, Arrays.asList(new Move(4, 2, 1), new Move(4, 5, 6), new Move(4, 8, 13), new Move(4, 7, 11)));
            validMoves.put(5, Arrays.asList(new Move(5, 8, 12), new Move(5, 9, 14)));
            validMoves.put(6, Arrays.asList(new Move(6, 3, 1), new Move(6, 5, 4), new Move(6, 9, 13), new Move(6, 10, 15)));
            validMoves.put(7, Arrays.asList(new Move(7, 4, 2), new Move(7, 8, 9)));
            validMoves.put(8, Arrays.asList(new Move(8, 5, 3), new Move(8, 9, 10)));
            validMoves.put(9, Arrays.asList(new Move(9, 5, 2), new Move(9, 8, 7)));
            validMoves.put(10, Arrays.asList(new Move(10, 6, 3), new Move(10, 9, 8)));
            validMoves.put(11, Arrays.asList(new Move(11, 7, 4), new Move(11, 12, 13)));
            validMoves.put(12, Arrays.asList(new Move(12, 8, 5), new Move(12, 13, 14)));
            validMoves.put(13, Arrays.asList(new Move(13, 12, 11), new Move(13, 8, 4), new Move(13, 9, 6), new Move(13, 14, 15)));
            validMoves.put(14, Arrays.asList(new Move(14, 13, 12), new Move(14, 9, 5)));
            validMoves.put(15, Arrays.asList(new Move(15, 14, 13), new Move(15, 10, 6)));
        }
        
        public List<Move> getValidMoves() {
            List<Move> moves = new ArrayList<Move>();
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                if ( pegs[i] ) {
                    for ( Move testMove : validMoves.get(i) ) {
                        if ( pegs[testMove.jump] && ! pegs[testMove.end] ) {
                            moves.add(testMove);
                        }
                    }
                }
            }
            return moves;
        }

        public boolean solved() {
            boolean foundFirstPeg = false;
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                if ( pegs[i] ) {
                    if ( foundFirstPeg ) {
                        return false;
                    }
                    foundFirstPeg = true;
                }
            }
            return true;
        }
        
        public Puzzle move(Move move) {
            Puzzle p = new Puzzle();
            if ( ! pegs[move.start] || ! pegs[move.jump] || pegs[move.end] ) {
                throw new RuntimeException("Invalid move.");
            }
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                p.pegs[i] = pegs[i];
            }
            p.pegs[move.start] = false;
            p.pegs[move.jump] = false;
            p.pegs[move.end] = true;
            for ( Move m : moves ) {
                p.moves.add(new Move(m.start, m.jump, m.end));
            }
            p.moves.add(new Move(move.start, move.jump, move.end));
            return p;
        }
        
        public int getLastPeg() {
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                if ( pegs[i] ) {
                    return i;
                }
            }
            throw new RuntimeException("ERROR:  Illegal position.");
        }
        
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("[");
            for ( int i = 1 ; i < MAX_PEGS ; i++ ) {
                sb.append(pegs[i] ? 1 : 0);
                sb.append(",");
            }
            sb.setLength(sb.length()-1);            
            sb.append("]");
            return sb.toString();
        }
    }
    
    private static class Move {
        int start;
        int jump;
        int end;
        
        public Move(int s, int j, int e) {
            start = s; jump = j; end = e;
        }
        
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("{");
            sb.append("s=" + start);
            sb.append(", j=" + jump);
            sb.append(", e=" + end);
            sb.append("}");
            return sb.toString();
        }
    }

}



Python: 


def DrawBoard(board):
  peg = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  for n in xrange(1,16):
    peg[n] = '.'
    if n in board:
      peg[n] = "%X" % n
  print "     %s" % peg[1]
  print "    %s %s" % (peg[2],peg[3])
  print "   %s %s %s" % (peg[4],peg[5],peg[6])
  print "  %s %s %s %s" % (peg[7],peg[8],peg[9],peg[10])
  print " %s %s %s %s %s" % (peg[11],peg[12],peg[13],peg[14],peg[15])



def RemovePeg(board,n):
  board.remove(n)


def AddPeg(board,n):
  board.append(n)


def IsPeg(board,n):
  return n in board



JumpMoves = { 1: [ (2,4),(3,6) ],  
              2: [ (4,7),(5,9)  ],
              3: [ (5,8),(6,10) ],
              4: [ (2,1),(5,6),(7,11),(8,13) ],
              5: [ (8,12),(9,14) ],
              6: [ (3,1),(5,4),(9,13),(10,15) ],
              7: [ (4,2),(8,9)  ],
              8: [ (5,3),(9,10) ],
              9: [ (5,2),(8,7)  ],
             10: [ (9,8) ],
             11: [ (12,13) ],
             12: [ (8,5),(13,14) ],
             13: [ (8,4),(9,6),(12,11),(14,15) ],
             14: [ (9,5),(13,12)  ],
             15: [ (10,6),(14,13) ]
            }

Solution = []



def Solve(board):
  
  if len(board) == 1:
    return board 
  
  for peg in xrange(1,16): 
    if IsPeg(board,peg):
      movelist = JumpMoves[peg]
      for over,land in movelist:
        if IsPeg(board,over) and not IsPeg(board,land):
          saveboard = board[:] 
          RemovePeg(board,peg)
          RemovePeg(board,over)
          AddPeg(board,land) 

          Solution.append((peg,over,land))

          board = Solve(board)
          if len(board) == 1:
            return board
        
          board = saveboard[:] 
          del Solution[-1] 
  return board




def InitSolve(empty):
  board = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
  RemovePeg(board,empty_start)
  Solve(board)


empty_start = 1
InitSolve(empty_start)

board = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
RemovePeg(board,empty_start)
for peg,over,land in Solution:
  RemovePeg(board,peg)
  RemovePeg(board,over)
  AddPeg(board,land) 
  DrawBoard(board)
  print "Peg %X jumped over %X to land on %X\n" % (peg,over,land)