811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

Samankaltaiset tiedostot
811312A Tietorakenteet ja algoritmit , Harjoitus 1 ratkaisu

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

811312A Tietorakenteet ja algoritmit Kertausta kurssin alkuosasta

811312A Tietorakenteet ja algoritmit, , Harjoitus 7, ratkaisu

Algoritmit 1. Demot Timo Männikkö

Algoritmit 1. Luento 5 Ti Timo Männikkö

Algoritmit 1. Demot Timo Männikkö

Matematiikassa väitelauseet ovat usein muotoa: jos P on totta, niin Q on totta.

Ohjelmoinnin perusteet Y Python

Approbatur 3, demo 1, ratkaisut A sanoo: Vähintään yksi meistä on retku. Tehtävänä on päätellä, mitä tyyppiä A ja B ovat.

1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

811312A Tietorakenteet ja algoritmit III Lajittelualgoritmeista

f(n) = Ω(g(n)) jos ja vain jos g(n) = O(f(n))

58131 Tietorakenteet ja algoritmit (syksy 2015)

58131 Tietorakenteet ja algoritmit (kevät 2014) Uusinta- ja erilliskoe, , vastauksia

58131 Tietorakenteet (kevät 2009) Harjoitus 9, ratkaisuja (Antti Laaksonen)

Ohjelmoinnin peruskurssi Y1

Ratkaisut Summa on nolla, sillä luvut muodostavat vastalukuparit: ( 10) + 10 = 0, ( 9) + 9 = 0,...

811312A Tietorakenteet ja algoritmit, , Harjoitus 3, Ratkaisu

Ohjelmoinnin perusteet Y Python

ALGORITMIT 1 DEMOVASTAUKSET KEVÄT 2012

Ohjelmoinnin perusteet Y Python

Tarkennamme geneeristä painamiskorotusalgoritmia

= 3 = 1. Induktioaskel. Induktio-oletus: Tehtävän summakaava pätee jollakin luonnollisella luvulla n 1. Induktioväite: n+1

Diskreetin matematiikan perusteet Laskuharjoitus 2 / vko 9

Ohjelmoinnin peruskurssi Y1

Toinen harjoitustyö. ASCII-grafiikkaa 2017

Algoritmit 1. Luento 11 Ti Timo Männikkö

Kohdissa 2 ja 3 jos lukujen valintaan on useita vaihtoehtoja, valitaan sellaiset luvut, jotka ovat mahdollisimman lähellä listan alkua.

811120P Diskreetit rakenteet

Algoritmit 1. Luento 1 Ti Timo Männikkö

(d) 29 4 (mod 7) (e) ( ) 49 (mod 10) (f) (mod 9)

Tietorakenteet, laskuharjoitus 10, ratkaisuja. 1. (a) Seuraava algoritmi tutkii, onko jokin luku taulukossa monta kertaa:

Algoritmit 2. Demot Timo Männikkö

Ohjelmoinnin perusteet Y Python

811120P Diskreetit rakenteet

811120P Diskreetit rakenteet

Algoritmit 2. Luento 10 To Timo Männikkö

811312A Tietorakenteet ja algoritmit, , Harjoitus 6, Ratkaisu

811312A Tietorakenteet ja algoritmit I Johdanto

4.3. Matemaattinen induktio

11. Javan toistorakenteet 11.1

Yhtäpitävyys. Aikaisemmin osoitettiin, että n on parillinen (oletus) n 2 on parillinen (väite).

Kaikki kurssin laskuharjoitukset pidetään Exactumin salissa C123. Malliratkaisut tulevat nettiin kurssisivulle.

Algoritmit 1. Demot Timo Männikkö

Algoritmit 2. Luento 2 To Timo Männikkö

Ohjelmoinnin perusteet, syksy 2006

MS-A0402 Diskreetin matematiikan perusteet Esimerkkejä ym., osa I

Matematiikan ja tilastotieteen laitos Algebra I - Kesä 2009 Ratkaisuehdoituksia harjoituksiin 8 -Tehtävät sivua Heikki Koivupalo ja Rami Luisto

Liite 1. Laajennettu Eukleideen algoritmi suoraviivainen tapa

12. Javan toistorakenteet 12.1

Tietorakenteet, laskuharjoitus 7, ratkaisuja

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Algoritmit 2. Luento 7 Ti Timo Männikkö

Jokaisen parittoman kokonaisluvun toinen potenssi on pariton.

