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

Programmeerimiskeeled 2018/19 sügis

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

Eksamiülesannete harjutamine

Eksamil on aega 3.5 tundi, et lahendada

  1. baastest (kellel veel pole arvestust), ja
  2. eksamiülesanded.

Eksamiülesannetest kolm on Haskelli kohta ja kolm Scala kohta. Mõlema keele kohta on kaks lihtsamat ülesannet ja üks raskem.

Pidades silmas piiratud eksamiaega (3.5h), on arvestatud sellega, et hindeid E ja D väärivad tudengid peaks oskama lihtsamaid ülesandeid lahendada ning A/B väärivad tudengid peaks oskama ka raskemaid lahendada.

Kõik ülesanded annavad kaheksa punkti ning kokku on võimalik saada 40 punkti. S.t maksimumpunktide saamiseks piisab lahendada kõik lihtsamad ülesanded ning kas Scala või Haskelli raskem ülesanne.

Ülesannete esitamine käib läbi Moodle. Seega eeldame arvuti kasutamist. Muidu kehtivad standardsed eksami reeglid: ei tohi kasutada teiste inimeste abi. Arusaamatuste vältimiseks on keelatud ülesannete lahendamiseks mittevajalike programmide/(veebi-)teenuste kasutamine eksami ajal.

Ülesanne H1 (8 punkti)

Funktsioon h :: [a -> b] -> [(a,b)] -> [b] saab argumendiks funktsioonide listi ja paaride listi.

Iga paaride listi element (x,y) genereerib lõpptulemusse kõigepealt väärtuse y, seejärel teisendatud x väärtused.

 h [(+1), (*2), id] [(2,400),(3,100)] 
      = [400, 2+1, 2*2, id 2, 100, 3+1, 3*2, id 3] 
      = [400,3,4,2,100,4,6,3]
 h [const "x", show] [(2,"a"),(3,"b")] 
      = ["a",const "x" 2, show 2, "b", const "x" 3, show 3]
      = ["a","x","2","b","x","3"]

H1.hs

h :: [a -> b] -> [(a,b)] -> [b]
h = undefined

Ülesanne H2 (8 punkti)

Kasutades järgnevaid definitsioone:

 data Puu a = Leht a | Haru (Puu a) a (Puu a) deriving (Show, Eq)

Kirjuta protseduur f :: (a -> IO ()) -> Puu a -> IO (), mis võtab argumendiks protseduuri ja puu.

Protseduur

  • rakendab eesjärjekorras argumentprotseduuri (3p)
  • vahetult enne rakendamist trükib kauguse juurest (4p)
  • enne vasema alampuu töötlemist trükib "vasem:" (0.5p)
  • enne parema alampuu töötlemist trükib "parem:" (0.5p)

Näiteks:

 *Main> f print p1
 0'd'
 vasem:
 1'b'
 vasem:
 2'a'
 parem:
 2'c'
 parem:
 1'f'
 vasem:
 2'e'
 parem:
 2'g'

H2.hs

-- Näide:
p1 = Haru (Haru (Leht 'a') 'b' (Leht 'c'))
          'd'
          (Haru (Leht 'e') 'f' (Leht 'g'))

f :: (a -> IO ()) -> Puu a -> IO ()
f h p = undefined

Ülesanne H3 (8 punkti)

Kasutades järgnevaid definitsioone:

 data KahendPuu a = Leht | Haru (KahendPuu a) a (KahendPuu a)
     deriving (Eq, Show)

Kirjutada KahendPuu-le Ord instants, nii et <= operaator oleks järjestus sisalduvuse mõttes. S.t. väiksema puu andmed sisalduvad suuremas puus. NB! Puu ei pruugi olla sorteeritud.

Näiteks:

 *H3> puu1 <= puu1
 True
 *H3> puu1 <= puu2
 False
 *H3> puu1 <= puu3
 True
 *H3> puu1 <= puu5
 True
 *H3> puu2 <= puu1
 False
 *H3> puu2 <= puu2
 True
 *H3> puu2 <= puu3
 False 

H3.hs

