2012-04-18 3 views
0

Я пытаюсь написать простую программу, которая просто проверяет, является ли входная плата sudoku некорректным; то есть он имеет два одинаковых числа в строке, столбце или «в ящике». У меня нет проблем с частью строк и столбцов - задача довольно прямолинейная, которую я выполняю со следующим кодом (следует отметить, что «0» представляет собой квадрат, который не был заполнен):Создание sudoku 'boxes' из строк - пролог

:- use_module(library(clpfd)). 

%Takes a matrix, determines if any row has repeating numbers 
check([H|T]):- 
    all_diff(H), 
    check(T). 
check([]). 

%takes a list, checks if it contains repetitions other than '0'. 
all_diff([]). 
all_diff([X|Xs]) :- 
    (X = 0 -> 
    all_diff(Xs) 
     ; 
     \+memberchk(X, Xs), 
     all_diff(Xs) 

    ). 

consistent(Rows):- 
    check(Rows),    %verify rows are free of repeats 
    transpose(Rows,Columns), %L1 represents columns 
    check(Columns),   %verify all columns are free of repeats 
     [H|T] = Rows, 
     length(H,M), 
    K is integer(sqrt(M)).  %this will give me dimensions of each box (KxK) 

Тем не менее, я не совсем понимаю, как создать списки, которые будут представлять поля KxK '(где K - квадратный корень длины строки). Я получаю значение K, и я думаю, что я хотел бы сделать что-то в соответствии с разделом row1 в K-подписок, а затем добавить подстроки строк row2 в конец подписок в row1 до тех пор, пока не достигнет строки (K * K).

К сожалению, я действительно не уверен, как это сделать? Есть ли BIP, который я могу использовать, что будет делать что-то в соответствии с тем, чтобы взять список и разбить его на X-списки по всей длине Y?

В противном случае любые идеи? Я знаю крошечный, но о петлях dowhile, и я полагаю, что они могут быть реализованы здесь, но я не совсем уверен, как я это сделаю? Большое спасибо за помощь!

ответ

1

простой, эффективный способ не может использовать индекс арифметических операций и петель:

... 
    Sq = 3, 
    findall(B, (between(1, Sq, R), 
      between(1, Sq, C), 
      block(M, Sq, R, C, B)), Bs). 

cell(M, R,C, V) :- 
    nth1(R,M,Row), nth1(C,Row,V). 

block(M, Sq, R,C, B) :- 
    findall(V, (between(1, Sq, X), 
      between(1, Sq, Y), 
      I is (R-1) * Sq + X, 
      J is (C-1) * Sq + Y, 
      cell(M, I, J, V)), B). 

В documentation библиотеки (clpfd) существует более эффективный способ, ограничивается известным стандартным измерением. Вы можете попытаться обобщить этот код.

Редактировать вот мой тестовый пример: обратите внимание, что матрица это подделка, просто упростите понимание того, где находятся блоки.

q(Bs) :- 
    M = [[1,2,3,4,5,6,7,8,9], 
     [a,b,c,d,_,3,_,8,5], 
     [x,y,z,_,2,_,_,_,_], 
     [u,v,z,e,t,y,_,_,_], 
     [b,b,b,e,t,y,1,_,_], 
     [c,c,c,e,t,y,_,_,_], 
     [5,_,_,_,_,_,_,7,3], 
     [_,_,2,_,1,_,_,_,_], 
     [_,_,_,_,4,_,_,_,9]], 

    Sq = 3, 
    findall(B, (between(1, Sq, R), 
      between(1, Sq, C), 
      block(M, Sq, R, C, B)), Bs). 

cell(M, R,C, V) :- 
    nth1(R,M,Row), nth1(C,Row,V). 

block(M, Sq, R,C, B) :- 
    findall(V, (between(1, Sq, X), 
      between(1, Sq, Y), 
      I is (R-1) * Sq + X, 
      J is (C-1) * Sq + Y, 
      cell(M, I, J, V)), B). 

и тест с помощью следующей команды:

?- q(Bs),maplist(writeln,Bs). 
[1,2,3,a,b,c,x,y,z] 
[4,5,6,d,_G928,3,_G934,2,_G940] 
[7,8,9,_G895,8,5,_G904,_G907,_G910] 
[u,v,z,b,b,b,c,c,c] 
[e,t,y,e,t,y,e,t,y] 
[_G796,_G799,_G802,1,_G808,_G811,_G814,_G817,_G820] 
[5,_G769,_G772,_G775,_G778,2,_G784,_G787,_G790] 
[_G736,_G739,_G742,_G745,1,_G751,_G754,4,_G760] 
[_G706,7,3,_G715,_G718,_G721,_G724,_G727,9] 
Bs = [[1, 2, 3, a, b, c, x, y|...], [4, 5, 6, d, _G928, 3, _G934|...], [7, 8, 9, _G895, 8, 5|...], [u, v, z, b, b|...], [e, t, y, e|...], [_G796, _G799, _G802|...], [5, _G769|...], [_G736|...], [...|...]]. 
+0

Большое спасибо! Мне интересно, однако, если вы, возможно, поможете мне понять, что здесь происходит немного лучше? Кажется, что между всадниками, находящимися в пределах поисковика, возникает какая-то путаница! Однако, похоже, что Bs должен быть списком, содержащим список «блоков» (может быть, я что-то пропустил?), Но он всегда заканчивается как [[], [], [], []] , Любая идея, что может там происходить? Еще раз спасибо за помощь - я очень ценю это! – user1257768

+0

Я добавил тестовый пример: см. Изменение – CapelliC