Search code examples
prolog

Magic square prolog


I have this code and I want to refactor a section to be more effecient.

num(1).
num(2).
num(3).
num(4).
num(5).              
num(6).              
num(7).               
num(8).
num(9).



nums(A,B,C,D,E,F,G,H,I):-
      num(A),num(B),num(C),              
      num(D),num(E),num(F),              
      num(G),num(H),num(I),    
      A\==B,A\==C,A\==D,A\==E,A\==F,A\==G,A\==H,A\==I, 
            B\==C,B\==D,B\==E,B\==F,B\==G,B\==H,B\==I, 
                  C\==D,C\==E,C\==F,C\==G,C\==H,C\==I, 
                        D\==E,D\==F,D\==G,D\==H,D\==I, 
                              E\==F,E\==G,E\==H,E\==I, 
                                    F\==G,F\==H,F\==I, 
                                          G\==H,G\==I,
                                                H\==I.

square(A,B,C,D,E,F,G,H,I):-
         nums(A,B,C,D,E,F,G,H,I),
         S1 is A + B + C,
         S2 is D + E + F,
         S3 is G + H + I, 
         S4 is A + D + G,
         S5 is B + E + H,
         S6 is C + F + I,
         S7 is A + E + I,
         S8 is G + E + C,
         S1==S2,S2==S3,S3==S4,S4==S5,S5==S6,S6==S7,S7==S8.   
          
solution([A,B,C,D,E,F,G,H,I]):-square(A,B,C,D,E,F,G,H,I).

The part that I want to reduce is this, I don't know how to use a function and I need to avoid doing something like this where I use a lot of code and instead make a function where I can solve it in a few lines

A\==B,A\==C,A\==D,A\==E,A\==F,A\==G,A\==H,A\==I, 
            B\==C,B\==D,B\==E,B\==F,B\==G,B\==H,B\==I, 
                  C\==D,C\==E,C\==F,C\==G,C\==H,C\==I, 
                        D\==E,D\==F,D\==G,D\==H,D\==I, 
                              E\==F,E\==G,E\==H,E\==I, 
                                    F\==G,F\==H,F\==I, 
                                          G\==H,G\==I,
                                                H\==I.

Solution

  • I'd suggest you use CLP(FD) to solve these kind of problems:

    fd_square(Sol, Sum):-
      Sol=[A,B,C,D,E,F,G,H,I],
      Sol ins 1..9,
      all_distinct(Sol),
      maplist(#=(Sum),
        [
         A + B + C,
         D + E + F,
         G + H + I,
         A + D + G,
         B + E + H,
         C + F + I,
         A + E + I,
         G + E + C
        ]).
    

    Sample run:

    ?- fd_square(Sol, Sum), label(Sol).
    Sol = [2, 7, 6, 9, 5, 1, 4, 3, 8],
    Sum = 15 ;
    Sol = [2, 9, 4, 7, 5, 3, 6, 1, 8],
    Sum = 15 ;
    Sol = [4, 3, 8, 9, 5, 1, 2, 7, 6],
    Sum = 15 ;
    Sol = [4, 9, 2, 3, 5, 7, 8, 1, 6],
    Sum = 15 ;
    Sol = [6, 1, 8, 7, 5, 3, 2, 9, 4],
    Sum = 15 ;
    Sol = [6, 7, 2, 1, 5, 9, 8, 3, 4],
    Sum = 15 ;
    Sol = [8, 1, 6, 3, 5, 7, 4, 9, 2],
    Sum = 15 ;
    Sol = [8, 3, 4, 1, 5, 9, 6, 7, 2],
    Sum = 15 ;
    false.