Diskreetin matematiikan perusteet Laskuharjoitus 1 / vko 8

811120P Diskreetit rakenteet

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

811312A Tietorakenteet ja algoritmit V Verkkojen algoritmeja Osa 2 : Kruskalin ja Dijkstran algoritmit

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

T Syksy 2004 Logiikka tietotekniikassa: perusteet Laskuharjoitus 12 (opetusmoniste, kappaleet )

Johdatus verkkoteoriaan 4. luento

4 Tehokkuus ja algoritmien suunnittelu

MS-A0402 Diskreetin matematiikan perusteet Esimerkkejä ym., osa I

Toinen harjoitustyö. ASCII-grafiikkaa

Johdatus matemaattiseen päättelyyn

Johdatus matemaattiseen päättelyyn

TAMPEREEN TEKNILLINEN YLIOPISTO

Algoritmit 2. Luento 13 Ti Timo Männikkö

Vastaoletuksen muodostaminen

Ohjelmoinnin perusteet Y Python

12. Javan toistorakenteet 12.1

2.1. Tehtävänä on osoittaa induktiolla, että kaikille n N pätee n = 1 n(n + 1). (1)

Tehtävä 2: Loppuosataulukko

Tekijä Pitkä Matematiikka 11 ratkaisut luku 2

A = a b B = c d. d e f. g h i determinantti on det(c) = a(ei fh) b(di fg) + c(dh eg). Matriisin determinanttia voi merkitä myös pystyviivojen avulla:

811312A Tietorakenteet ja algoritmit, , Harjoitus 4, Ratkaisu

Ohjelmoinnin peruskurssi Y1

Algoritmit 2. Luento 2 Ke Timo Männikkö

Pikalajittelu: valitaan ns. pivot-alkio esim. pivot = oikeanpuoleisin

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

Python-ohjelmointi Harjoitus 2

ja λ 2 = 2x 1r 0 x 2 + 2x 1r 0 x 2

58131 Tietorakenteet ja algoritmit (syksy 2015) Toinen välikoe, malliratkaisut

Algoritmit 2. Luento 11 Ti Timo Männikkö

1. Osoita, että joukon X osajoukoille A ja B on voimassa toinen ns. de Morganin laki (A B) = A B.

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

Algoritmit 1. Luento 12 Ti Timo Männikkö

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin peruskurssi Y1

Johdatus lukuteoriaan Harjoitus 11 syksy 2008 Eemeli Blåsten. Ratkaisuehdotelma

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin peruskurssi Y1

n. asteen polynomilla on enintään n nollakohtaa ja enintään n - 1 ääriarvokohtaa.

ITKP102 Ohjelmointi 1 (6 op), arvosteluraportti

Tietorakenteet, laskuharjoitus 2,

Transkriptio:

811312A Tietorakenteet ja algoritmit 2017-2018, Harjoitus 2 ratkaisu Harjoituksen aiheena on algoritmien oikeellisuus. Tehtävä 2.1 Kahvipurkkiongelma. Kahvipurkissa P on valkoisia ja mustia kahvipapuja, yhteensä vähintään kaksi kappaletta. Lisäksi saatavilla on suuri määrä mustia papuja. Osoita, että seuraava algoritmi päättyy. Merkitään purkissa P kulloinkin olevien papujen määrää N(P):llä. Syöte: Kahvipurkki P, jossa on valkoisia ja mustia papuja, alussa N(P) >= 2. Tuloste: Purkin viimeinen papu. PAVUT(P) 1. while N(P) > 1 2. valitse satunnaisesti kaksi papua purkista P 3. if pavut samanväriset 4. heitä pois pavut ja lisää purkkiin musta papu 5. else 6. palauta valkoinen papu purkkiin ja heitä pois musta papu 7. return purkkiin jäänyt papu Voidaanko viimeisen pavun väriä tietää ennakolta, jos tiedetään purkissa alussa olevien valkoisten ja mustien papujen lukumäärät? Ratkaisu. Algoritmin päättyminen voidaan havaita seuraavasti: Jokaisella silmukan kierroksella purkista poistetaan kaksi papua ja palautetaan yksi papu. Näin ollen papujen määrä N(P) pienenee joka kierroksella ja saavuttaa lopulta arvon 1. Siten algoritmi päättyy (ja N(P) on siis konvergentti). Tarkastellaan vielä viimeisen pavun väriä. Jos purkissa on kaksi papua, niin on kaksi mahdollisuutta: 1. Purkissa on joko kaksi mustaa tai kaksi valkoista papua. Tällöin viimeiseksi purkkiin jää musta papu. 2. Purkissa on valkoinen ja musta papu. Tällöin viimeiseksi purkkiin jää valkoinen papu. Koodia tutkimalla huomataan, että valkoisia papuja vähennetään joko kahdella tai ei lainkaan. Näin ollen saadaan taas kaksi mahdollisuutta: 1. Purkissa on alun perin parillinen määrä valkoisia papuja. Koska jokaisen kierroksen jälkeen purkkiin myös jää parillinen määrä valkoisia papuja, niin kaksi viimeistä ovat joko kaksi mustaa tai kaksi valkoista, jolloin viimeiseksi purkkiin jää musta papu. 2. Purkissa on alun perin pariton määrä valkoisia papuja. Koska jokaisen kierroksen jälkeen purkkiin myös jää pariton määrä valkoisia papuja, niin kaksi viimeistä ovat musta ja valkoinen papu, jolloin viimeiseksi purkkiin jää valkoinen papu. Siten laskemalla valkoiset pavut alussa voidaan lopputulos tietää: Jos alussa valkoisia papuja on parillinen määrä, niin viimeinen papu on musta. Jos taas alussa valkoisia papuja on pariton määrä, niin viimeinen papu on valkoinen.

