diff --git a/wk5/elm.json b/wk5/elm.json new file mode 100644 index 0000000..ce2a08d --- /dev/null +++ b/wk5/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.3" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/wk5/src/HighOrder.elm b/wk5/src/HighOrder.elm new file mode 100644 index 0000000..f6bc31a --- /dev/null +++ b/wk5/src/HighOrder.elm @@ -0,0 +1,65 @@ +module HighOrder exposing (..) + +{- + Higher order functions + Dimitar Byalkov and Kaloyan Stoykov +-} + +repeatUntil: (a -> Bool) -> (a -> a) -> a -> a +repeatUntil p f init = + let + fResult = f init + in + if not(p fResult) then + repeatUntil p f fResult + else + fResult + +double: Int -> Int +double a = + a * 2 + +above100: Int -> Bool +above100 x = + x > 100 + +aboveN: Int -> (Int -> Bool) +aboveN n = + ((<=) n) + +log: Int -> Int -> Int +log base result = + if result == base then + 1 + else + log base ((repeatUntil (aboveN result) (\x -> base * x) base) + // base) + 1 + +myCollatz: List Int -> List Int +myCollatz values = + case values of + [] -> + [] + x :: _ -> + if modBy 2 x == 0 then + x // 2 :: values + else + (3 * x + 1) :: values + +myPredicate: List Int -> Bool +myPredicate vals = + case vals of + [] -> + False + x :: _ -> + x == 1 + +-- Tests + +testCollatzEven: Bool +testCollatzEven = repeatUntil myPredicate myCollatz [24] == + [1,2,4,8,16,5,10,3,6,12,24] + +testCollatzOdd: Bool +testCollatzOdd = repeatUntil myPredicate myCollatz [19] == + [1,2,4,8,16,5,10,20,40,13,26,52,17,34,11,22,44,88,29,58,19] \ No newline at end of file diff --git a/wk5/src/Modelling1.elm b/wk5/src/Modelling1.elm new file mode 100644 index 0000000..df942d7 --- /dev/null +++ b/wk5/src/Modelling1.elm @@ -0,0 +1,114 @@ +module Modelling1 exposing (..) + +{- + Modelling Math Functions (part 1) + Dimitar Byalkov and Kaloyan Stoykov +-} + +type Function + = Poly Function Int + | Mult Function Function + | Div Function Function + | Plus Function Function + | Minus Function Function + | Const Int + | X + +print: Function -> String +print f = + case f of + X -> + "x" + Const val -> + String.fromInt val + Poly func val -> + "(" ++ print func ++ " ^ " ++ String.fromInt val ++ ")" + Mult func1 func2 -> + "(" ++ print func1 ++ " * " ++ print func2 ++ ")" + Div func1 func2 -> + "(" ++ print func1 ++ " / " ++ print func2 ++ ")" + Plus func1 func2 -> + "(" ++ print func1 ++ " + " ++ print func2 ++ ")" + Minus func1 func2 -> + "(" ++ print func1 ++ " - " ++ print func2 ++ ")" + +eval: Float -> Function -> Float +eval num f = + case f of + X -> + num + Const val -> + toFloat val + Poly func val -> + eval num func ^ (toFloat val) + Mult func1 func2 -> + eval num func1 * eval num func2 + Div func1 func2 -> + eval num func1 / eval num func2 + Plus func1 func2 -> + eval num func1 + eval num func2 + Minus func1 func2 -> + eval num func1 - eval num func2 + +-- Graph line drawing function +graphLine: Function -> Int -> Int -> Int -> String +graphLine func x ymin ymax = + let + -- value of f(x) + funcValue = round (eval (toFloat x) func) + -- number of points on the line + ySpan = abs ymin + abs ymax + in + -- Check if the value of f(x) is in the specified range + if (funcValue > ymin) && (funcValue < ymax) then + stringFill (funcValue - ymin) "*" ++ stringFill (ySpan - (funcValue - ymin)) "-" + else if (funcValue > ymin) then + stringFill ySpan "*" + else + stringFill ySpan "-" + +-- Recursive function to create a string of specified characters with a given length +stringFill: Int -> String -> String +stringFill n sym = + if (n <= 0) then + "" + else + sym ++ stringFill (n - 1) sym + +-- xmin < xmax; ymin < ymax +graph: Function -> Int -> Int -> Int -> Int -> String +graph func xmin xmax ymin ymax = + -- Check if range is not possible + if xmin > xmax || ymin > ymax then + "Error: Range is negative" + else if xmin == xmax then + graphLine func xmin ymin ymax + else + graphLine func xmin ymin ymax ++ "\n" ++ graph func (xmin + 1) xmax ymin ymax + +testPrint: Bool +testPrint = print (Plus (Mult (Plus (Const 3) X) (Minus X (Poly X 5))) (Const 2)) == "(((3 + x) * (x - (x ^ 5))) + 2)" + +testEval: Bool +testEval = eval 2 (Plus (Mult (Plus (Const 3) X) (Minus X (Poly X 5))) (Const 2)) == -148 + +testGraph1: Bool +testGraph1 = graph (Plus (Minus (Poly (Minus (Div X (Const 5)) (Const 1)) 4) (Poly (Plus (Div X (Const -2)) (Const 2)) 2)) (Const 6)) -10 20 -10 10 == + "********************\n********************\n********************\n*******************-\n**************------\n************--------\n**********----------\n**********----------\n***********---------\n************--------\n*************-------\n**************------\n***************-----\n****************----\n****************----\n****************----\n***************-----\n**************------\n************--------\n**********----------\n********------------\n******--------------\n****----------------\n**------------------\n*-------------------\n**------------------\n***-----------------\n*******-------------\n*************-------\n********************\n********************" + +-- for reference 3x2-graph.png +testGraph2: Bool +testGraph2 = graph (Mult (Const 3) (Poly X 2)) -5 5 -1 10 == "***********\n***********\n***********\n***********\n****-------\n*----------\n****-------\n***********\n***********\n***********\n***********" + +testEmptyParams: Bool +testEmptyParams = graph (Mult (Const 3) (Poly X 2)) 0 0 0 0 == "" + +testSingleLine: Bool +testSingleLine = graph (Mult (Const 3) (Poly X 2)) 1 1 -1 10 == "****-------" + + +testInvalidArgs: Bool +testInvalidArgs = graph X 2 1 2 1 == "Error: Range is negative" + +testAllGraphs : List Bool +testAllGraphs = [testGraph1, testGraph2, testEmptyParams, testSingleLine, testInvalidArgs] \ No newline at end of file diff --git a/wk5/src/Modelling2.elm b/wk5/src/Modelling2.elm new file mode 100644 index 0000000..2f69608 --- /dev/null +++ b/wk5/src/Modelling2.elm @@ -0,0 +1,93 @@ +module Modelling2 exposing (..) +import Modelling1 exposing (..) +import HighOrder exposing (..) + +{- + Modelling Math Functions (part 2) + Dimitar Byalkov and Kaloyan Stoykov +-} + +f: Function +f = Plus (Mult (Plus (Const 3) X) (Minus X (Poly X 5))) (Const 2) + +derivative: Function -> Function +derivative func = + case func of + -- constant + Const _ -> + Const 0 + -- X + X -> + Const 1 + -- sum + Plus left right -> + Plus (derivative left) (derivative right) + -- difference + Minus left right -> + Minus (derivative left) (derivative right) + -- product + Mult left right -> + Plus (Mult (derivative left) right) (Mult left (derivative right)) + -- quotient + Div left right -> + Div (Minus (Mult (derivative left) right) (Mult left (derivative right))) + (Poly right 2) + -- power + Poly X right -> + Mult (Const right) (Poly X (right - 1)) + Poly left right -> + Poly (derivative left) right + +simplify: Function -> Function +simplify func = + -- tries to simplify until no further simplification is possible + repeatUntil (\x -> x == simplifyHelp x) simplifyHelp func + +simplifyHelp: Function -> Function +simplifyHelp func = + case func of + -- arithmetics + Mult (Const left) (Const right) -> + Const (left * right) + Div (Const left) (Const right) -> + Const (left // right) + Plus (Const left) (Const right) -> + Const (left + right) + Minus (Const left) (Const right) -> + Const (left - right) + -- nested addition and subtraction + Poly left 1 -> + left + Poly _ 0 -> + (Const 1) + Poly (Const left) right -> + Const (left ^ right) + Poly left right -> + Poly left right + Mult (Const 1) right -> + right + Mult left (Const 1) -> + left + Mult _ (Const 0) -> + (Const 0) + Div (Const 0) _ -> + (Const 0) + Div left (Const 1) -> + left + Plus left (Const 0) -> + left + Plus (Const 0) right -> + right + Minus left (Const 0) -> + left + -- recursive simplification + Mult left right -> + Mult (simplify left) (simplify right) + Div left right -> + Div (simplify left) (simplify right) + Plus left right -> + Plus (simplify left) (simplify right) + Minus left right -> + Minus (simplify left) (simplify right) + _ -> + func \ No newline at end of file