Learning Prolog, Sudoku Solver

1k views Asked by At

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?

1

There are 1 answers

5
max66 On BEST ANSWER

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