Tehtävä 2.2 Seuraava ongelma tunnetaan selkäreppuongelmana (knapsack problem): On annettu kokonaislukujen joukko S = {s 1,s 2,,s n} ja kokonaisluku T. Etsi joukon S sellainen osajoukko (mikäli sellainen osajoukko on olemassa), että sen alkioiden summa on tarkalleen T. Esimerkiksi, kun S = {5,10,1,2,11}, niin jos T=24, on olemassa ratkaisu ({1,2,10,11}), mutta jos T=25, ratkaisua ei ole. Näytä, että mikään seuraavista algoritmeista ei ole oikea ratkaisu selkäreppuongelmaan: a) Valitaan osajoukon alkiot joukosta S järjestyksessä vasemmalta oikealle. Luku lisätään, jos osajoukon summa ei ylitä lukua T (first-fit). b) Valitaan osajoukon alkiot joukosta S järjestyksessä pienimmästä suurimpaan (best-fit). c) Valitaan osajoukon alkiot joukosta S järjestyksessä suurimmasta pienimpään. Ratkaisu. Algoritmin vääräksi osoittamiseen tarvitaan ainoastaan yksi vastaesimerkki, ts. laillinen syöte, jolla algoritmi toimii väärin. Tässä tapauksessa on löydettävä sellainen joukko S ja summa T, että joukon S alkioista voidaan muodostaa summa T, mutta algoritmi ei löydä sitä. Valitaan nyt S = {8,5,4,11} ja T = 20. Tällöin ongelmalla on ratkaisu {4,5,11}. Tutkitaan miten annetut algoritmit käyttäytyvät. a) Algoritmi valitsee luvut vasemmalta järjestyksessä {8,5,4} ja 11 ei mahdu. Näin ollen algoritmi ei löydä ratkaisua. b) Algoritmi valitsee luvut pienimmästä suurimpaan järjestyksessä {4,5,8} ja luku 11 ei mahdu. Algoritmi ei löydä ratkaisua. c) Algoritmi valitsee luvut suurimmasta pienimpään järjestyksessä {11,8} ja lisää ei mahdu. Näin ollen tämäkään algoritmi ei löydä ratkaisua. Mikään algoritmeista ei siis ole oikea ratkaisu ongelmaan. Tehtävä 2.3 Seuraavan algoritmin oletetaan laskevan syötteenä saamansa taulukon alkioiden summan. Syöte: Taulukko A[1,..,n], n >= 1 Tuloste: Taulukon alkioiden summa ALKIOIDEN_SUMMA(A) 1. sum = 0 2. i = 1 3. while i<=n 4. sum = sum + A[i] 5. i = i+1 6. return sum Laske algoritmia käyttäen taulukon A = {3,4,2} alkioiden summa (vastaus:9). Osoita algoritmi oikeaksi. Osoita algoritmin päättyminen sopivan konvergentin avulla. Muotoile ja todista oikeaksi silmukkainvariantti, joka vahvistaa algoritmin tuottavan oikean tuloksen.

