Difference between revisions of "FP Laboratory 2/en"

From Marek Běhálek Wiki
Jump to navigation Jump to search
(Updating to match new version of source page)
(Updating to match new version of source page)
 
(3 intermediate revisions by the same user not shown)
Line 60: Line 60:
  
 
Implement following functions:
 
Implement following functions:
* Function that computes a factorial of a given number.
+
* Function that computes a factorial of a given number. <div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/WHkBFQIHmsw]]</div>
 
<syntaxhighlight lang="Haskell">factorial :: Int -> Int</syntaxhighlight>
 
<syntaxhighlight lang="Haskell">factorial :: Int -> Int</syntaxhighlight>
 +
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> factorial 5
 +
120
 +
</syntaxhighlight>
  
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
Line 76: Line 81:
 
factorial'' n = if n==0 then 1 else n * factorial'' (n-1)
 
factorial'' n = if n==0 then 1 else n * factorial'' (n-1)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
  
* Function that computes n-th number in Fibonacci sequence.
+
* Function that computes n-th number in Fibonacci sequence. <div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/GBxb_cFQG14]]</div>
 
<syntaxhighlight lang="Haskell">fib :: Int -> Int</syntaxhighlight>
 
<syntaxhighlight lang="Haskell">fib :: Int -> Int</syntaxhighlight>
 +
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> fib 5     
 +
8
 +
</syntaxhighlight>
 +
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
<syntaxhighlight lang="Haskell">
Line 93: Line 105:
 
   tmp x a b = tmp (x-1) b (a+b)
 
   tmp x a b = tmp (x-1) b (a+b)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
 
* Function that checks if a year is a leap-year (divisible without remainder by 4 and it is not divisible by 100. If it is divisible by 400, it is a leap-year).
 
* Function that checks if a year is a leap-year (divisible without remainder by 4 and it is not divisible by 100. If it is divisible by 400, it is a leap-year).
 
<syntaxhighlight lang="Haskell">leapYear :: Int -> Bool</syntaxhighlight>
 
<syntaxhighlight lang="Haskell">leapYear :: Int -> Bool</syntaxhighlight>
 +
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> leapYear 2000
 +
True
 +
*Main> leapYear 2020
 +
True
 +
*Main> leapYear 2100
 +
False
 +
*Main> leapYear 2019
 +
False
 +
</syntaxhighlight>
 +
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
<syntaxhighlight lang="Haskell">
Line 107: Line 132:
 
             | otherwise = x `mod` 4 == 0
 
             | otherwise = x `mod` 4 == 0
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
Line 114: Line 140:
 
max3 :: Int -> Int -> Int -> Int
 
max3 :: Int -> Int -> Int -> Int
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> max2 5 8
 +
8
 +
*Main> max3 5 8 4
 +
8
 +
</syntaxhighlight>
 +
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
<syntaxhighlight lang="Haskell">
Line 123: Line 156:
 
max3 x y z = (x `max2` y) `max2` z
 
max3 x y z = (x `max2` y) `max2` z
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
 
* Term combination is a selection of items from a collection, such that (unlike permutations) the order of elements in this selection does not matter. Compute the number of possible combinations if we are taking k things from the collection of n things.  
 
* Term combination is a selection of items from a collection, such that (unlike permutations) the order of elements in this selection does not matter. Compute the number of possible combinations if we are taking k things from the collection of n things.  
 
<syntaxhighlight lang="Haskell">combinations :: Int -> Int -> Int</syntaxhighlight>
 
<syntaxhighlight lang="Haskell">combinations :: Int -> Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> combinations 8 5
 +
56
 +
</syntaxhighlight>
 +
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<syntaxhighlight lang="Haskell">
 
<syntaxhighlight lang="Haskell">
Line 139: Line 178:
 
combinations' n k = fromIntegral(factorial n) `div` fromIntegral(factorial k * factorial (n-k))
 
combinations' n k = fromIntegral(factorial n) `div` fromIntegral(factorial k * factorial (n-k))
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
Line 146: Line 186:
 
f x y = let a = x + y
 
f x y = let a = x + y
 
         in a * a
 
         in a * a
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> numberOfRoots 1 4 2
 +
2
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 154: Line 198:
 
                       in if d<0 then 0 else if d == 0 then 1 else 2
 
                       in if d<0 then 0 else if d == 0 then 1 else 2
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
  
* Implement a function that computes greatest common divider for two given numbers.
+
* Implement a function that computes greatest common divider for two given numbers. <div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/uNs9Zqetu7k]]</div>
 
<syntaxhighlight lang="Haskell">gcd' :: Int -> Int -> Int</syntaxhighlight>
 
<syntaxhighlight lang="Haskell">gcd' :: Int -> Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> gcd' 30 18
 +
6
 +
</syntaxhighlight>
  
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
Line 171: Line 220:
 
gcd2 a b = gcd2 b (a `mod` b)
 
gcd2 a b = gcd2 b (a `mod` b)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
  
* Implement a function that compute, if a given number is a prime number.
+
* Implement a function that compute, if a given number is a prime number. <div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/XSc8qjd4StQ]]</div>
 
