815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset



Samankaltaiset tiedostot
815338A Ohjelmointikielten periaatteet Harjoitus 6 Vastaukset

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet

Luku 3. Listankäsittelyä. 3.1 Listat

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Laiska laskenta, korekursio ja äärettömyys. TIEA341 Funktio ohjelmointi Syksy 2005

Tyyppejä ja vähän muutakin. TIEA341 Funktio ohjelmointi 1 Syksy 2005

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ohjelmoinnin perusteet Y Python

Makrojen mystinen maailma lyhyt oppimäärä

Ohjelmoinnin perusteet Y Python

Luento 5. Timo Savola. 28. huhtikuuta 2006

Harjoitus 1 -- Ratkaisut

Ohjelmoinnin peruskurssien laaja oppimäärä

Tietorakenteet ja algoritmit

Ohjelmoinnin peruskurssien laaja oppimäärä

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

Jatkeet. TIES341 Funktio ohjelmointi 2 Kevät 2006

Ohjelmoinnin perusteet Y Python

Mathematica Sekalaista asiaa

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Scheme-kesäkurssi luento 3

Racket ohjelmointia osa 2. Tiina Partanen Lielahden koulu 2014

Funktionaalinen ohjelmointi

811120P Diskreetit rakenteet

Algebralliset tietotyypit ym. TIEA341 Funktio ohjelmointi 1 Syksy 2005

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Harjoitus 1 -- Ratkaisut

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssi Y1

Algoritmit 1. Demot Timo Männikkö

Ohjelmoinnin perusteet Y Python

815338A Ohjelmointikielten periaatteet

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

811120P Diskreetit rakenteet

Harjoitus 4 -- Ratkaisut

Ohjelmoinnin perusteet Y Python

Funktionaalinen ohjelmointi

Bootstrap / HTDP2 / Realm of Racket. Vertailu

Ohjelmoinnin peruskurssi Y1

811120P Diskreetit rakenteet

Ehto- ja toistolauseet

Demo 7 ( ) Antti-Juhani Kaijanaho. 9. joulukuuta 2005

Kerta 2. Kerta 2 Kerta 3 Kerta 4 Kerta Toteuta Pythonilla seuraava ohjelma:

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin peruskurssien laaja oppimäärä

Ohjelmoinnin perusteet Y Python

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Ohjelmoinnin peruskurssi Y1

TAMPEREEN TEKNILLINEN YLIOPISTO

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

TIEA341 Funktio-ohjelmointi 1, kevät 2008

Java-kielen perusteet

JavaScript alkeet Esimerkkikoodeja moniste 2 ( Metropolia)

Ohjelmoinnin perusteet Y Python

Harjoitus 5 (viikko 48)

Ohjelmoinnin perusteet Y Python

Geneeriset tyypit. TIES542 Ohjelmointikielten periaatteet, kevät Antti-Juhani Kaijanaho. Jyväskylän yliopisto Tietotekniikan laitos

Luonnollisten lukujen laskutoimitusten määrittely Peanon aksioomien pohjalta

Tietorakenteet (syksy 2013)

Tietorakenteet ja algoritmit syksy Laskuharjoitus 1

Ohjelmoinnin perusteet Y Python

Kesälukio 2000 PK2 Tauluharjoituksia I Mallivastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssien laaja oppimäärä

Scheme-kesäkurssi luento 2

Tietorakenteet ja algoritmit - syksy

2. Seuraavassa kuvassa on verkon solmujen topologinen järjestys: x t v q z u s y w r. Kuva 1: Tehtävän 2 solmut järjestettynä topologisesti.

Ohjelmoinnin perusteet Y Python

Transkriptio:

