魔方陣を作ってみる

30分プログラム、その784。魔方陣を作ってみた。
最初はリストモナドでベタ書きしようかと思ったけど

magicSquare = do a <- [1..9]
	         b <- delete a [1..9]
		 c <- delete b $ delete a [1..9]
		 ....
		 guard ...
		 return ...

みたいなひどいことになりそうだったのでやめました、まる。

使い方

*Main> magicSquare
[[[2,7,6],[9,5,1],[4,3,8]],[[2,9,4],[7,5,3],[6,1,8]],
 [[4,3,8],[9,5,1],[2,7,6]],[[4,9,2],[3,5,7],[8,1,6]],
 [[6,1,8],[7,5,3],[2,9,4]],[[6,7,2],[1,5,9],[8,3,4]],
 [[8,1,6],[3,5,7],[4,9,2]],[[8,3,4],[1,5,9],[6,7,2]]]

ソースコード

import Data.List
import Control.Monad.List
shuffle :: [Int] -> [[Int]]

shuffle [] = [[]]
shuffle xs = do y <- xs
                ys <- shuffle (delete y xs)
                return (y:ys)

same :: Eq a => [a] -> Bool
same [] = True
same (x:xs) = all (==x) xs

magicSquare = do [a,b,c,d,e,f,g,h,i] <- shuffle [1..9]
                 guard $ same [
                            a + b + c, d + e + f, g + h + i,
                            a + d + g, b + e + h, c + f + i,
                            a + e + i, c + e + g
                           ]
                 return [[a, b, c],
                         [d, e, f],
                         [g, h, i]]