2

possible quick question here since I'm new to Prolog. I'm trying to convert this code for solving a triangular peg solitaire puzzle into solving a rectangular peg solitaire puzzle. The problem I think I'm facing is trying to figure out how to let the program know it completed the puzzle. Here's what I've got currently:

% Legal jumps along a line.
linjmp([x, x, o | T], [o, o, x | T]).
linjmp([o, x, x | T], [x, o, o | T]).
linjmp([H|T1], [H|T2]) :- linjmp(T1,T2).

% Rotate the board
rotate([[A, B, C, D, E, F],
        [G, H, I, J, K, L],
        [M, N, O, P, Q, R],
        [S, T, U, V, W, X]],
        [[S, M, G, A],
        [T, N, H, B],
        [U, O, I, C],
        [V, P, J, D],
        [W, Q, K, E],
        [X, R, L, F]]).

rotateBack([[A, B, C, D],
            [E, F, G, H],
            [I, J, K, L],
            [M, N, O, P],
            [Q, R, S, T],
            [U, V, W, X]],
            [[D, H, L, P, T, X],
            [C, G, K, O, S, W],
            [B, F, J, N, R, V],
            [A, E, I, M, Q, U]]).

% A jump on some line.
horizjmp([A|T],[B|T]) :- linjmp(A,B).
horizjmp([H|T1],[H|T2]) :- horizjmp(T1,T2).

% One legal jump.
jump(B,A) :- horizjmp(B,A).
jump(B,A) :- rotate(B,BR), horizjmp(BR,BRJ), rotateBack(A,BRJ).
%jump(B,A) :- rotate(BR,B), horizjmp(BR,BRJ), rotate(BRJ,A).

% Series of legal boards.
series(From, To, [From, To]) :- jump(From, To).
series(From, To, [From, By | Rest])
       :- jump(From, By),
         series(By, To, [By | Rest]).

% A solution.
solution(L) :- series([[o, x, x, x, x, x],
                       [x, x, x, x, x, x],
                       [x, x, x, x, x, x],
                       [x, x, x, x, x, x]], L).

The triangular puzzle code required that the user input what the ending table would look like, but I didn't want that. I want this to show any possible solution. The table will always be exactly 6x4. I liked the idea of rotating the grid to continue to simply figure out horizontal jumps, so I changed the rotate function to rotate it's side, and added a RotateBack function to put it back into place. I figured I would have to do this because the grid isn't symmetrical. Since it will always be this size, I figure the simplest way to find the end is to set up a counter that will count how many moves are taken place. Once we hit 22 moves (the max moves possible to clear the whole grid except for 1 peg), then the solution will be a success.

In other words, I think I need to remove this code:

% Series of legal boards.
series(From, To, [From, To]) :- jump(From, To).
series(From, To, [From, By | Rest])
       :- jump(From, By),
         series(By, To, [By | Rest]).

And change it so that it sets up a counter that stops at 22. Any suggestions?

ebohlman
  • 14,795
  • 5
  • 33
  • 35
Nick
  • 25
  • 2
  • 2
  • 6
  • Please note that your `rotate/2` and `rotateBack/2` are essentially the same definition, the only difference is the argument order. So you do not need `rotateBack/2` in Prolog! – false Oct 11 '12 at 14:08

1 Answers1

0

I think you could count the pegs, or better, fail when there are at least 2.

To do it efficiently, should be (untested code)

finished(L) :-
   \+ call_nth(find_peg(L), 2).
find_peg(L) :-
   member(R, L),
   memberchk(R, x).

call_nth/2, as defined in this answer, requires the builtin nb_setval. This is available in SWI-Prolog or Yap.

Community
  • 1
  • 1
CapelliC
  • 59,646
  • 5
  • 47
  • 90