Arvutiteaduse instituut
  1. Kursused
  2. 2020/21 sügis
  3. Programmeerimiskeeled (MTAT.03.006)
EN
Logi sisse

Programmeerimiskeeled 2020/21 sügis

  • Info
  • Õppekava
  • Moodle
  • Loengud & Praksid
  • Lisamaterjalid
  • Küsi abi! (Fleep)

6. Haskelli praktikum

Näiteülesanded

dialoog

Kirjuta protseduur dialoog, mis küsib kasutajalt nime ja tervitab teda sellega.

dialoog :: IO ()
dialoog = undefined

listi trükk

Kirjuta funktsioon, mis prindib talle argumendina antud arvude listi. Iga prinditav arv peab tulema eraldi reale. Näiteks:

> prindiArvud1 [1,66,99]
1
66
99

Kirjuta see funktsioon nii lihtrekursiooniga kui ka forM_-abil.

prindiArvud1 :: [Int] -> IO ()
prindiArvud1 xs = undefined

prindiArvud2 :: [Int] -> IO ()
prindiArvud2 xs = undefined

forM_ jaoks on vaja import Control.Monad.

arvude sisetamine

Kirjuta protseduur, mis esmalt küsib kasutajalt arvu. Kui kasutaja sisestab mittearvu, tuleb veast teatada ning uuesti arvu küsida. Protseduur tagastab edukalt sisestatud arvu.

readMaybe :: Read a => String -> Maybe a
readMaybe xs = f (readsPrec 0 xs)  
  where f [(n,"")] = Just n
        f _        = Nothing

loeArv :: IO Int
loeArv = undefined 

State monaad

Olgu antud järgmine puu andmestruktuur ja funktsioon numberTree, mis nummerdab puu lehed vasakul paremale:

data Tree a = Leaf a | Branch (Tree a) (Tree a)  deriving (Show, Eq)

puu1 = Branch (Branch (Leaf ()) (Leaf ())) (Leaf ())
puu2 = Branch puu1 puu1

numberTree :: Tree a -> Tree Int
numberTree = snd . numberTree' 0
  where
    numberTree' :: Int -> Tree a -> (Int, Tree Int)
    numberTree' n (Leaf _) = (n + 1, Leaf n)
    numberTree' n (Branch l r) =
      let (n', l') = numberTree' n l
          (n'', r') = numberTree' n' r
      in (n'', Branch l' r')

Kirjuta funktsioon numberTreeState, mis teeb täpselt sama, kuid kasutab abifunktsioonis State monaadi, et lihtsustada oleku liikumist arvutuste vahel:

numberTreeState :: Tree a -> Tree Int
numberTreeState t = evalState (numberTreeState' t) 0
  where
    numberTreeState' :: Tree a -> State Int (Tree Int)
    numberTreeState' t = undefined

State monaadi jaoks on vaja import Control.Monad.State.

Harjutusülesanded

kahe arvu summa

Kirjuta protseduur, mis küsib kasutajalt kaks arvu ning trükib nende summa.

summa2 :: IO ()
summa2 = undefined

arvude summa

Kirjuta protseduur, mis esmalt küsib arvu n, seejärel loeb n arvu ning lõpuks trükib viimati loetud n arvu summa. Proovige lahendada seda lihtrekursiooniga kui ka kasutades näiteks sequence funktsiooni.

summaN1 :: IO ()
summaN1 = undefined

summaN2 :: IO ()
summaN2 = undefined

arvu arvamise mäng

Implementeeri klassikaline mäng, mis valib juhusliku arvu (nt. randomRIO-ga, moodulist System.Random; installida stack install random) nullist sajani ning kasutaja peab selle ära arvama. Kasutaja saab pakkuda arve ja programm ütleb, kas pakutud arv on suurem, võrdne või väiksem. Kui vastus on võrdne (s.t. pakutud arv on võrdne juhuslikult valitud arvuga) on mäng läbi ja trükitakse pakkumiste arv.

> m2ng
Arva ära täisarv vahemikus nullist sajani!
Sisesta number: 50
Ei! Minu number on suurem
Sisesta number: 62
Ei! Minu number on väiksem
Sisesta number: 61
Ära arvasid! Oligi 61. Pakkusid 3 korda.
m2ng :: IO ()
m2ng = undefined

Maybe monaad

Olgu antud järgmine avaldispuude andmestruktuur:

data Expr = Const Int | Add Expr Expr | Div Expr Expr  deriving (Show, Eq)

expr1 = Div (Add (Const 3) (Const 1)) (Const 2)
expr2 = Add (Const 1) (Div (Const 1) (Add (Const 1) (Const (-1))))

Kirjuta funktsioon, mis väärtustab avaldispuu või tagastab Nothing kui selles tekib nulliga jagamine:

evalExpr :: Expr -> Maybe Int
evalExpr e = undefined

Maybe monaadi kasutamine lihtsustab lahendust oluliselt.

Ülesanded*

m2ngR

Implementeeri arvu äraarvamise mängu pöördversioon, kus kasutaja valib mõttes (juhusliku) arvu ja programm püüab seda ära arvata. Programm peaks ära tundma sohitegemise, kui kasutaja on vastanud enesele vasturääivalt.

Rekursiivne kataloogide läbimine

Kasutades funktsioone moodulist System.Directory (https://hackage.haskell.org/package/directory-1.3.4.0/docs/System-Directory.html), implementeerige rekursiivne kataloogi suuruse arvutamise protseduur. Faili suuruse arvutamine teha ette antud funktsiooniga failiSuurus. S.t kataloogi suurusena loeme selles olevate failide suuruste summa pluss alamkataloogide suurus.

import System.Directory
import System.IO

failiSuurus :: FilePath -> IO Integer 
failiSuurus path = withFile path ReadMode hFileSize

suurusKataloog :: FilePath -> IO Integer
suurusKataloog f = undefined
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused