{- Copyright 2012 Ken Takusagawa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} {-# LANGUAGE ScopedTypeVariables #-} module Main where { import System.Environment(getArgs); import Control.Monad(guard); import Text.Printf; main :: (IO ()); main = (getArgs >>= (\lambda_case_var ->case lambda_case_var of { ["nothing"] -> (return ()); [n] -> ((mapM_ ans)((filter (not . bad_expr))((filter ok_commutative)(list_expr_of_complexity(Complexity(read(n))))))); _ -> (putStrLn "need max complexity") })); euler_constant :: Double; euler_constant = (exp 1); phi :: Double; phi = ((/) ((+) 1 (sqrt 5)) 2); data Expr = E | Pi | Phi | TwoPi | InvPhi | Zero | Unity | Two | Add Expr Expr | Sub Expr Expr | Mul Expr Expr | Div Expr Expr | Pow Expr Expr | Root Expr Expr | Log Expr Expr deriving (Show, Ord, Eq); evalop :: (Double -> Double -> Double) -> Expr -> Expr -> (Maybe Double); evalop op x y = (do { (jx :: Double) <- (eval x); (jy :: Double) <- (eval y); (return (op jx jy)); }); loglimit :: Double; loglimit = ((*) 1023 (log 2)); eval :: Expr -> (Maybe Double); eval e = (case e of { E -> (return euler_constant); Pi -> (return pi); Phi -> (return phi); TwoPi -> (return ((*) 2 pi)); InvPhi -> (return ((/) 1 phi)); Zero -> (return 0); Unity -> (return 1); Two -> (return 2); (Add x y) -> (evalop (+) x y); (Sub x y) -> (evalop (-) x y); (Mul x y) -> (evalop (*) x y); (Div x y) -> (do { (jy :: Double) <- (eval y); (guard ((/=) 0 jy)); (jx :: Double) <- (eval x); (return ((/) jx jy)); }); (Pow mx my) -> (do { (x :: Double) <- (eval mx); (y :: Double) <- (eval my); (guard ((<=) 0 x)); (guard ((<) ((*) y (log x)) loglimit)); (return ((**) x y)); }); (Root base expo) -> (eval (Pow base (eReciprocal expo))); (Log mbase mx) -> (do { (x :: Double) <- (eval mx); (base :: Double) <- (eval mbase); (guard ((<) 0 x)); (guard ((<) 0 base)); (guard ((/=) 1 base)); (return ((/) (log x) (log base))); }) }); leaf :: ([] Expr); leaf = [E, Pi, Phi, TwoPi, InvPhi, Zero, Unity, Two]; newtype Complexity = Complexity Integer deriving (Show); list_expr_of_complexity :: Complexity -> ([] Expr); list_expr_of_complexity n = (case n of { (Complexity 0) -> []; (Complexity 1) -> leaf; _ -> (do { ([False, True] >>= (\lambda_case_var ->case lambda_case_var of { False -> (do { f <- one_arg; x <- (list_expr_of_complexity (pred_complexity n)); (return (f x)); }); True -> (do { f <- two_arg; first <- (enum_complexity (pred_complexity n)); x <- (list_expr_of_complexity first); y <- (list_expr_of_complexity (subtract_complexity (pred_complexity n) first)); (return (f x y)); }) })); }) }); enum_complexity :: Complexity -> ([] Complexity); enum_complexity (Complexity cmax) = ((map Complexity)((enumFromTo 0)(cmax))); subtract_complexity :: Complexity -> Complexity -> Complexity; subtract_complexity (Complexity x) (Complexity y) = (Complexity ((-) x y)); pred_complexity :: Complexity -> Complexity; pred_complexity (Complexity x) = (Complexity (pred x)); listn :: Complexity -> ([] Expr); listn n = (concatMap list_expr_of_complexity (enum_complexity n)); one_arg :: ([] (Expr -> Expr)); one_arg = [eSqrt, eSqr, eNegate, eReciprocal, eDouble]; eSqrt :: Expr -> Expr; eSqrt x = (Root x Two); eSqr :: Expr -> Expr; eSqr x = (Pow x Two); eNegate :: Expr -> Expr; eNegate x = (Sub Zero x); eReciprocal :: Expr -> Expr; eReciprocal x = (Div Unity x); eDouble :: Expr -> Expr; eDouble x = (Mul Two x); two_arg :: ([] (Expr -> Expr -> Expr)); two_arg = [Add, Sub, Mul, Div, Pow, Root, Log]; ans :: Expr -> (IO ()); ans e = (case (eval e) of { Nothing -> (return ()); (Just x) -> (case True of { True -> (putStrLn ((printf "%.6f" x) ++ " " ++ (show e))); _ -> (return ()) }) }); clock :: Double -> Bool; clock x = ((&&) ((<) 1 x) ((<) x 13)); ok_commutative :: Expr -> Bool; ok_commutative e = (let { twook :: (Expr -> Expr -> Bool); twook = (two_boilerplate ok_commutative (&&)) } in (case e of { E -> True; Pi -> True; Phi -> True; TwoPi -> True; InvPhi -> True; Zero -> True; Unity -> True; Two -> True; (Add x y) -> ((&&) ((<=) x y) (twook x y)); (Mul x y) -> ((&&) ((<=) x y) (twook x y)); (Sub x y) -> (twook x y); (Div x y) -> (twook x y); (Root x y) -> (twook x y); (Log x y) -> (twook x y); (Pow x y) -> (twook x y) })); bad_denominator :: Expr -> Bool; bad_denominator e = (case e of { Phi -> True; InvPhi -> True; Unity -> True; Zero -> True; (Div _ _) -> True; _ -> False }); bad_expr_inner :: Expr -> Bool; bad_expr_inner e1 = (let { two_bad :: Expr -> Expr -> Bool; two_bad x y = (two_boilerplate bad_expr_inner (||) x y); bad_log :: Expr -> Expr -> Bool; bad_log base e = (case e of { (Mul x y) -> (two_bad (Log base x) (Log base y)); (Div x y) -> (two_bad (Log base x) (Log base y)); (Pow x _) -> (bad_expr_inner (Log base x)); _ -> False }) } in (case e1 of { E -> False; Pi -> False; Phi -> False; TwoPi -> False; InvPhi -> False; Zero -> False; Unity -> False; Two -> False; (Add (Sub x y) (Sub fy fx)) | ((&&) ((==) x fx) ((==) y fy)) -> True ; (Add _ (Log InvPhi _)) -> True; (Add (Log x Phi) (Log y InvPhi)) | ((==) x y) -> True ; (Add Pi Pi) -> True; (Add Unity Unity) -> True; (Add _ Zero) -> True; (Add Zero _) -> True; (Add x y) -> ((||) (two_bad x y) ((==) x y)); (Sub _ (Sub _ _)) -> True; (Sub InvPhi Phi) -> True; (Sub Phi InvPhi) -> True; (Sub Pi TwoPi) -> True; (Sub _ Zero) -> True; (Sub Two Unity) -> True; (Sub x y) -> ((||) (two_bad x y) ((==) x y)); (Mul Zero _) -> True; (Mul _ Zero) -> True; (Mul Unity _) -> True; (Mul _ Unity) -> True; (Mul Phi InvPhi) -> True; (Mul x y) -> (or [(two_bad x y), ((==) x y)]); (Div _ Zero) -> True; (Div Zero _) -> True; (Div _ Unity) -> True; (Div _ Phi) -> True; (Div TwoPi Pi) -> True; (Div Pi TwoPi) -> True; (Div _ InvPhi) -> True; (Div x y) -> (or [(two_bad x y), ((==) x y), (bad_denominator y)]); (Pow Zero _) -> True; (Pow Unity _) -> True; (Pow _ Zero) -> True; (Pow _ Unity) -> True; (Pow (Root _ x) y) | ((==) x y) -> True ; (Pow (Pow _ _) _) -> True; (Pow x y) -> (or [(two_bad x y)]); (Root Zero _) -> True; (Root Unity _) -> True; (Root _ Unity) -> True; (Root _ Phi) -> True; (Root _ InvPhi) -> True; (Root _ (Div _ _)) -> True; (Root x y) -> (or [(two_bad x y)]); (Log _ Unity) -> True; (Log Phi InvPhi) -> True; (Log InvPhi Phi) -> True; (Log x y) -> (or [(two_bad x y), ((==) x y), (bad_log y x), (bad_log x y)]) })); bad_expr :: Expr -> Bool; bad_expr e = (bad_expr_inner(e)); two_boilerplate :: (a -> b) -> (b -> b -> b) -> a -> a -> b; two_boilerplate process join x y = (join (process x) (process y)) }