Difference between revisions of "PFP Laboratory 2"

From Marek Běhálek Wiki
Jump to navigation Jump to search
(Created page with "== Simple functions working with list == Implement following functions: * Create a function that computes length of a list. <syntaxhighlight lang="Haskell">length' :: [a] -> I...")
 
Line 216: Line 216:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BEBLH60352]]
 
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BEBLH60352]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
== Advanced functions working with lists == <!--T:1-->
 +
Implement following functions:
 +
 +
* Create a function that takes first n elements of the list.
 +
 +
<syntaxhighlight lang="Haskell">take' :: Int -> [a] -> [a]</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> take' 2 [1,2,3]
 +
[1,2]
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
take' :: Int -> [a] -> [a]
 +
take' 0 _ = []
 +
take' _ [] = []
 +
take' n (x:xs) = x: take' (n-1) xs
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
* Create a function that takes the remaining list after the first n elements.
 +
 +
<syntaxhighlight lang="Haskell">drop' :: Int -> [a] -> [a]</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> drop' 2 [1,2,3]
 +
[3]
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
drop' :: Int -> [a] -> [a]
 +
drop' 0 x = x
 +
drop' _ [] = []
 +
drop' n (_:xs) = drop' (n-1) xs
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
* Create a function that find the smallest element in the list. Consider input restrictions.
 +
 +
<syntaxhighlight lang="Haskell">minimum' :: [a] -> a -- Is this right?</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
 +
*Main> minimum' [1,3,4,0]
 +
0
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
minimum' :: Ord a => [a] -> a
 +
minimum' [x] = x
 +
minimum' (x:y:z) | x < y = minimum' (x:z)
 +
                | otherwise = minimum' (y:z)
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
* Find all integer divisors of a given number.
 +
 +
<div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/8iKGkcOlzpI]]</div>
 +
<syntaxhighlight lang="Haskell">divisors :: Int -> [Int]</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> divisors 32 
 +
[1,2,4,8,16,32]
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
divisors :: Int -> [Int]
 +
divisors n = tmp n where
 +
  tmp 0 = []
 +
  tmp x | n `mod` x == 0 = x: tmp (x-1)
 +
        | otherwise = tmp (x-1)
 +
 +
divisors' :: Int -> [Int]
 +
divisors' n =  filter (\x -> n `mod` x == 0) [1..n]
 +
 +
divisors'' :: Int -> [Int]
 +
divisors'' n =  [x | x<-[1..n], n `mod` x == 0]
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
== Functions working with lists and tuples ==
 +
Implement following functions:
 +
* Create a function that merge two lists into one list of tuples.
 +
 +
<syntaxhighlight lang="Haskell">zipThem:: [a] -> [b] -> [(a,b)]</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> zipThem [1,2,3] "ABCD"
 +
[(1,'A'),(2,'B'),(3,'C')]
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
zipThem:: [a] -> [b] -> [(a,b)]
 +
zipThem (x:xs) (y:ys) = (x,y) : zipThem xs ys
 +
zipThem _ _ = []
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
* Create a function that compute Cartesian product of two vectors.
 +
 +
<syntaxhighlight lang="Haskell">dotProduct :: [a] -> [b] -> [(a,b)]</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> dotProduct [1..4] "ABC"
 +
[(1,'A'),(1,'B'),(1,'C'),(2,'A'),(2,'B'),(2,'C'),(3,'A'),(3,'B'),(3,'C'),(4,'A'),(4,'B'),(4,'C')]
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
dotProduct :: [a] -> [b] -> [(a,b)]
 +
dotProduct [] _ = []
 +
dotProduct (x:xs) ys = tmp ys ++ dotProduct xs ys where
 +
  tmp [] = []
 +
  tmp (b:bs) = (x,b) : tmp bs
 +
 +
dotProduct' :: [a] -> [b] -> [(a,b)] 
 +
dotProduct' xs ys = [(x,y)|x<-xs, y<-ys]
 +
 +
dotProduct'' :: [a] -> [b] -> [(a,b)]
 +
dotProduct'' x y =
 +
  zip (concat (map (replicate (length y)) x))
 +
                    (concat (replicate (length x) y))
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
* Create a function that computes n-th number in the Fibonacci sequence. The function should use tuples in the solution.
 +
 +
<div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/Sge0DXXI36k]]</div>
 +
<syntaxhighlight lang="Haskell">fibonacci :: Int -> Int</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> fibonacci 12
 +
144
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
fibonacci :: Int -> Int
 +
fibonacci n = fst (tmp n) where
 +
  fibStep (a,b) = (b,a+b)
 +
  tmp 0 = (0,1)
 +
  tmp x = fibStep (tmp (x-1))
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
== High-order functions ==
 +
