Project Euler 93

http://projecteuler.net/index.php?section=problems&id=93


演算子の配列は、

operators = [ (+), (-), (*), (/) ]

けれど、実際の演算は、

op = (+)
n = op 1 2  -- 3

と、前置にしなければならない。
0割りを回避するところで、演算子が(/)かどうかを直接判定する方法がわからなくて(型が指定されていないから?)、しかたなくインデックスにした。

import Data.List
import Ratio
import qualified Data.Set as S

operators = [ (+), (-), (*), (/) ]

consecutive_length a = f b where
        f [p,q] = if p + 1 == q then 2 else 1
        f (p:q:ps) = if p + 1 == q then 1 + (f (q:ps)) else 1
        b = S.toList s
        s :: S.Set Int
        s = S.fromList [ floor r | c <- permutations a,
                                   r <- g c, denominator r == 1 && r > 0 ]
        g :: [Ratio Int] -> [Ratio Int]
        g [d] = [d]
        g a = [ op p q | (ps,qs) <- h [] a,
                         p <- g ps, q <- g qs,
                         (k, op) <- zip [0..3] operators, q /= 0 || k /= 3 ]
        h ps [q] = []
        h ps (q:qs) = (ps ++ [q],qs):(h (ps ++ [q]) qs)

to_number a = floor (foldl (\x y -> x * 10 + y) 0 a)

combinations a 0 = [[]]
combinations a n = concat (map (\e -> map (e:)
            (combinations (filter (>e) a) (n - 1))) a)

longer x y = if snd x >= snd y then x else y
a = [ (to_number a, consecutive_length a) | a <- combinations [0..9] 4 ]
main = print (fst (foldr longer (0,0) a))