clegger ([info]clegger) wrote in [info]ru_lambda,
@ 2006-09-27 09:52:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
"Переборные" задачи на 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/download.php/30402/411005/303317/1409/magic-squares.hs
Честно говоря, выглядит для меня страшно. По-моему это должно быть проще...



(Post a new comment)


[info]thesz
2006-09-27 09:51 am UTC (link)
Ну, начнём с того, что в поставке Hugs есть Пролог-на-Хаскеле. ;)

Переборные задачи решать можно следущим способом: генерируешь дерево решений, и отсекаешь неподходящие ветви.

Сейчас пример выдать не могу, сильно лень. ;)

(Reply to this)(Thread)


[info]nealar
2006-09-27 10:31 am UTC (link)
http://www.lexifi.com/Downloads/Hughes.pdf#search=%22whyfp.pdf%22
titled "Why functional programming matters"
Про дерево перебора там хорошо написано.

(Reply to this)(Parent)


[info]_darkus_
2006-09-27 06:44 pm UTC (link)
Это решение на Прологе очень похоже на то, что кто-то изгалялся и пытался перевести функциональный стиль в логический. На Хаскеле эта задача решается в пару-тройку функций. На этом компьютере интерпретатора нет, завтра на работе посмотрю. Но у меня студенты, я помню, на лабораторных работах решали простейшим перебором в несколько строк.

Основная идея перебора в Хаскеле (без углубления в теорию):

[x | x <- xs]


Эта запись обозначает: «список из всех x, взятых из xs»...

(Reply to this)


[info]_adept_
2006-09-28 06:20 am UTC (link)
Например, так:


module Main where

import List (delete)

main = do
mapM_ printM3 magic3

printM3 [a,b,c,d,e,f,g,h,i] = do
print (a,b,c)
print (d,e,f)
print (g,h,i)
print "====="

-- Generate all squares of size N
squares n = gen [1..9] (n*n)
gen digits 1 = [ [d] | d <- digits ]
gen digits n =
[ d:sq | d <- digits
, sq <- gen (delete d digits) (n-1) ]

-- a b c
-- d e f
-- g h i
magic3 =
[ [a,b,c,d,e,f,g,h,i] | [a,b,c,d,e,f,g,h,i] <- squares 3
, fits a b c , fits d e f , fits g h i -- rows
, fits a d g , fits b e h , fits c f i -- cols
, fits a e i , fits c e g -- diags
]

fits x y z = x+y+z == 15

(Reply to this)


[info]clegger
2006-09-29 06:15 am UTC (link)
спасибо огромное всем! разобрался! :-)

(Reply to this)(Thread)


[info]_darkus_
2006-10-02 06:02 pm UTC (link)
Уже, может, неактуально, но я у себя написал на прошлой неделе, а ссылку здесь забыл дать. Тем, не менее: http://users.livejournal.com/_darkus_/266151.html

(Reply to this)(Parent)(Thread)


[info]clegger
2006-10-03 05:52 am UTC (link)
огромное спасибо! :-)

(Reply to this)(Parent)


Create an Account
Forgot your login?
Login w/ OpenID
English • Español • Deutsch • Русский…