Search code examples
prologclpfd

Solving Instant Insanity in PROLOG but i always get "NO"


i currently write a Solver for the Basic Instant-Insanity. My program tells me alltime "NO" as it cant find a solution for my problem and i am to confused to find a fail. Can anyone provide me some help? Even a simple tip can be enough. Thanks alot!

ps: i am using GNU Prolog 1.4.5

pps : solutionnormal(l) should print me l with the cube list in it.

   /*
         |   |
         | 3 |
     -----------------
     | 5 | 1 | 6 | 2 |
     -----------------
         |   |
         | 4 |
   numeration of grid faces, for our problem is 1,2,5,6 interesting   
*/
%basecubes
cube(1,[r,w,w,b,r,g]).
cube(2,[r,b,w,g,b,w]).
cube(3,[r,g,b,b,g,w]).
cube(4,[r,r,r,b,w,g]).  

%possible rotations
rotate(S, [X1,X2,X3,X4,X5,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X3,X2,X5,X4,X6,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X5,X2,X6,X4,X1,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X6,X2,X1,X4,X3,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).    
rotate(S, [X6,X1,X4,X5,X3,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X4,X1,X3,X5,X2,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X3,X1,X2,X5,X6,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X2,X1,X6,X5,X4,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X2,X6,X5,X3,X4,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X5,X6,X4,X3,X1,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X4,X6,X1,X3,X2,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X1,X6,X2,X3,X5,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X5,X4,X3,X2,X1,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X3,X4,X1,X2,X6,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X1,X4,X6,X2,X5,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X6,X4,X5,X2,X3,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X6,X5,X2,X1,X3,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X2,X5,X3,X1,X4,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X3,X5,X4,X1,X6,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X4,X5,X6,X1,X2,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X2,X3,X1,X6,X4,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X1,X3,X4,X6,X5,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X4,X3,X5,X6,X2,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
rotate(S, [X5,X3,X2,X6,X1,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).

%my list
l([cube1,cube2,cube3,cube4]).
%solutionnormal().
solutionnormal([cube1,cube2,cube3,cube4]) :- 
   getfaces([cube1,cube2,cube3,cube4],1,L1), frontdiff(L1),
   getfaces([cube1,cube2,cube3,cube4],2,L2), backdiff(L2),
   getfaces([cube1,cube2,cube3,cube4],5,L5), leftdiff(L5),
   getfaces([cube1,cube2,cube3,cube4],6,L6), rightdiff(L6),
   cube1(1, cube1),
   rotate(2, cube2),
   rotate(3, cube3),
   rotate(4, cube4).
%get a list of faces on this side
getfaces([C1,C2,C3,C4], X, List) :-
   List = [fd_nth(C1, X),fd_nth(C2,X),fd_nth(C3,X),fd_nth(C4,X)].

%all diff for list
frontdiff(L1) :- fd_all_different(L1).

backdiff(L2) :- fd_all_different(L2).

leftdiff(L5) :- fd_all_different(L5).

rightdiff(L6) :- fd_all_different(L6).

Solution

  • Unfortunately I can't use gprolog at the moment (it's a long story)... but it seems to me that you have to rotate the cubes before and then check the faces.

    I mean... something as

    rotate(1, C1), % rotation of cube1 (needed? you can use directly cube1 instead?)
    rotate(2, C2), % rotation of cube2
    rotate(3, C3), % rotation of cube3
    rotate(4, C4), % rotation of cube4
    getfaces([C1, C2, C3, C4], 1, L1), frontdiff(L1),
    getfaces([C1, C2, C3, C4], 2, L2), backdiff(L2),
    getfaces([C1, C2, C3, C4], 5, L5), leftdiff(L5),
    getfaces([C1, C2, C3, C4], 6, L6), rightdiff(L6).
    

    Off topic: I don't see the need of frontdiff/1, backdiff/1, leftdiff/1, rightdiff/1 as aliases of fd_all_different/1

    It seems to me that is a lot clearer to use fd_all_diff/1 directly

    rotate(1, C1),
    rotate(2, C2),
    rotate(3, C3),
    rotate(4, C4),
    getfaces([C1, C2, C3, C4], 1, L1), fd_all_different(L1),
    getfaces([C1, C2, C3, C4], 2, L2), fd_all_different(L2),
    getfaces([C1, C2, C3, C4], 5, L5), fd_all_different(L5),
    getfaces([C1, C2, C3, C4], 6, L6), fd_all_different(L6).
    

    -- EDIT --

    I add a full compiling, with the following command

    swipl --goal=main --stand_alone=true -o test -c test.pl
    

    SWI-prolog example for a Linux platform.

    The test.pl file contains

    %:- initialization(main).
    :- use_module(library(clpfd)).
    
    %basecubes
    cube(1, [1,2,2,3,1,4]).
    cube(2, [1,3,2,4,3,2]).
    cube(3, [1,4,3,3,4,2]).
    cube(4, [1,1,1,3,2,4]).  
    
    %possible rotations
    rotate(S, [X1,X2,X3,X4,X5,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X3,X2,X5,X4,X6,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X5,X2,X6,X4,X1,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X6,X2,X1,X4,X3,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).    
    rotate(S, [X6,X1,X4,X5,X3,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X4,X1,X3,X5,X2,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X3,X1,X2,X5,X6,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X2,X1,X6,X5,X4,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X2,X6,X5,X3,X4,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X5,X6,X4,X3,X1,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X4,X6,X1,X3,X2,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X1,X6,X2,X3,X5,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X5,X4,X3,X2,X1,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X3,X4,X1,X2,X6,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X1,X4,X6,X2,X5,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X6,X4,X5,X2,X3,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X6,X5,X2,X1,X3,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X2,X5,X3,X1,X4,X6]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X3,X5,X4,X1,X6,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X4,X5,X6,X1,X2,X3]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X2,X3,X1,X6,X4,X5]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X1,X3,X4,X6,X5,X2]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X4,X3,X5,X6,X2,X1]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    rotate(S, [X5,X3,X2,X6,X1,X4]) :- cube(S, [X1,X2,X3,X4,X5,X6]).
    
    %get a list of faces on this side
    getfaces([C1, C2, C3, C4], X, [Y1, Y2, Y3, Y4]) :-
      nth1(X, C1, Y1), nth1(X, C2, Y2), nth1(X, C3, Y3), nth1(X, C4, Y4).
    
    main :-
      rotate(1, C1), rotate(2, C2), rotate(3, C3), rotate(4, C4),
      getfaces([C1, C2, C3, C4], 1, L1), all_distinct(L1),
      getfaces([C1, C2, C3, C4], 2, L2), all_distinct(L2),
      getfaces([C1, C2, C3, C4], 5, L5), all_distinct(L5),
      getfaces([C1, C2, C3, C4], 6, L6), all_distinct(L6),
      writeln(L1), writeln(L2), writeln(L5), writeln(L6),
      writeln("ok"),
      halt(0).
    
    main :-
      halt(1).
    

    and the output, executing ./test, is

    [4,3,2,1]
    [2,3,4,1]
    [2,1,3,4]
    [1,2,4,3]
    ok