Difference between revisions of "FP Test3 2025"

From Marek Běhálek Wiki
Jump to navigation Jump to search
 
(5 intermediate revisions by the same user not shown)
Line 7: Line 7:
  
 
<translate>
 
<translate>
Let's have a data types representing the state of a vending machine:
+
Let's define a data types representing the state of a vending machine:
 
* a type <code>Stock</code> for the available ingredients (name and quantity),
 
* a type <code>Stock</code> for the available ingredients (name and quantity),
 
* a type <code>Drink</code> with the drink’s name, price, and list of required ingredients,
 
* a type <code>Drink</code> with the drink’s name, price, and list of required ingredients,
* a type Machine that combines both stock and available drinks.
+
* a type <code>Machine</code> that combines both stock and available drinks.
 
</translate>
 
</translate>
  
Line 114: Line 114:
 
<syntaxhighlight lang="Haskell" class="myDark">
 
<syntaxhighlight lang="Haskell" class="myDark">
 
ghci> processOrders machineExample ["Coffee","Tea","Coffee","Chocolate"]
 
ghci> processOrders machineExample ["Coffee","Tea","Coffee","Chocolate"]
Just (Machine {stock = [("water",5),("coffee",2),("milk",1),("tea",2),("sugar",5)], drinks = [ {- skiping list of drinks -} ]})
+
Just (Machine {stock = [("water",5),("coffee",2),("milk",1),("tea",2),("sugar",5)], drinks = [ {- skipping list of drinks -} ]})
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 129: Line 129:
  
 
<translate>
 
<translate>
* Implement a function <code>bestValue</code> that that finds the '''best''' possible subsequence of orders '''maximizing''' the total profit.  
+
* Implement a function <code>bestValue</code> that finds the best possible combination of orders (any subset of the given list) maximizing the total profit.  
  
Hint: You can generate all possible order sequences,
+
Hint: You can generate all subsets of the input list, evaluate each with <code>processPayment</code>, and return one that yields the highest total payment.
 
 
 
 
Use processPayment to evaluate each sequence.
 
 
 
Return the sequence that yields the highest total payment.
 
 
 
If no sequence can be completed successfully, return an empty list.
 
 
</translate>
 
</translate>
  
<syntaxhighlight lang="Haskell">processPayment :: Machine -> [String] -> Maybe Int</syntaxhighlight>
+
<syntaxhighlight lang="Haskell">bestValue :: Machine -> [String] -> [String]</syntaxhighlight>
 
<syntaxhighlight lang="Haskell" class="myDark">
 
<syntaxhighlight lang="Haskell" class="myDark">
ghci> processPayment  machineExample ["Coffee","Tea","Coffee","Chocolate"]
+
ghci> bestValue machineExample ["Coffee","Tea","Coffee","Chocolate"]  
Just 135
+
["Coffee","Tea","Coffee","Chocolate"]
 +
ghci> bestValue machineExample ["Cappuccino","Cappuccino","Tea","Cocoa","Chocolate"]
 +
["Cappuccino","Tea","Chocolate"]
 +
ghci> bestValue machineExample ["Cocoa","Chocolate"]                               
 +
["Cocoa"]
 
</syntaxhighlight>
 
</syntaxhighlight>

Latest revision as of 08:05, 11 November 2025

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"]