小町算っぽいやつ

30分プログラム、その106。小町算をやろうとして、挫折したやつ。
元ネタはたぶん、LL魂

ダメな理由。

  • 空白に対応していない
  • 括弧を使ってしまっている

使い方

*Main> mapM_ (putStrLn.show) $take 3 ans
(1.0+(2.0+(3.0+(4.0+(5.0-(6.0+(7.0-(8.0+(9.0*10.0)))))))))
(1.0+(2.0+(3.0+(4.0-(5.0-(6.0+(7.0-(8.0-(9.0*10.0)))))))))
(1.0+(2.0+(3.0*(4.0+(5.0/(6.0/(7.0+(8.0+(9.0+10.0)))))))))

ソースコード

import Data.List
import Control.Monad.List

data Exp =  Exp `Add` Exp |
            Exp `Sub` Exp |
            Exp `Mul` Exp |
            Exp `Div` Exp |
            Number Float

instance Show Exp where
    show (Number a) = show a
    show (a `Add` b) = "("++(show a)++"+"++(show b)++")"
    show (a `Sub` b) = "("++(show a)++"-"++(show b)++")"
    show (a `Mul` b) = "("++(show a)++"*"++(show b)++")"
    show (a `Div` b) = "("++(show a)++"/"++(show b)++")"

-- なんとなくfoldl1っぽい
makeExp :: [Float]->[Exp]
makeExp [x] = [Number x]
makeExp (x:xs) = do op <- [Add,Sub,Mul,Div]
                    xs' <- makeExp xs
                    return $ (Number x) `op` xs'

eval :: Exp -> Float
eval (Number x) = x
eval (a `Add` b) = (eval a) + (eval b)
eval (a `Sub` b) = (eval a) - (eval b)
eval (a `Mul` b) = (eval a) * (eval b)
eval (a `Div` b) = (eval a) / (eval b)

komachi target xs = do exp <- makeExp xs
                       guard $ eval exp == target
                       return exp
ans = komachi 100 [1..10]