Search code examples
prologsudokuconstraint-satisfaction

Learning Prolog, Sudoku Solver


my problem is: While learning Prolog i wanted to make a NxN Sudoku solver. This solver will get the input like

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

Where some of them might be variables. The solver has to solve that Sudoku. The problem is way smaller:

    firstElementsOf([],_).
    firstElementsOf([[X|_]|Rest2],Y) :-
      firstElementsOf(Rest2,Y2),
      append([X],[Y2],NotFlat),
      flatten(NotFlat,Y).

This should be the beginning of checking, if every column has distinct numbers. The Y from firstElementsOf should contain only the first elements of the given rows. In the Example:

    [1,3,2,4]

Sadly, thanks to append, it always adds another empty space to the Y list. It gives:

    [1,3,2,4,_1320]

Question1: Is there a way to get rid of that _1320?

Question2: Is this even right? Will there be a way to get the 2nd and 3rd elements of the Input with that?


Solution

  • For question 1: I suppose the error is in

    firstElementsOf([],_).
    

    I think should be

    firstElementsOf([],[]).
    

    Off topic: are you sure that you can't simply write the other clause as follows?

    firstElementsOf([[X|_]|Rest2],[X|Y]) :-
      firstElementsOf(Rest2,Y).
    

    For question 2: I propose a more general predicate: the following getPosList/3 with support of getPosElem/3

    getPosElem([H | _], 1, H).
    
    getPosElem([_ | T], Pos, H) :-
      Pos > 1,
      Pm1 is Pos - 1,
      getPosElem(T, Pm1, H).
    
    getPosList([], _, []).
    
    getPosList([H | T], Pos, [E | L]) :-
      getPosElem(H, Pos, E),
      getPosList(T, Pos, L).
    

    It extract a list of all elements in position Pos, so

    getPosList([[1,2,3,4],[3,4,1,2],[2,3,4,1],[4,1,2,3]], 1, L),
    

    it's equivalent to firstElementOf([[1,2,3,4],[3,4,1,2],[2,3,4,1],[4,1,2,3]], L) and extract [1, 3, 2, 4],

    getPosList([[1,2,3,4],[3,4,1,2],[2,3,4,1],[4,1,2,3]], 2, L),
    

    extract [2, 4, 3, 1],

    getPosList([[1,2,3,4],[3,4,1,2],[2,3,4,1],[4,1,2,3]], 3, L),
    

    extract [3, 1, 4, 2],

    getPosList([[1,2,3,4],[3,4,1,2],[2,3,4,1],[4,1,2,3]], 4, L),
    

    extract [4, 2, 1, 3] and

    getPosList([[1,2,3,4],[3,4,1,2],[2,3,4,1],[4,1,2,3]], 5, L),
    

    or a number greather than 5, return false