puu1, puu2, puu3, puu5 :: KahendPuu Int
puu1 = Haru Leht (-1) Leht
puu2 = Haru (Haru Leht 0 Leht) (-2) (Haru Leht 0 Leht)
puu3 = Haru (Haru (Haru Leht 1 Leht) 2 (Haru Leht 0 Leht)) (-3) (Haru (Haru Leht 0 Leht) 2 (Haru Leht (-1) Leht))
puu5 = Haru (Haru (Haru (Haru (Haru Leht 1 Leht) 2 (Haru Leht 1 Leht)) (-1) (Haru (Haru Leht (-1) Leht) 2 (Haru Leht 1 Leht))) (-4) (Haru (Haru (Haru Leht (-1) Leht) 2 (Haru Leht 1 Leht)) (-1) (Haru (Haru Leht (-1) Leht) 0 (Haru Leht 1 Leht)))) 3 (Haru (Haru (Haru (Haru Leht 0 Leht) 2 (Haru Leht (-1) Leht)) 2 (Haru (Haru Leht (-1) Leht) 1 (Haru Leht (-1) Leht))) 1 (Haru (Haru (Haru Leht 0 Leht) 0 (Haru Leht 0 Leht)) 2 (Haru (Haru Leht (-1) Leht) 2 (Haru Leht 1 Leht))))

Ülesanne S1 (8 punkti)

a) (4p) Defineeri funktsioon neighbour(w1: String, w2: String): Boolean

See tagastab true siis ja ainult siis, kui tema argumendid erinevad täpselt ühes kohas.

Näiteks: “kala” ja “kaja” või “karu” ja “maru”. Võib eeldada, et argumendid on ühepikkused.

 def neighbour(w1: String, w2: String): Boolean = ???

b) (4p) Meil on defineeritud globaalne muutuja: val dict = Set("kala", "koer", "pala", "maja", "kaja")

Defineerida järgmine funktsioon: neighboursOf(word: String): Set[String] mis tagastab sõne word kõik naabrid hulgast dict.

Näiteks võiks ülaloleva sõnade hulga puhul olla neighboursOf("kala") tulemus Set("pala", "kaja").

 def neighboursOf(word: String): Set[String] = ???

Ülesanne S2 (8 punkti)

  sealed trait Num
  case object Zero         extends Num
  case class  Succ(n: Num) extends Num
  case class  Pred(n: Num) extends Num

Nendega saab täisarve defineerida. Täisarv on kas 0 või mõne teise teisarvule järgnev arv või eelnev arv.

Näiteks saab kodeerida arvud 2 ja -2 vastavalt:

  val two      = Succ(Succ(Zero))
  val minusTwo = Pred(Pred(Zero))

Arve saab ka rumalalt kodeerida, näiteks on kahte võimalik ka väljendada järgmiselt:

  val stupidTwo = Succ(Pred(Succ(Succ(Zero))))

a) (4p) Defineeri funktsioon, mis tagastab selliste kodeeritud arvude puhul nende tegelik väärtus:

  def numToInt(n: Num): Int = ???

b) (4p) Defineeri funktsioon, mis kodeerib etteantud täisarvu nende case klassidega

  def intToNum(i: Int): Num = ???

Kindlasti tasub kontrollida, et iga arvu puhul saad edasi-tagasi konverteerides esialgse arvu tagasi: numToInt(intToNum(n)) == n

Ülesanne S3 (8 punkti)

Implementeerim mittetühjade listide andmestruktuur MTList.

  • Traiti MTList instantsidel olgu defineeritud MTListiOp[T, MTList] meetodid (3p).
  • Lisaks peab kompanjonobjekstis olema MTList-ide Ehitaja[A, MTList[A]] (5p).

Andmestruktuur peab läbima all toodud testid.

 object Kolmas {
  trait Ehitaja[El, C] {
    def +=(e: El): Unit
    def tulemus: C
  }

  trait MTListiOp[+T,+CC[_]]{
    def listiks: List[T]            // 1p
    def map[U](f: T => U): CC[U]    // 1p
    def +:[U >: T](x:U): CC[U]      // 1p
  }

  trait MTList[+T] extends MTListiOp[T, MTList]
  case class Yks[T](x: T) extends MTList[T] {
    // ???
  }
  case class Lisa[T](x: T, xs: MTList[T]) extends MTList[T] {
    // ???
  }

  object  MTList {
    // 5p
    def uusEhitaja[A]: Ehitaja[A, MTList[A]] = ???

    def apply[T](xs: T*): MTList[T] = {
      val b = uusEhitaja[T]
      for (x <- xs.reverse) b += x
      b.tulemus
    }
  }

  def main(args: Array[String]): Unit = {
    val x = MTList(1,2,3,4)
    val y = MTList(2)
    val z = MTList('a','b')

    assert(x.map(_+1).listiks == List(2,3,4,5))
    assert(y.map(_*2).listiks == List(4))
    assert((1 +: y).listiks == List(1,2))
    assert(z.map(_.toUpper).listiks == List('A', 'B'))
  }
 }
  • 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