Prolog - Constraints - Light-Up/Akari

1.5k views Asked by At

I'm trying to solve a Light-Up puzzle and I'm having troubles nailing down the constraints.

My main predicate is:

akari(Rows, Size) :-
   length(Rows, Size), maplist(length_list(Size), Rows),
   append(Rows, Board),
   domain(Board, 0, 2),
   processRows(Rows, Rows, 0-0, Size),
   % transpose(Rows, Columns),
   % processRows(Columns, Columns, 0-0, Size),
   labeling([], Board),
   write(Board), nl,
   printBoard(Board, Size).

The Rows are in a form of a matrix, for example, a case with every free square:

start :-
   akari([[_,_,_],
          [_,_,_],
          [_,_,_]], 3).

To process every row I use:

processRows([], _Board, _Row-_Col, _Size).
processRows([H|T], Board, Row-Col, Size) :-
   processRow(H, Board, Row-Col, Size, []),
   NewRow is Row + 1,
   processRows(T, Board, NewRow-0, Size).

processRow([], _Board, _Row-_Col, _Size, _VarList).
processRow([H|T], _Board, _Row-Col, _Size, _VarList) :-
   H == 2,
   NewCol is Col + 1,
   processRow(T, Board, Row-NewCol, Size, []).          
processRow([H|T], Board, Row-Col, Size, VarList) :-
   gatherLeft(Board, Row-Col, Row-Col, Size, VarList).
   NewCol is Col + 1,
   processRow(T, Board, Row-NewCol, Size, []).

So I go through each element of the matrix, and I gather, starting with gatherLeft - which summons the other cardinal gathers, Right, Up and Down - the row and column of the square I'm processing. The idea is that each intersection of row and column - a cross, if you will - can one have at most one lightbulb.

But if I do something like this:

count2([],0).           
count2([H|T], Count) :-
   H #= 1 #<=> C,
   count2(T, C2),
   Count #= C + C2.

Or this sum(VarList, #=<, 1)

My intent is "Each cross can have at most one lightbulb", but I end up selecting every space and I end up saying "The whole board can have at most one light". And I end up with an empty board.

Edit

For posterity, the solution I came up with was is:

Every square can have at most one light, so sum([H], #=<, 1).

Taking a square, it's column and row can have at most one light, so sum(Row, #=<, 1).

The neighborhood of a square must have at least one light, so sum(VarList, #>=, 1).

It now appears to be working.

0

There are 0 answers