| clegger ( @ 2006-09-27 09:52:00 |
"Переборные" задачи на haskell
Подскажите пожалуйста общую схему решения задач перебора на Хаскел. Особенно буду благодарен если с каким-нибудь практическим примером (задача коммивояжора, ферзи, укладка рюкзака) и т.п.
Из всех примеров особо интересует генерация "магических" квадратов. На прологе решается очень эффектно - описываются правила, пролог сам "подбирает" решение. Можно ли на Хаскелл получить подобное:
% Find all 3 by 3 magic squares. 10 times faster!
% d(D) is for digit
d(1). d(2). d(3). d(4). d(5). d(6). d(7). d(8). d(9).
% a row has 3 different digits that add up to 15
row(X,Y,Z):-d(X),d(Y), X=\=Y, Z is 15 - X - Y, d(Z), d(Z),X=\=Z, Y=\=Z.
% was row(X,Y,Z):-d(X),d(Y), X=\=Y, d(Z),X=\=Z, Y=\=Z, X+Y+Z=:=15.
col(X,Y,Z):-X=\=Y, Y=\=Z, X=\=Z, X+Y+Z=:=15.
diag(X,Y,Z):-X=\=Y, Y=\=Z, X=\=Z, X+Y+Z=:=15.
% make sure that there are no other duplicate digits
offdiag(X,Y,Z):-X=\=Y, Y=\=Z, X=\=Z.
printrow(A,B,C):-write(A),write(B),write(C) ,nl.
out(A,B,C,D,E,F,G,H,I):-nl,
printrow(A,B,C),
printrow(D,E,F),
printrow(G,H,I).
go:-go(More).
go(More):-More=more,
row(A,B,C),
row(D,E,F),
G is 15-A-D, H is 15-B-E,
row(G,H,I),
col(A,D,G),col(B,E,H),col(C,F,I),
diag(A,E,I), diag(G,E,C),
offdiag(A,H,F), offdiag(C,D,H),offdiag(G,B,F),offdiag(I,D,B) ,
out(A,B,C,D,E,F,G,H,I).
ЗЫ Погуглил, нашел следующее: http://alioth.debian.org/tracker/downlo ad.php/30402/411005/303317/1409/magic-sq uares.hs
Честно говоря, выглядит для меня страшно. По-моему это должно быть проще...
Подскажите пожалуйста общую схему решения задач перебора на Хаскел. Особенно буду благодарен если с каким-нибудь практическим примером (задача коммивояжора, ферзи, укладка рюкзака) и т.п.
Из всех примеров особо интересует генерация "магических" квадратов. На прологе решается очень эффектно - описываются правила, пролог сам "подбирает" решение. Можно ли на Хаскелл получить подобное:
% Find all 3 by 3 magic squares. 10 times faster!
% d(D) is for digit
d(1). d(2). d(3). d(4). d(5). d(6). d(7). d(8). d(9).
% a row has 3 different digits that add up to 15
row(X,Y,Z):-d(X),d(Y), X=\=Y, Z is 15 - X - Y, d(Z), d(Z),X=\=Z, Y=\=Z.
% was row(X,Y,Z):-d(X),d(Y), X=\=Y, d(Z),X=\=Z, Y=\=Z, X+Y+Z=:=15.
col(X,Y,Z):-X=\=Y, Y=\=Z, X=\=Z, X+Y+Z=:=15.
diag(X,Y,Z):-X=\=Y, Y=\=Z, X=\=Z, X+Y+Z=:=15.
% make sure that there are no other duplicate digits
offdiag(X,Y,Z):-X=\=Y, Y=\=Z, X=\=Z.
printrow(A,B,C):-write(A),write(B),write(C)
out(A,B,C,D,E,F,G,H,I):-nl,
printrow(A,B,C),
printrow(D,E,F),
printrow(G,H,I).
go:-go(More).
go(More):-More=more,
row(A,B,C),
row(D,E,F),
G is 15-A-D, H is 15-B-E,
row(G,H,I),
col(A,D,G),col(B,E,H),col(C,F,I),
diag(A,E,I), diag(G,E,C),
offdiag(A,H,F), offdiag(C,D,H),offdiag(G,B,F),offdiag(I,D,B)
out(A,B,C,D,E,F,G,H,I).
ЗЫ Погуглил, нашел следующее: http://alioth.debian.org/tracker/downlo
Честно говоря, выглядит для меня страшно. По-моему это должно быть проще...