* Create a function that takes a string and converts all characters to upper case letters.
 +
 +
<syntaxhighlight lang="Haskell">allToUpper :: String -> String</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> allToUpper "aAbc"
 +
"AABC"
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
import Data.Char
 +
 +
allToUpper :: String -> String
 +
allToUpper xs = [toUpper x |x<-xs]                   
 +
 +
allToUpper' :: String -> String
 +
allToUpper' xs = map toUpper xs
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 +
</div>
 +
<div style="clear:both"></div>
 +
 +
* Implement the [https://en.wikipedia.org/wiki/Quicksort <code>quicksort</code>] algorithm. As a pivot use always the first element in the list. For dividing the list, use the function <code>filter</code>.
 +
 +
<div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/Sj8cbRv89To]]</div>
 +
<syntaxhighlight lang="Haskell">quicksort :: (Ord a) => [a] -> [a]</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> filter (<5) [1..10]
 +
[1,2,3,4]
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark">
 +
*Main> quicksort [1,5,3,7,9,5,2,1]
 +
[1,1,2,3,5,5,7,9]
 +
</syntaxhighlight>
 +
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
quicksort :: (Ord a) => [a] -> [a]
 +
quicksort [] = []
 +
quicksort (x:xs) = let lp = filter (< x) xs
 +
                      rp = filter (>= x) xs
 +
                  in quicksort lp ++ [x] ++ quicksort rp
 +
</syntaxhighlight>
 +
