FP Test3 2025

From Marek Běhálek Wiki
Revision as of 08:05, 11 November 2025 by Beh01 (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Home Preparation For Test 3 - 2025

(Theme: Vending Machine)

Data types and examples

Let's define a data types representing the state of a vending machine:

  • a type Stock for the available ingredients (name and quantity),
  • a type Drink with the drink’s name, price, and list of required ingredients,
  • a type Machine that combines both stock and available drinks.
type Stock = [(String, Int)]
data Drink = Drink { name :: String , price :: Int , ingredients :: [String] } deriving Show
data Machine = Machine {stock :: Stock, drinks :: [Drink] } deriving Show

stockExample :: Stock
stockExample = [ ("water", 10) , ("coffee", 4) , ("milk", 2) , ("tea", 3) , ("sugar", 5) , ("cocoa", 1) ]

drinksList :: [Drink]
drinksList = [ 
    Drink "Coffee" 30 ["water","coffee"],
    Drink "StrongCoffee" 40 ["water","coffee","coffee"],
    Drink "Tea" 25 ["water", "water","tea"],
    Drink "Cappuccino" 45 ["water","coffee","milk"],
    Drink "Latte" 50 ["water","coffee","milk","sugar"],
    Drink "Chocolate" 50 ["water","cocoa","milk"],
    Drink "Cocoa" 60 ["milk","cocoa","milk"]
    ]

machineExample :: Machine
machineExample = Machine stockExample drinksList

Tasks

Create functions that:

  • Implement a function findDrink that finds a drink by name from a list.

If the drink does not exist, raise an error "No such drink".

findDrink :: [Drink] -> String -> Drink
ghci> findDrink drinksList "Tea"  
Drink {name = "Tea", price = 25, ingredients = ["water","water","tea"]}
  • Implement a function inStock that checks whether a given ingredient is currently available in stock.
inStock :: Stock -> String -> Bool
ghci> inStock stockExample "milk"
True
ghci> inStock stockExample "juice"
False
  • Implement a function useIngredient that decreases the quantity of a given ingredient by one unit.

Ingredients with zero quantity should be removed from the stock.

useIngredient :: Stock -> String -> Stock
ghci> useIngredient  stockExample "milk"
[("water",10),("coffee",4),("milk",1),("tea",3),("sugar",5),("cocoa",1)]
ghci> useIngredient  stockExample "cocoa"
[("water",10),("coffee",4),("milk",2),("tea",3),("sugar",5)]
  • Implement a function canServeDrink that checks whether all ingredients required for a drink are available.
canServeDrink :: Stock -> Drink -> Bool
ghci> canServeDrink stockExample (findDrink drinksList "Cocoa")
True
  • Implement a function serveDrink that updates the stock after preparing a drink.

If some ingredient is missing, raise an error "Can not serve this drink".

serveDrink :: Stock -> Drink -> Stock
ghci> serveDrink stockExample (findDrink drinksList "Cocoa")   
[("water",10),("coffee",4),("tea",3),("sugar",5)]
  • Implement a function processOrders that processes a list of orders (drink names) in sequence. It returns:
    • Just a new machine with the updated stock if all drinks can be served, or
    • Nothing if any of the orders cannot be fulfilled.
processOrders :: Machine -> [String] -> Maybe Machine
ghci> processOrders machineExample ["Coffee","Tea","Coffee","Chocolate"]
Just (Machine {stock = [("water",5),("coffee",2),("milk",1),("tea",2),("sugar",5)], drinks = [ {- skipping list of drinks -} ]})
  • Implement a function processPayment that processes orders similarly but returns the total price of all successfully served drinks,

or Nothing if any order fails.

processPayment :: Machine -> [String] -> Maybe Int
ghci> processPayment  machineExample ["Coffee","Tea","Coffee","Chocolate"]
Just 135
  • Implement a function bestValue that finds the best possible combination of orders (any subset of the given list) maximizing the total profit.

Hint: You can generate all subsets of the input list, evaluate each with processPayment, and return one that yields the highest total payment.

bestValue :: Machine -> [String] -> [String]
ghci> bestValue machineExample ["Coffee","Tea","Coffee","Chocolate"]    
["Coffee","Tea","Coffee","Chocolate"]
ghci> bestValue machineExample ["Cappuccino","Cappuccino","Tea","Cocoa","Chocolate"]
["Cappuccino","Tea","Chocolate"]
ghci> bestValue machineExample ["Cocoa","Chocolate"]                                
["Cocoa"]