815338A Ohjelmointikielten periaatteet 2014-2015. Harjoitus 7 Vastaukset Harjoituksen aiheena on funktionaalinen ohjelmointi Scheme- ja Haskell-kielillä. Voit suorittaa ohjelmat osoitteessa https://ideone.com/ tai http://www.tutorialspoint.com/codingground.htm. Tehtävä 1. Suorita Schemellä seuraavat laskutoimitukset 5-6 1/5 + 3/10 1.5 * (21.2-11.0)/3.2 Tuloksen näyttäminen onnistuu funktiolla display, esimerkiksi 12*13 ja rivinvaihto voitaisiin kirjoittaa (display (* 12 13)) Vastaus. Schemessä operaatiot kirjoitetaan listojen muodossa samaan tapaan kuin funktiotkin. Ensimmäiseksi tulee operaatio ja sitten argumentit. Mainitut laskutoimitukset kirjoitettaisiin (tuloksen näyttämisen kera) seuraavasti: (display (- 6 5)) (display (+ (/ 1 5) (/ 3 10))) (display (* 1.5 (/ (- 21.2 11.0) 3.2))) Kun lausekkeet ajetaan tulkissa, saadaan vastaukset 1 1/2 4.781249999999999 Tehtävä 2. Tutki seuraavia funktioita: a) Scheme-funktio (define (a_fun x y) (cond ((null? x) y) (else (cons (car x) (a_fun (cdr x) y))))) b) Haskell-funktio b_fun(x,[]) = [] b_fun(x,(y:ys)) = if x==y then (y:ys) else b_fun(x,ys)

Yritä ensin päätellä koodista funktioiden toiminta. Kopioi koodi tulkkiin ja kutsu funktiota; tarkista oliko päätelmäsi oikea. Scheme-funktion kutsu voidaan kirjoittaa esimerkiksi (display (a_fun (aa bb cc) (bb aa)) ja Haskell-funktion kutsu main = do print(b_fun ("aa", ["bb","aa","cc"])) Vastaus. a) Scheme-funktio (define (a_fun x y) (cond ((null? x) y) (else (cons (car x) (a_fun (cdr x) y))))) ottaa siis kaksi parametria, joista ainakin ensimmäisen tulee olla lista, koska siihen sovelletaan listojen operaatioita. Schemessä cond määrittelee monivalintalauseen toteuttavan funktion. Kun kohdataan ensimmäinen lauseke, joka evaluoituu todeksi, palautetaan sitä vastaava arvo: Jos siis x on tyhjä lista, palautetaan y. Jos x ei ole tyhjä, sovelletaan ensin funktiota x:n häntään (cdr x) ja y:hyn. Sitten x:n päästä (car x) ja muodostuneesta listasta muodostetaan lista. Jos x:ssä on vain yksi alkio (häntä on tyhjä), niin tämä alkio liitetään listan y alkuun. Rekursiivisesti päättelemällä huomataan, että funktio liittää listan x listan y alkuun. Tämän voi varmistaa kokeilemalla funktiota eri syötteillä tulkissa. Esimerkiksi (display (a_fun '(1 2 3) '(a b))) tulostaa (1 2 3 a b). b) Haskell-funktio b_fun(x,[]) = [] b_fun(x,(y:ys)) = if x==y then (y:ys) else b_fun(x,ys) ottaa myös kaksi parametria, joista jälkimmäinen on lista. Haskellissa voidaan funktioita määritellä hahmontunnistuksen avulla. Edellä oleva funktio palauttaa tyhjän listan, jos jälkimmäinen parametri on tyhjä lista. Jos jälkimmäinen parametri ei ole tyhjä lista, se jaetaan päähän y ja häntään ys. Jos parametri x on sama kuin listan pää, palautetaan lista. Muuten kutsutaan funktiota