[[File:Tryit.png|center|60px|Try it!|link=https://rextester.com/BVU17842]]
 
</div>
 
</div>
 
<div style="clear:both"></div>
 
<div style="clear:both"></div>

Revision as of 10:04, 29 September 2022

Simple functions working with list

Implement following functions:

  • Create a function that computes length of a list.
length' :: [a] -> Int
*Main> length' "ABCD"
4
length' :: [a] -> Int
length' []  = 0
length' (_:xs) = 1 + length' xs
Try it!
  • Create a function that sums the list of integers.
Video logo.png
sumIt :: [Int] -> Int
*Main> sumIt [1,2,3]
6
sumIt :: [Int] -> Int
sumIt []  = 0
sumIt (x:xs) = x + sumIt xs
Try it!
  • Create a function that returns the first element in the list.
getHead :: [a] -> a
*Main> getHead [1,2,3]
1
getHead :: [a] -> a
getHead (x:_) = x
Try it!
  • Create a function that returns the last element in the list.
Video logo.png
getLast :: [a] -> a
*Main> getLast [1,2,3]
3
getLast :: [a] -> a
getLast [x] = x
getLast (x:xs) = getLast xs

getLast' :: [a] -> a
getLast' (x:xs) | length xs == 0 = x
                | otherwise = getLast' xs
Try it!
  • Create a function that checks if an element is a member of the list.
isElement :: Eq a => a -> [a] -> Bool
*Main> isElement 2 [1,2,3]
True
isElement :: Eq a => a -> [a] -> Bool
isElement _ [] = False
isElement a (x:xs) | a == x = True 
                   | otherwise = isElement a xs
Try it!
  • Create a function that returns the list without the first element.
getTail :: [a] -> [a]
*Main> getTail [1,2,3]
[2,3]
getTail :: [a] -> [a]                   
getTail (_:xs) = xs
Try it!
  • Create a function that returns the list without the last element.
Video logo.png
getInit :: [a] -> [a]
*Main> getInit [1,2,3]
[1,2]
getInit :: [a] -> [a]
getInit [_] = []
getInit (x:xs) = x : getInit xs
Try it!
  • Create a function that merge two lists into one list.
Video logo.png
combine :: [a] -> [a] -> [a]
*Main> combine [1,2,3] [4,5]
[1,2,3,4,5]
combine :: [a] -> [a] -> [a]
combine [] y = y
combine (x:xs) y = x : combine xs y
Try it!
  • Create a function that finds the maximum in the list of integers.
Video logo.png
max' :: [Int] -> Int
*Main> max' [3,1,7,5]
7
max' :: [Int] -> Int
max' [x] = x
max' (x:y:z) | x > y = max' (x:z)
             | otherwise = max' (y:z)

max'' :: [Int] -> Int
max'' (y:ys) = tmp y ys where
   tmp a [] = a
   tmp a (x:xs) | x > a = tmp x xs 
                |otherwise = tmp a xs
Try it!
  • Create a function that reverse a list.
Video logo.png
reverse' :: [a] -> [a]
*Main> reverse' [3,1,7,5]
[5,7,1,3]
reverse' :: [a] -> [a]             
reverse' [] = []
reverse' (x:xs) = (reverse' xs) ++ [x]

reverse'' :: [a] -> [a] 
reverse'' n = tmp n  []
  where tmp [] ys = ys 
        tmp (x:xs) ys = tmp xs (x:ys)
Try it!
  • Create a function that product scalar multiplication if two vectors.
scalar :: [Int] -> [Int] -> Int
*Main> scalar [1,2,3] [4,5,6]
32
scalar :: [Int] -> [Int] -> Int
scalar [] [] = 0
scalar (x:xs) (y:ys) = x*y + scalar xs ys
Try it!

Advanced functions working with lists

Implement following functions:

  • Create a function that takes first n elements of the list.
take' :: Int -> [a] -> [a]
*Main> take' 2 [1,2,3]
[1,2]
take' :: Int -> [a] -> [a]
take' 0 _ = []
take' _ [] = []
take' n (x:xs) = x: take' (n-1) xs
Try it!
  • Create a function that takes the remaining list after the first n elements.
drop' :: Int -> [a] -> [a]
*Main> drop' 2 [1,2,3]
[3]
drop' :: Int -> [a] -> [a]
drop' 0 x = x
drop' _ [] = []
drop' n (_:xs) = drop' (n-1) xs
Try it!
  • Create a function that find the smallest element in the list. Consider input restrictions.
minimum' :: [a] -> a -- Is this right?
*Main> minimum' [1,3,4,0]
0
minimum' :: Ord a => [a] -> a 
minimum' [x] = x
minimum' (x:y:z) | x < y = minimum' (x:z)
                 | otherwise = minimum' (y:z)
Try it!
  • Find all integer divisors of a given number.
Video logo.png
divisors :: Int -> [Int]
*Main> divisors 32  
[1,2,4,8,16,32]
divisors :: Int -> [Int]
divisors n = tmp n where
  tmp 0 = []
  tmp x | n `mod` x == 0 = x: tmp (x-1)
        | otherwise = tmp (x-1)

divisors' :: Int -> [Int]
divisors' n =  filter (\x -> n `mod` x == 0) [1..n] 

divisors'' :: Int -> [Int]
divisors'' n =  [x | x<-[1..n], n `mod` x == 0]
Try it!

Functions working with lists and tuples

Implement following functions:

  • Create a function that merge two lists into one list of tuples.
zipThem:: [a] -> [b] -> [(a,b)]
*Main> zipThem [1,2,3] "ABCD"
[(1,'A'),(2,'B'),(3,'C')]
zipThem:: [a] -> [b] -> [(a,b)]
zipThem (x:xs) (y:ys) = (x,y) : zipThem xs ys
zipThem _ _ = []
Try it!
  • Create a function that compute Cartesian product of two vectors.
dotProduct :: [a] -> [b] -> [(a,b)]
*Main> dotProduct [1..4] "ABC"
[(1,'A'),(1,'B'),(1,'C'),(2,'A'),(2,'B'),(2,'C'),(3,'A'),(3,'B'),(3,'C'),(4,'A'),(4,'B'),(4,'C')]
dotProduct :: [a] -> [b] -> [(a,b)]
dotProduct [] _ = []
dotProduct (x:xs) ys = tmp ys ++ dotProduct xs ys where
  tmp [] = []
  tmp (b:bs) = (x,b) : tmp bs

dotProduct' :: [a] -> [b] -> [(a,b)]  
dotProduct' xs ys = [(x,y)|x<-xs, y<-ys]

dotProduct'' :: [a] -> [b] -> [(a,b)]
dotProduct'' x y = 
  zip (concat (map (replicate (length y)) x))
                     (concat (replicate (length x) y))
Try it!
  • Create a function that computes n-th number in the Fibonacci sequence. The function should use tuples in the solution.
Video logo.png
fibonacci :: Int -> Int
*Main> fibonacci 12
144
fibonacci :: Int -> Int
fibonacci n = fst (tmp n) where
  fibStep (a,b) = (b,a+b)
  tmp 0 = (0,1)
  tmp x = fibStep (tmp (x-1))
Try it!

High-order functions

  • Create a function that takes a string and converts all characters to upper case letters.
allToUpper :: String -> String
*Main> allToUpper "aAbc"
"AABC"
import Data.Char

allToUpper :: String -> String
allToUpper xs = [toUpper x |x<-xs]                     

allToUpper' :: String -> String
allToUpper' xs = map toUpper xs
Try it!
  • Implement the quicksort algorithm. As a pivot use always the first element in the list. For dividing the list, use the function filter.
Video logo.png
quicksort :: (Ord a) => [a] -> [a]
*Main> filter (<5) [1..10]
[1,2,3,4]
*Main> quicksort [1,5,3,7,9,5,2,1]
[1,1,2,3,5,5,7,9]
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) = let lp = filter (< x) xs
                       rp = filter (>= x) xs
                   in quicksort lp ++ [x] ++ quicksort rp
Try it!