カード

http://d.hatena.ne.jp/a-ki_room/20050823/1124892990
算数オリンピック・広中杯の問題という。

1から12までの数字が書かれたカードが1枚ずつあり、これをA,B,Cの3人に同じ枚数ずつ配る。各人4枚のカードを持つことになる。Aのカードに書かれた数字の和とBのカードに書かれた数字の和が等しく、Bのカードに書かれた数字の積とCのカードに書かれた数字の積が等しいような配り方はどのような配り方か。

最近ネタ切れっぽくて、かわいそう(顔。なんだけれどもこれは比較的それっぽいか。
1から15までのカードの場合はどうか、の拡張も考える。

例によって Haskell で。

gen :: (Int, Int, Int) -> [Int] -> [([Int], [Int], [Int])]
gen (1,0,0) (x:xs) = [([x],[ ],[ ])]
gen (0,1,0) (x:xs) = [([ ],[x],[ ])]
gen (0,0,1) (x:xs) = [([ ],[ ],[x])]
gen (a,b,c) (x:xs) | a < 0 || b < 0 || c < 0 = [ ]
gen (a,b,c) (x:xs)=    (map (\(as,bs,cs) -> ((x:as),bs,cs)) (gen (a-1,b,c) xs))
                    ++ (map (\(as,bs,cs) -> (as,(x:bs),cs)) (gen (a,b-1,c) xs))
                    ++ (map (\(as,bs,cs) -> (as,bs,(x:cs))) (gen (a,b,c-1) xs))
gen _ [ ] = [ ]
filter (\(a,b,c) -> product a == product b && sum b == sum c)$ gen (4,4,4) [1..12]
[([*,*,*,*],[*,*,*,*],[*,*,*,*])]

filter (\(a,b,c) -> product a == product b && sum b == sum c)$ gen (5,5,5) [1..15]
[([*,*,*,*,*],[*,*,*,*,*],[*,*,*,*,*]),
 ([*,*,*,*,*],[*,*,*,*,*],[*,*,*,*,*]),
 ([*,*,*,*,*],[*,*,*,*,*],[*,*,*,*,*]),
 ([*,*,*,*,*],[*,*,*,*,*],[*,*,*,*,*])]

大きなバグもなく10分くらいで書けていい言語だ。*の中身はあててください。