<syntaxhighlight lang="Haskell">isPrime :: Int -> Bool</syntaxhighlight>
 
<syntaxhighlight lang="Haskell">isPrime :: Int -> Bool</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> isPrime 7
 +
True
 +
</syntaxhighlight>
  
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
Line 186: Line 240:
 
                   | otherwise = isPrimeTest n (x-1)
 
                   | otherwise = isPrimeTest n (x-1)
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/WRUF28416]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>
 +
 +
== Additional exercises ==
 +
* Define a function that returns true iff all three arguments are different.
 +
 +
<syntaxhighlight lang="Haskell">threeDifferent :: Int -> Int -> Int -> Bool</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> threeDifferent 4 5 6
 +
True
 +
*Main> threeDifferent 6 5 6
 +
False
 +
</syntaxhighlight>
 +
 +
* Define a function that returns true iff all four arguments are equal.
 +
 +
<syntaxhighlight lang="Haskell">fourEqual :: Int -> Int -> Int -> Int-> Bool</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> fourEqual 4 5 6 7
 +
False
 +
*Main> fourEqual 4 4 4 4
 +
True
 +
</syntaxhighlight>
 +
 +
* Define a function that computes the average of three integers.
 +
 +
<syntaxhighlight lang="Haskell">averageThree :: Int -> Int -> Int -> Float</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> averageThree 4 10 20
 +
11.333333
 +
</syntaxhighlight>
 +
 +
* Define a function that returns how many of its inputs are larger than their average value.
 +
 +
<syntaxhighlight lang="Haskell">howManyAboveAverage :: Int -> Int -> Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> howManyAboveAverage 5 5 5
 +
0
 +
*Main> howManyAboveAverage 10 50 50
 +
2
 +
</syntaxhighlight>
 +
 +
* Using the multiplication over the integer numbers, implement a recursive function that realizes the n-th power of an integer number.
 +
<syntaxhighlight lang="Haskell">power :: Int -> Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> power 2 3                   
 +
8
 +
*Main> power 4 2
 +
16
 +
*Main> power 4 3
 +
64
 +
</syntaxhighlight>
 +
 +
* Using the addition over the integer numbers, implement a recursive function that realizes the multiplication of integer numbers.
 +
<syntaxhighlight lang="Haskell">mult :: Int -> Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> mult 4 5
 +
20
 +
*Main> mult 4 9
 +
36
 +
*Main> mult 4 0
 +
0
 +
</syntaxhighlight>
 +
 +
* Define a recursive function that computes the remainder of integer division.
 +
<syntaxhighlight lang="Haskell">mod' :: Int -> Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> mod' 40 7
 +
5
 +
*Main> mod' 30 5
 +
0
 +
*Main> mod' 20 7
 +
6
 +
</syntaxhighlight>

Latest revision as of 08:38, 19 September 2023

Types

  • Using the GHCi command :info, learn the type of the following functions (and operators): +, sqrt, succ, max
  • Get the information about the data type of following expressions and evaluate them. it is possible using the command :type. You can switch this option on for all commands by :set +t (removing by :unset +t).
5 + 8 
3 * 5 + 8
2 + 4
sqrt 16 
succ 6
succ 7
pred 9
pred 8
sin (pi / 2)
truncate pi
round 3.5
round 3.4 
floor 3.7 
ceiling 3.3
mod 10 3
odd 3
  • At presentations, we have spoken about some basic types: Int, Double, Bool, Char. For each of previous expressions assign them the most appropriate of these basic data types. You can verify your guess by using ::. For example, for the first expression, let's assume it is Int. We can cast the result to integer and get the following result.
Prelude> :type (5 + 8) :: Int
(5 + 8) :: Int :: Int

If we try incorrect conversion to Char, we get the following result.

Prelude> :type (5 + 8) :: Char

