3

how to get all elements of the blocks in prolog? the size can change dynamic in my code, so the blocksize differs, 4x4 = 4 elements, 9x9= 9 elements etc. the blocks are cut into squares, so in 4x4 the horizontal length is round(sqrt(4))= 2 and vertical length of the block is round(sqrt(4)) = 2. and 9x9 ... sqrt(9).. so height and width of the blocks are 3. i need an algorithm to get the elements efficient.

my sudokulists are build up this way:

L=[ [4,3,1,2], [2,1,4,3], [3,4,2,1], [1,2,3,4] ],

so a list, with lists of the rows in sudoku. checking rows and columns is no problem, -> all_different check with rows, transpose the whole List, all_different check with the transposed list.

but because of the dynamic size of the sudoku, i cannot code fix code for the blocks. so anyone any idea? i thought about flatten(L) and working with offsets to get the correct blocks, but it seems pretty hard to do that this way?

please help me!

viktor
  • 31
  • 2

2 Answers2

2

A possible solution goes as follows (assuming you have blocksizexblocksize blocks of size blocksizexblocksize - in standard sudoku all numbers are equal, can be adjusted to match other layouts)

  1. Let a = [],...,[] be a list of blocksize buckets.
  2. Partition each row into blocksize parts.
  3. Put first part into first bucket, second into second, and so on. If you reached last bucket start with first one again.
  4. Flatten out a completely
  5. Partition the result again into blocksizexblocksize blocks

In your example:

L=[ [4,3,1,2], [2,1,4,3], [3,4,2,1], [1,2,3,4] ]
Partitions => [[4,3] [1,2] [2,1] [4,3] [3,4] [2,1] [1,2] [3,4]]
Bucketed => [[4,3] [2,1] [3,4] [1,2]] [[1,2] [4,3] [2,1] [3,4]]
Flattened => [4,3,2,1,3,4,1,2,1,2,4,3,2,1,3,4]
Partitioned => [4,3,2,1], [3,4,1,2], [1,2,4,3], [2,1,3,4]]
Howard
  • 38,639
  • 9
  • 64
  • 83
1

Here's some simple Prolog to transpose a matrix in list-of-lists representation. The idea is to create a new "first row" by pulling the head off each existing row, then recurse on the list of "leftover" tails.

transpose([[ ]|_],[ ]) :- !.
transpose(A,[H|T]) :-
    decap_List(A,H,B),
    transpose(B,T).

decap_List([ ],[ ],[ ]).
decap_List([[H|T]|Rows],[H|Hs],[T|Ts]) :-
    decap_List(Rows,Hs,Ts).

For example:

?- transpose([[1,2,3],[4,5,6],[7,8,9]],X).

X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 

Note however for a generalized sudoku matrix of size K²xK², you also have "all different" entries in each "box" of size KxK tiling the matrix. Using you same design as before, you would also need a predicate to repackage the sudoku matrix into a list of "box" lists.

To do so only requires a further predicate to "partition" a matrix into groups of K rows apiece.

part_K_rows([ ],_,[ ]) :- !.
part_K_rows(A,K,[H|T]) :-
    get_K_rows(A,K,H,B),
    part_K_rows(B,K,T).

get_K_rows(A,0,[ ],A) :- !.
get_K_rows([H|T],K,[H|Z],B),
    J is K-1,
    get_K_rows(T,J,Z,B).

Applying part_K_rows/3 to the original sudoku matrix, then transposing each of the resulting row partitions and applying part_K_rows/3 to each of them will produce the required list of "box" lists.

hardmath
  • 8,753
  • 2
  • 37
  • 65