Ratkaisu. Lasketaan algoritmilla aluksi taulukon A = {3,4,2} alkioiden summa. Nyt siis A[1]=3, A[2]=4 ja A[3]=2. Nyt n=3 ja aluksi sum=0 sekä i=1. Silmukan ensimmäisellä kierroksella sum päivittyy arvoon 0+A[1]=3 ja i arvoon 2. Seuraavalla kierroksella sum päivittyy arvoon 3+A[2] = 3+4 = 7 ja i arvoon 3. Kolmannella kierroksella sum päivittyy arvoon 7+A[3] = 7+2 = 9 ja i arvoon 4. Nyt i > n, joten seuraavalle kierrokselle ei enää mennä vaan algoritmi päättyy ja palauttaa arvon 9, kuten pitääkin. Todistetaan nyt algoritmi oikeaksi. Algoritmin varsinaisen työn tekee silmukka. Sen ulkopuolella on vain kaksi sijoituskäskyä ja return. Tällaisessa algoritmissa oikeellisuus liittyy keskeisesti silmukkainvarianttiin. Algoritmin päättymisen takaa konvergenttina i, joka alkuarvolla 1 mahdollistaa pääsyn silmukkaan, kasvaa jokaisella silmukan kierroksella ja saavuttaessaan arvon n+1 lopettaa silmukan suorittamisen. Sen jälkeen algoritmi päättyy ja palauttaa tuloksen. Osoitetaan sitten algoritmin osittainen oikeellisuus. Määritellään silmukkainvariantti: Rivillä 3 muuttujan sum arvo k:nnen kierroksen jälkeen on taulukon arvojen A[1],..., A[k] summa A[1]+...+A[k] ja i=k+1. Aluksi i=1 ja sum=0. Ensimmäisen kierroksen jälkeen sum = A[1] ja i=2. Invariantti on siis alussa voimassa. Invariantin ylläpito: Tehdään oletus, että k < n+1 ja että invariantti on voimassa k:nnen kierroksen jälkeen eli sum=a[1]+...+a[k] ja i=k+1. Seuraavalla (eli k+1:nnellä) kierroksella rivillä 4 sijoitetaan sum = sum + A[k+1] = A[1]+...+A[k] + A[k+1]. Rivillä 5 kasvatetaan i:n arvoa yhdellä joten kierroksen jälkeen sum = A[1]+...+A[k]+A[k+1] ja i=k+2. Invariantti pysyy siis voimassa. Loppu: Invariantti on alussa voimassa ja säilyy jokaisella kierroksella. Siten lopussa, kun i=n+1, on sum = A[1]+...+A[n] eli taulukon arvojen summa. Algoritmin osittainen oikeellisuus on todistettu. Algoritmi on oikeellinen, koska se on osittain oikeellinen ja päättyy.