<interactive>:1:2: error:
    * No instance for (Num Char) arising from a use of `+'
    * In the expression: (5 + 8) :: Char

For this expression, also the type Double works.

Prelude> :type (5 + 8) :: Double
(5 + 8) :: Double :: Double

Reasoning about types

For following expression, try to determine:

  • if the expression's type is correct;
  • what will be the type of the result;
  • what will be the result;
  • put the expression into the interpreter, and verify your claims.
5.9/7
(floor 5.9)/7
floor 5.9/7
fromIntegral floor 5.9/7
fromIntegral (floor 5.9)/7
div (floor 5.9) 7
(floor 5.9) div 7
(floor 5.9) `div` 7
mod 10/2 3
mod (floor (10/2)) 3

Simple functions

Implement following functions:

  • Function that computes a factorial of a given number.
    Video logo.png
factorial :: Int -> Int
*Main> factorial 5
120
factorial  :: Int -> Int
factorial  0 = 1
factorial  n = n * factorial  (n-1)

factorial'  :: Int -> Int
factorial' n | n==0 = 1
             | otherwise = n * factorial'' (n-1)

factorial''  :: Int -> Int        
factorial'' n = if n==0 then 1 else n * factorial'' (n-1)
Try it!
  • Function that computes n-th number in Fibonacci sequence.
    Video logo.png
fib :: Int -> Int
*Main> fib 5      
8
fib :: Int->Int
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

fib' :: Int -> Int
fib' n = tmp n 1 1 where
  tmp 0 a _ = a 
  tmp x a b = tmp (x-1) b (a+b)
Try it!
  • Function that checks if a year is a leap-year (divisible without remainder by 4 and it is not divisible by 100. If it is divisible by 400, it is a leap-year).
leapYear :: Int -> Bool
*Main> leapYear 2000
True
*Main> leapYear 2020
True
*Main> leapYear 2100
False
*Main> leapYear 2019
False
leapYear :: Int -> Bool
leapYear x = x `mod` 4 == 0 && x `mod` 100 /= 0 || x `mod` 400 == 0

leapYear' :: Int -> Bool
leapYear' x | x `mod` 400 == 0 = True
            | x `mod` 100 == 0 = False
            | otherwise = x `mod` 4 == 0
Try it!
  • Implement two functions that returns a maximum from 2 respectively 3 given parameters.
max2 :: Int -> Int -> Int
max3 :: Int -> Int -> Int -> Int
*Main> max2 5 8
8
*Main> max3 5 8 4
8
max2 :: Int -> Int -> Int
max2 x y | x >= y = x
         |otherwise = y

max3 :: Int -> Int -> Int -> Int
max3 x y z = (x `max2` y) `max2` z
Try it!
  • Term combination is a selection of items from a collection, such that (unlike permutations) the order of elements in this selection does not matter. Compute the number of possible combinations if we are taking k things from the collection of n things.
combinations :: Int -> Int -> Int
*Main> combinations 8 5
56
factorial  :: Int -> Int
factorial  0 = 1
factorial  n = n * factorial  (n-1)

combinations :: Int -> Int -> Int
combinations n k = factorial n `div` (factorial k * factorial (n-k))

combinations' :: Int -> Int -> Int
combinations' n k = fromIntegral(factorial n) `div` fromIntegral(factorial k * factorial (n-k))
Try it!
  • Implement a function that computes the number of solutions for a quadratic equation. This quadratic equation will be given using standard coefficients: a, b, c.
numberOfRoots :: Int -> Int -> Int -> Int
-- To simplify the solution, let construct can be used
f x y = let a = x + y
        in a * a
*Main> numberOfRoots 1 4 2
2
numberOfRoots :: Int -> Int -> Int -> Int
numberOfRoots a b c = let d = b*b - 4 * a *c
                      in if d<0 then 0 else if d == 0 then 1 else 2
Try it!
  • Implement a function that computes greatest common divider for two given numbers.
    Video logo.png
gcd' :: Int -> Int -> Int
*Main> gcd' 30 18
6
gcd' :: Int -> Int -> Int
gcd' a b | a > b = gcd' (a-b) b
         | a < b = gcd' a (b-a)
         | a==b = a

gcd2 :: Int -> Int -> Int         
gcd2 a 0 = a
gcd2 a b = gcd2 b (a `mod` b)
Try it!
  • Implement a function that compute, if a given number is a prime number.
    Video logo.png
isPrime :: Int -> Bool
*Main> isPrime 7
True
isPrime :: Int -> Bool
isPrime 1 = False
isPrime y = isPrimeTest y (y-1) where
  isPrimeTest _ 1 = True 
  isPrimeTest n x | n `mod` x ==0 = False
                  | otherwise = isPrimeTest n (x-1)
Try it!

Additional exercises

  • Define a function that returns true iff all three arguments are different.
threeDifferent :: Int -> Int -> Int -> Bool
*Main> threeDifferent 4 5 6
True
*Main> threeDifferent 6 5 6
False
  • Define a function that returns true iff all four arguments are equal.
fourEqual :: Int -> Int -> Int -> Int-> Bool
*Main> fourEqual 4 5 6 7
False
*Main> fourEqual 4 4 4 4
True
  • Define a function that computes the average of three integers.
averageThree :: Int -> Int -> Int -> Float
*Main> averageThree 4 10 20
11.333333
  • Define a function that returns how many of its inputs are larger than their average value.
howManyAboveAverage :: Int -> Int -> Int -> Int
*Main> howManyAboveAverage 5 5 5
0
*Main> howManyAboveAverage 10 50 50 
2
  • Using the multiplication over the integer numbers, implement a recursive function that realizes the n-th power of an integer number.
power :: Int -> Int -> Int
*Main> power 2 3                    
8
*Main> power 4 2
16
*Main> power 4 3
64
  • Using the addition over the integer numbers, implement a recursive function that realizes the multiplication of integer numbers.
mult :: Int -> Int -> Int
*Main> mult 4 5
20
*Main> mult 4 9
36
*Main> mult 4 0
0
  • Define a recursive function that computes the remainder of integer division.
mod' :: Int -> Int -> Int
*Main> mod' 40 7
5
*Main> mod' 30 5
0
*Main> mod' 20 7
6