mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
216 lines
6.8 KiB
Haskell
216 lines
6.8 KiB
Haskell
-- Exercise set 4a:
|
|
--
|
|
-- * using type classes
|
|
-- * working with lists
|
|
--
|
|
-- Type classes you'll need
|
|
-- * Eq
|
|
-- * Ord
|
|
-- * Num
|
|
-- * Fractional
|
|
--
|
|
-- Useful functions:
|
|
-- * maximum
|
|
-- * minimum
|
|
-- * sort
|
|
|
|
module Set4a where
|
|
|
|
import Mooc.Todo
|
|
import Data.List
|
|
import Data.Ord
|
|
import qualified Data.Map as Map
|
|
import Data.Array
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 1: implement the function allEqual which returns True if all
|
|
-- values in the list are equal.
|
|
--
|
|
-- Examples:
|
|
-- allEqual [] ==> True
|
|
-- allEqual [1,2,3] ==> False
|
|
-- allEqual [1,1,1] ==> True
|
|
--
|
|
-- PS. check out the error message you get with your implementation if
|
|
-- you remove the Eq a => constraint from the type!
|
|
|
|
allEqual :: Eq a => [a] -> Bool
|
|
allEqual xs = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 2: implement the function distinct which returns True if all
|
|
-- values in a list are different.
|
|
--
|
|
-- Hint: a certain function from the lecture material can make this
|
|
-- really easy for you.
|
|
--
|
|
-- Examples:
|
|
-- distinct [] ==> True
|
|
-- distinct [1,1,2] ==> False
|
|
-- distinct [1,2] ==> True
|
|
|
|
distinct :: Eq a => [a] -> Bool
|
|
distinct = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 3: implement the function middle that returns the middle value
|
|
-- (not the smallest or the largest) out of its three arguments.
|
|
--
|
|
-- The function should work on all types in the Ord class. Give it a
|
|
-- suitable type signature.
|
|
--
|
|
-- Examples:
|
|
-- middle 'b' 'a' 'c' ==> 'b'
|
|
-- middle 1 7 3 ==> 3
|
|
|
|
middle = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 4: return the range of an input list, that is, the difference
|
|
-- between the smallest and the largest element.
|
|
--
|
|
-- Your function should work on all suitable types, like Float and
|
|
-- Int. You'll need to add _class constraints_ to the type of range.
|
|
--
|
|
-- It's fine if your function doesn't work for empty inputs.
|
|
--
|
|
-- Examples:
|
|
-- rangeOf [4,2,1,3] ==> 3
|
|
-- rangeOf [1.5,1.0,1.1,1.2] ==> 0.5
|
|
|
|
rangeOf :: [a] -> a
|
|
rangeOf = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 5: given a (non-empty) list of (non-empty) lists, return the longest
|
|
-- list. If there are multiple lists of the same length, return the list that
|
|
-- has the smallest _first element_.
|
|
--
|
|
-- (If multiple lists have the same length and same first element,
|
|
-- you can return any one of them.)
|
|
--
|
|
-- Give the function "longest" a suitable type.
|
|
--
|
|
-- Challenge: Can you solve this exercise without sorting the list of lists?
|
|
--
|
|
-- Examples:
|
|
-- longest [[1,2,3],[4,5],[6]] ==> [1,2,3]
|
|
-- longest ["bcd","def","ab"] ==> "bcd"
|
|
|
|
longest = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 6: Implement the function incrementKey, that takes a list of
|
|
-- (key,value) pairs, and adds 1 to all the values that have the given key.
|
|
--
|
|
-- You'll need to add _class constraints_ to the type of incrementKey
|
|
-- to make the function work!
|
|
--
|
|
-- The function needs to be generic and handle all compatible types,
|
|
-- see the examples.
|
|
--
|
|
-- Examples:
|
|
-- incrementKey True [(True,1),(False,3),(True,4)] ==> [(True,2),(False,3),(True,5)]
|
|
-- incrementKey 'a' [('a',3.4)] ==> [('a',4.4)]
|
|
|
|
incrementKey :: k -> [(k,v)] -> [(k,v)]
|
|
incrementKey = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 7: compute the average of a list of values of the Fractional
|
|
-- class.
|
|
--
|
|
-- There is no need to handle the empty list case.
|
|
--
|
|
-- Hint! since Fractional is a subclass of Num, you have all
|
|
-- arithmetic operations available
|
|
--
|
|
-- Hint! you can use the function fromIntegral to convert the list
|
|
-- length to a Fractional
|
|
|
|
average :: Fractional a => [a] -> a
|
|
average xs = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 8: given a map from player name to score and two players, return
|
|
-- the name of the player with more points. If the players are tied,
|
|
-- return the name of the first player (that is, the name of the
|
|
-- player who comes first in the argument list, player1).
|
|
--
|
|
-- If a player doesn't exist in the map, you can assume they have 0 points.
|
|
--
|
|
-- Hint: Map.findWithDefault can make this simpler
|
|
--
|
|
-- Examples:
|
|
-- winner (Map.fromList [("Bob",3470),("Jane",2130),("Lisa",9448)]) "Jane" "Lisa"
|
|
-- ==> "Lisa"
|
|
-- winner (Map.fromList [("Mike",13607),("Bob",5899),("Lisa",5899)]) "Lisa" "Bob"
|
|
-- ==> "Lisa"
|
|
|
|
winner :: Map.Map String Int -> String -> String -> String
|
|
winner scores player1 player2 = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 9: compute how many times each value in the list occurs. Return
|
|
-- the frequencies as a Map from value to Int.
|
|
--
|
|
-- Challenge 1: try using Map.alter for this
|
|
--
|
|
-- Challenge 2: use foldr to process the list
|
|
--
|
|
-- Example:
|
|
-- freqs [False,False,False,True]
|
|
-- ==> Map.fromList [(False,3),(True,1)]
|
|
|
|
freqs :: (Eq a, Ord a) => [a] -> Map.Map a Int
|
|
freqs xs = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 10: recall the withdraw example from the course material. Write a
|
|
-- similar function, transfer, that transfers money from one account
|
|
-- to another.
|
|
--
|
|
-- However, the function should not perform the transfer if
|
|
-- * the from account doesn't exist,
|
|
-- * the to account doesn't exist,
|
|
-- * the sum is negative,
|
|
-- * or the from account doesn't have enough money.
|
|
--
|
|
-- Hint: there are many ways to implement this logic. Map.member or
|
|
-- Map.notMember might help.
|
|
--
|
|
-- Examples:
|
|
-- let bank = Map.fromList [("Bob",100),("Mike",50)]
|
|
-- transfer "Bob" "Mike" 20 bank
|
|
-- ==> fromList [("Bob",80),("Mike",70)]
|
|
-- transfer "Bob" "Mike" 120 bank
|
|
-- ==> fromList [("Bob",100),("Mike",50)]
|
|
-- transfer "Bob" "Lisa" 20 bank
|
|
-- ==> fromList [("Bob",100),("Mike",50)]
|
|
-- transfer "Lisa" "Mike" 20 bank
|
|
-- ==> fromList [("Bob",100),("Mike",50)]
|
|
|
|
transfer :: String -> String -> Int -> Map.Map String Int -> Map.Map String Int
|
|
transfer from to amount bank = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 11: given an Array and two indices, swap the elements in the indices.
|
|
--
|
|
-- Example:
|
|
-- swap 2 3 (array (1,4) [(1,"one"),(2,"two"),(3,"three"),(4,"four")])
|
|
-- ==> array (1,4) [(1,"one"),(2,"three"),(3,"two"),(4,"four")]
|
|
|
|
swap :: Ix i => i -> i -> Array i a -> Array i a
|
|
swap i j arr = todo
|
|
|
|
------------------------------------------------------------------------------
|
|
-- Ex 12: given an Array, find the index of the largest element. You
|
|
-- can assume the Array isn't empty.
|
|
--
|
|
-- You may assume that the largest element is unique.
|
|
--
|
|
-- Hint: check out Data.Array.indices or Data.Array.assocs
|
|
|
|
maxIndex :: (Ix i, Ord a) => Array i a -> i
|
|
maxIndex = todo
|