150 likes | 291 Views
Functional Programming. Universitatea Politehnica Bucuresti 2007-2008 Adina Magda Florea http://turing.cs.pub.ro/fp_08. Lecture No. 11 - cont. How the "Countdown problem" functions work. Evaluating expressions Define an operator: data Op = Add | Sub | Mul | Div Main> :info Op
E N D
Functional Programming Universitatea Politehnica Bucuresti2007-2008 Adina Magda Florea http://turing.cs.pub.ro/fp_08
Lecture No. 11 - cont • How the "Countdown problem" functions work
Evaluating expressions Define an operator: data Op = Add | Sub | Mul | Div Main> :info Op -- type constructor data Op -- constructors: Add :: Op Sub :: Op Mul :: Op Div :: Op
Evaluating expressions Apply an operator: apply :: Op -> Int -> Int -> Int apply Add x y = x + y apply Sub x y = x-y apply Mul x y = x*y apply Div x y = x `div` y Main> apply Div 10 2 5
Decide if the result of applying an operator to two positive numbers is a natural number: valid :: Op -> Int -> Int -> Bool valid Add _ _ = True valid Sub x y = x > y valid Mul _ _ = True valid Div x y = x `mod` y == 0 Main> valid Sub 3 5 False Main> valid Add 2 4 True
Define an expression: data Expr = Val Int | App Op Expr Expr Main> :info Expr -- type constructor data Expr -- constructors: Val :: Int -> Expr App :: Op -> Expr -> Expr -> Expr
Evaluate an expression if the result is a natural number: eval :: Expr -> [Int] eval (Val n) = [n | n>0] eval (App o l r) = [apply o x y | x <- eval l , y <- eval r , valid o x y] Main> eval (Val 1) [1] Main> eval (App Add (Val 1) (Val 2)) [3]
Return a list of all possible ways of choosing zero or more elements from a list: choices :: [a] -> [[a]] choices [ ] = [[ ]] choices (x:xs) = [x:xs | xs <-l] ++ l where l = choices xs Main> choices [1,2] [[1,2],[1],[2],[]] Main> choices [1,2,3] [[1,2,3],[1,2],[1,3],[1],[2,3],[2],[3],[]]
Homework Modify choices so that the result is: Main> choices [1,2] [[1,2],[2,1],[1],[2],[]] In what follows this is the behaviour for choices that we are relying on
Return a list of all values in an expressions: values :: Expr -> [Int] values (Val n) = [n] values (App _ l r) = values l ++ values r Main> values (App Add (Val 1) (Val 2)) [1,2] Main> values (App Add (Val 1) (App Sub (Val 3) (Val 2))) [1,3,2] Main> values (App Add (Val 1) (App Sub (Val 3) (Val 20))) [1,3,20]
Decide if an expression is a solution for a given list of source numbers and a target number: solution :: Expr -> [Int] -> Int -> Bool solution e ns n = elem (values e) (choices ns) && eval e == [n] Main> values (App Add (Val 1) (App Sub (Val 3) (Val 2))) [1,3,2] Main> choices [1,2,3] [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1],[1,2],[2,1],[1,3],[3,1], [1],[2,3],[3,2],[2],[3],[]] Main> elem [1,3,2] (choices [1,2,3]) True Main> solution (App Add (Val 1) (App Sub (Val 3) (Val 2))) [1,3,2] 2 True
Return a list of all possible ways of splitting a list into two non-empty lists: splitaux :: Int -> [a] -> [([a],[a])] splitaux 0 l = [ ] splitaux n l = [(x,y)] ++ splitaux (n-1) l where x = take n l y = drop n l split l = splitaux (length l -1) l Main> split [1,2,3,4] [([1,2,3],[4]),([1,2],[3,4]),([1],[2,3,4])]
Combine two expressions using each operator: combine :: Expr -> Expr -> [Expr] combine l r = [App o l r | o <- [Add, Sub, Mul, Div]] Main> combine (Val 1) (Val 2) ERROR - Cannot find "show" function for: *** Expression : combine (Val 1) (Val 2) *** Of type : [Expr] Homework: write a function that will display an expression of type Expr so that it can be used to display the results of combine [(App Add (Val 1) (Val 2)), (App Sub (Val 1) (Val 2)), (App Mul (Val 1) (Val 2)), (App Div (Val 1) (Val 2))]
Return a list of all possible expressions whose values are a given list of numbers: exprs :: [Int] -> [Expr] exprs [ ] = [ ] exprs [n] = [Val n] exprs ns = [ e | (ls,rs) <- split ns , l <- exprs ls , r <- exprs rs , e <- combine l r ]
Return a list of all possible expressions that solve the countdown problem: solutions :: [Int] -> Int -> [Expr] solutions ns n = [e | ns' <- choices ns , e <- exprs ns' , eval e == [n] ] • choices returns the list ns' of all possible ways of choosing zero or more elements from the list of numbers ns • exprs returns the list e of all possible expressions whose values are the list of numbers ns' • eval evaluates the expression e (uses apply to apply the operator if the application is validated by function valid) • then check if the result e is equal to the natural number n NB. In order to display this list a show function for the Expr type is needed (see homework)