Difference between revisions of "FP Test3 2025"

From Marek Běhálek Wiki
Jump to navigation Jump to search
Line 1: Line 1:
 
<translate>
 
<translate>
 
= Home Preparation For Test 3 - 2025 =
 
= Home Preparation For Test 3 - 2025 =
 +
(Theme: Vending Machine)
  
== Theme: Vending Machine ==
+
== Data types and examples ==
 
 
=== Data types and examples ===
 
 
</translate>
 
</translate>
  
 
<translate>
 
<translate>
Consider following type representing a maze:
+
Let's have 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>Drink</code> with the drink’s name, price, and list of required ingredients,
 +
* a type Machine that combines both stock and available drinks.
 
</translate>
 
</translate>
  
<syntaxhighlight lang="Haskell">type Maze = [String]</syntaxhighlight>
+
<syntaxhighlight lang="Haskell">
 +
type Stock = [(String, Int)]
 +
data Drink = Drink { name :: String , price :: Int , ingredients :: [String] } deriving Show
 +
data Machine = Machine {stock :: Stock, drinks :: [Drink] } deriving Show
  
<translate>
+
stockExample :: Stock
If you want to print this maze on a screen you can use:
+
stockExample = [ ("water", 10) , ("coffee", 4) , ("milk", 2) , ("tea", 3) , ("sugar", 5) , ("cocoa", 1) ]
</translate>
 
  
<syntaxhighlight lang="Haskell">
+
drinksList :: [Drink]
printMaze :: Maze -> IO ()
+
drinksList = [
printMaze x = putStr (concat (map (++"\n") x))
+
    Drink "Coffee" 30 ["water","coffee"],
</syntaxhighlight>
+
    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"]
 +
    ]
  
<translate>
+
machineExample :: Machine
<!--T:14-->
+
machineExample = Machine stockExample drinksList
Maze example:
 
</translate>
 
 
 
<syntaxhighlight lang="Haskell">
 
sample1 :: Maze
 
sample1 = ["*********",
 
          "* *  * *",
 
          "* * * * *",
 
          "* * * * *",
 
          "*  *  *",
 
          "******* *",
 
          "        *",
 
          "*********"]
 
sample2 :: Maze
 
sample2 = ["      ",
 
          "      ",
 
          "  ***  ",
 
          "  ***  ",
 
          "  ***  ",
 
          "      ",
 
          "      "]
 
sample3 :: Maze
 
sample3 = ["  * *  ",
 
          " ##### ",
 
          "  ***  ",
 
          "  * *  ",
 
          "  ***  ",
 
          "    * ",
 
          "      "]
 
sample4 :: Maze
 
sample4 = ["*********",
 
          "*s*  *e*",
 
          "* *  * *",
 
          "* *  * *",
 
          "*      *",
 
          "******* *",
 
          "        *",
 
          "*********"]
 
arrow :: Maze
 
arrow = [ "....#....",
 
          "...###...",
 
          "..#.#.#..",
 
          ".#..#..#.",
 
          "....#....",
 
          "....#....",
 
          "....#####"]
 
</syntaxhighlight>
 
<syntaxhighlight lang="Haskell" class="myDark">
 
ghci> printMaze sample1                                         
 
*********
 
* *  * *
 
* * * * *
 
* * * * *
 
*  *  *
 
******* *
 
        *
 
*********
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 92: Line 45:
  
 
<translate>
 
<translate>
*Place one maze above another.
+
* Implement a function <code>findDrink :: [Drink] -> String -> Drink</code> that finds a drink by name from a list.
 +
If the drink does not exist, raise an error <code>"No such drink"</code>.
 
</translate>
 
</translate>
  

Revision as of 07:14, 11 November 2025

Home Preparation For Test 3 - 2025

(Theme: Vending Machine)

Data types and examples

Let's have 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 :: [Drink] -> String -> Drink that finds a drink by name from a list.

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

above :: Maze -> Maze -> Maze
*Main> printMaze(above arrow arrow)
....#....
...###...
..#.#.#..
.#..#..#.
....#....
....#....
....#####
....#....
...###...
..#.#.#..
.#..#..#.
....#....
....#....
....#####
  • Place two mazes side by side (consider, that they have the same height).
sideBySide :: Maze -> Maze -> Maze
*Main> printMaze(sideBySide arrow arrow)
....#........#....
...###......###...
..#.#.#....#.#.#..
.#..#..#..#..#..#.
....#........#....
....#........#....
....#####....#####
  • Rotate maze to the left and to the right.
rotateR :: Maze -> Maze
rotateL :: Maze -> Maze
*Main> printMaze (rotateR arrow)       
.......
...#...
....#..
.....#.
#######
#....#.
#...#..
#..#...
#......
*Main> printMaze(rotateL arrow)
......#
...#..#
..#...#
.#....#
#######
.#.....
..#....
...#...
.......
  • Define a function getFromMaze that takes a character from a maze. The coordinates are given as: (row index, column index) where the indexes start from (0,0). The coordinate (0,0) is a top left corner.
getFromMaze :: Maze -> (Int, Int) -> Char
ghci> getFromMaze  sample1  (1,1)
' '
  • Using the same coordinates as for the function above, define a function putIntoMaze that takes a maze and a list of triplets (row index, column index, character) and puts on given coordinate given character.
putIntoMaze :: Maze -> [(Int, Int, Char)] -> Maze
ghci> printMaze(putIntoMaze sample2 [(0,0,'1'),(6,6,'2'),(0,6,'3')]) 
1     3

  ***
  ***
  ***

      2
  • Using the same coordinates as for the functions above, define a function getPart that takes a maze and extracts a rectangular part of this maze. The maze is given as first parameter. The extracted part is defined by the position of the top left corner (second parameter) and its size (third parameter, given as (height, width)).
getPart :: Maze -> (Int,Int) -> (Int,Int) -> Maze
ghci> printMaze(getPart sample1 (1,1) (7,7))
 *   *
 * * *
 * * *
   *
******

*******
  • Implement the function solveMaze. It has 1 argument. It is a list of strings representing a maze row by row from top to bottom ('*' - wall, ' ' - empty square, 's' - starting position, 'e' - ending possition). At the beginning we are at position 's' and we want to get the length of the shortest path to the position denotated by 'e'. Such path compose from steps. in each step we can move one square left, right, up or down. The function returns a number of these steps in the shortest path from 's' to 'e'.
solveMaze :: Result -> Int
solveMaze sample4 
12