Tehtävä 2.4 Seuraavan algoritmin tulisi kääntää syötetaulukon alkioiden järjestys päinvastaiseksi: Syöte: Taulukko A[0,1,..,n-1], n >= 1 (n siis taulukon koko) Tuloste: Kääntää taulukon A alkiot päinvastaiseen järjestykseen REVERSE(A,n) 1. i = 0 2. while i <= n/2 3. temp = A[i] 4. A[i] = A[n-i-1] 5. A[n-i-1] = temp 6. i = i+1 7. return Algoritmi ei kuitenkaan ole korrekti. Implementoi algoritmi ja yritä löytää virhe. Korjaa tämän jälkeen ohjelma (ja algoritmi) toimimaan oikein. Ratkaisu. Suoritetaan algoritmia aluksi kolmepaikkaisella taulukolla A = [1,2,3]. Nyt siis n=3. Näin ollen while-silmukan ensimmäisellä kierroksella i=0 ja n-1-i=2; tällöin vaihdetaan taulukon alkiot A[0] ja A[2], eli taulukko on [3,2,1]. Silmukka suoritetaan vielä muuttujan i arvolla 1, jolloin i=1 ja n-1-i=1; vaihdetaan taulukon alkiot A[1] ja A[1]. Vaihdolla ei ole vaikutusta ja taulukko jää tilaan [3,2,1]. Algoritmi toimii siis tässä tapauksessa oikein. Suoritetaan algoritmia seuraavaksi nelipaikkaisella taulukolla A = [1,2,3,4]. Nyt siis n=4. Näin ollen whilesilmukan ensimmäisellä kierroksella i=0 ja n-1-i=3; tällöin vaihdetaan taulukon alkiot A[0] ja A[3], eli taulukko on [4,2,3,1]. Silmukka suoritetaan seuraavaksi muuttujan i arvolla 1, jolloin i=1 ja n-1-i=2; vaihdetaan taulukon alkiot A[1] ja A[2]. Taulukko on [4,3,2,1], mikä olisi oikea lopputulos. Silmukka suoritetaan kuitenkin vielä, kun i=2, jolloin n-i-1=1; jälleen vaihdetaan taulukon alkiot A[1] ja A[2] ja taulukko jää tilaan [4,2,3,1]. Algoritmi tuottaa siis tässä tapauksessa väärän tuloksen. Yleistämällä yllä oleva päättely huomataan, että algoritmi toimii oikein, kun taulukossa on pariton määrä alkioita. Sen sijaan, kun taulukossa on parillinen määrä alkioita, algoritmi vaihtaa taulukon keskimmäiset alkiot takaisin alkuperäiseen järjestykseen ja tuottaa (yleensä) väärän tuloksen. Tätä voi tarkastella empiirisesti implementoimalla algoritmin. Edellisen tarkastelun perusteella voidaan päätellä, että algoritmi toimii muuten oikein, mutta while-silmukkaa suoritetaan liian pitkälle. Näin ollen algoritmin voi korjata helposti: oikea versio on Syöte: Taulukko A[0,1,..,n-1], n >= 1 (n siis taulukon koko) Tuloste: Kääntää taulukon A alkiot päinvastaiseen järjestykseen REVERSE(A,n) 1. i = 0 2. while i < n/2 3. temp = A[i] 4. A[i] = A[n-i-1] 5. A[n-i-1] = temp 6. i = i+1 7. return

Tehtävä 2.5 Ns. puolitushaun avulla voidaan hakea annettu arvo taulukosta, jossa alkiot ovat suuruusjärjestyksessä. Algoritmi toimii siten, että aluksi luetaan taulukon puolivälissä oleva arvo, jonka perusteella tiedetään, onko haettu arvo alku- vai loppupuolella taulukkoa. Tämän jälkeen puolitetaan jäljellä oleva osa, minkä jälkeen tiedetään missä taulukon neljänneksessä haettu arvo on. Näin jatkamalla löydetään arvo taulukosta tai havaitaan, että arvoa ei ole taulukossa. Seuraava iteratiivinen ohjelma pyrkii toteuttamaan puolitushaun järjestettyyn taulukkoon. Implementointi on kuitenkin virheellinen. Yritä löytää virhe. Implementoi ohjelma (joko C- tai Python-kielellä) ja yritä löytää testitapaus, jolla ohjelma toimii virheellisesti. Syöte: Taulukko A[1,..,n], n >= 1, taulukon alkiot ovat kasvavassa järjestyksessä A[1] <= A[2] <= <= A[n]. Luku x jota haetaan taulukosta. Tulostus: Alkion x indeksi taulukossa tai arvo -1, jos x ei esiinny taulukossa. HAKU(A,x) 1. low=1 2. up=n 3. while low <= up 4. r = (low + up)/2 5. if A[r] < x 6. low = r 7. else if A[r] > x 8. up = r 9. else 10. return r 11. return -1 Merkintä x ( floor ) tarkoittaa suurinta kokonaislukua, joka on korkeintaan yhtäsuuri kuin x. Ratkaisu. Algoritmin ongelma on, että hakuintervalli ei pienene kaikilla syötteillä. Esimerkiksi, jos taulukko on [10,20,30,40,50] ja siitä haetaan arvoa 50, niin indeksimuuttujat päivitetään seuraavasti: low = 1 up = 5 low = 3 up = 5 low = 4 up = 5 low = 4 up = 5 jne. Algoritmi jää siis ikuiseen silmukkaan. Samoin käy haettaessa mitä tahansa arvoa, joka ei ole taulukossa. Algoritmi voidaan korjata huomaamalla, että arvo A[r] on jo tarkastettu, joten sitä ei tarvitse enää ottaa huomioon. Näin ollen algoritmissa voidaan muuttaa rivi 6 muotoon low = r+1 ja rivi 8 muotoon up = r-1. Tällöin algoritmi toimii oikein. Nämä asiat voi havaita kirjoittamalla algoritmista ohjelma.