rekursiivisesti parametreilla x ja listan häntä. Näin edetään, kunnes alkio x löytyy listasta ja palautetaan x:llä alkava listan osa, tai lista tyhjenee, jolloin palautetaan tyhjä lista. Funktio siis etsii listasta y loppuosan joka alkaa x:llä. Tämän voi myös tarkistaa tulkilla, esimerkiksi syötteellä main = do print (b_fun(3,[1,2,3,4,5])) tulostuu [3,4,5]. Tehtävä 3. Kirjoita Scheme-funktio kaanna, joka kääntää argumenttinaan saamansa listan. Listan syvärakennetta ei tarvitse kääntää, ts. syötteellä (a b c d) funktio palauttaa listan (d c b a) ja syötteellä (a (b c) (d e) (f g)) listan ((f g) (d e) (b c) a). Voit käyttää hyväksi Schemen varusfunktiota append, joka yhdistää parametrina annettavat kaksi listaa. Kannattanee kirjoittaa funktio tekstitiedostoon, josta kopioi Scheme-tulkkiin. Testaa funktiotasi. Vastaus. Lista voidaan kääntää rekursiivisesti siten, että tyhjän listan kääntäminen palauttaa tyhjän listan. Muuten lista käännetään niin, että ensin käännetään listan häntä ja käännetyn hännän perään liitetään listan pää. Näin saadaan rekursiivinen funktio (define (kaanna x) (cond ((null? x) '()) ((not (list? x)) x) (else (append (kaanna (cdr x)) (list (car x)))))) Yllä on otettu vielä huomioon, että funktiolle voidaan syöttää myös parametri joka ei ole lista. Tällöin palautetaan parametri sellaisenaan. Huomaa vielä, että listan pää ei välttämättä ole lista, joten siitä muodostetaan lista ennen sen lisäämistä käännetyn hännän perään.

Tehtävä 4. Kirjoita Scheme-funktio rullaa, joka tuottaa argumenttinaan saamastaan listasta sen kaikki kierrot eli rotaatiot ja esittää ne yhdessä listassa. Syötteellä (a b c d) funktio palauttaa siis listan ((a b c d) (b c d a) (c d a b) (d a b c)). Vihje: Toteutus tulee helpommaksi, jos kirjoittaa apufunktioita. Vastaus. Kirjoitetaan ensin apufunktio turn, joka tekee yhden rotaation, ts. siirtää listan pään sen viimeiseksi alkioksi: (define (turn x) (append (cdr x) (list (car x)))) Tämä funktio palauttaa esimerkiksi parametrilistalla (1 2 3 4) listan (2 3 4 1). Tätä funktiota toistuvasti soveltamalla saadaan kaikki rotaatiot. Pitää vain pystyä kontrolloimaan sitä, että saadaan täsmälleen oikea määrä rotaatioita. Rotaatioita on yhtä monta kuin listassa on alkioita, joten kirjoitetaan apufunktio roll, joka ottaa parametrinaan kaksi listaa. Ensimmäistä kierretään ja toista lyhennetään jokaisella kutsulla. Parametrilista lisätään palautettavan listan alkioksi. Rekursio päättyy, kun toinen lista tyhjenee: (define (roll x y) (cond ((null? x) '() ) ((null? y) '() ) (else (append (list x) (roll (turn x) (cdr y)) )))) Näin saadaan listan x kaikki rotaatiot yhteen listaan, kun kirjoitetaan funktio, joka kutsuu edellistä funktiota sama lista kumpanakin parametrina: (define (rullaa x) (if (list? x) (roll x x) '())) Tällöin kutsu (rullaa (1 2 3 4)) palauttaa listan ((1 2 3 4) (2 3 4 1) (3 4 1 2) (4 1 2 3))

Tehtävä 5. Kirjoita Haskellilla tehtävien 3 ja 4 funktiot. Vastaus. Käytetään samaa logiikkaa kuin Scheme-funktioissa. Tehtävän 3 funktio voidaan kirjoittaa seuraavasti: kaanna [] = [] kaanna (x:xs) = kaanna(xs) ++ [x] Huomaa, että Haskellissa listat kirjoitetaan hakasulkeisiin ja alkiot erotetaan pilkuilla. Haskellissa listan pää ja häntä voidaan käsitellä hahmontunnistuksella (x:xs) kuten yllä. Listoja yhdistellään operaattorilla ++. Tehtävän 4 funktio laaditaan samalla periaatteella kuin Scheme-funktio kahden apufunktion avulla. turn [] = [] turn (x:xs) = xs ++ [x] roll (x,[]) = [] roll (x,(y:ys)) = [x] ++ roll(turn(x),ys) rullaa x = roll(x,x) Haskell-koodi lienee kieliä tuntemattomalle luettavampaa kuin Scheme.