Kesän 2011 Ohjelmoinnin jatkokurssi muodostuu kolmesta tehtäväsarjasta, joissa jokaisessa on 16 tehtävää:
Perustehtävät (11 kpl) ovat suoraviivaisia tehtäviä kurssin tärkeimmistä asioista. Perustehtävät kannattaa tehdä aina kokonaan.
Lisätehtävät (4 kpl) ovat syventäviä tehtäviä, joissa kurssin asioita sovelletaan uudenlaisissa tilanteissa.
Pähkinä (1 kpl) on haastava tehtävä, jonka ratkaiseminen vaatii miettimistä ja oivaltamista.
Tehtävät palautetaan esittelemällä niitä ohjaajalle ohjelmointipajassa. Osan 1 tehtävien viimeinen palautuspäivä on torstai 9.6., mutta tehtäviä voi mielellään palauttaa aiemminkin.
Voit valita itse, kuinka paljon vietät aikaa ohjelmointipajassa. Voit tehdä kaikki tehtävät ohjelmointipajassa tai käydä vain palauttamassa valmiit tehtävät – tai tyypillisesti jotain siltä väliltä.
Tee tätä tehtäväsarjaa varten NetBeans-projekti
LyyraKortti
.
Tässä tehtäväsarjassa tehdään ohjelma, joka jäljittelee Lyyra-kortin käyttämistä Unicafe-ravintoloissa. Lyyra-kortille voi ladata rahaa ja sillä voi ostaa aterioita.
Lue materiaalista luku 1 ja tee seuraavat tehtävät:
Tee luokka LyyraKortti
, jonka tietosisältönä on kortin omistajan
nimi ja kortilla oleva rahamäärä. Kortin omistajan nimi annetaan luokan
konstruktorissa, ja kortilla oleva rahamäärä on aluksi 0,00 euroa. Tee myös
metodi lisaaRahaa
, joka lisää rahaa kortille, sekä metodi
toString
, joka muodostaa merkkijonoesityksen kortista.
Seuraava pääohjelma testaa luomaasi luokkaa:
public class Main { public static void main(String[] args) { LyyraKortti kortti = new LyyraKortti("Olli Opiskelija"); System.out.println(kortti); kortti.lisaaRahaa(12); System.out.println(kortti); kortti.lisaaRahaa(5); System.out.println(kortti); } }
Ohjelman tulostuksen tulisi olla seuraava:
Olli Opiskelija (0.0 euroa) Olli Opiskelija (12.0 euroa) Olli Opiskelija (17.0 euroa)
Unicafessa on kahdenlaisia aterioita: "edullisesti" maksaa 2,40 euroa ja
"maukkaasti" maksaa 4,00 euroa. Lisää LyyraKortti
-luokkaan metodit
syoEdullisesti
ja syoMaukkaasti
, jotka vähentävät
kortin rahamäärää vastaavasti. Jos kortilla ei ole riittävästi rahaa, metodit
eivät muuta rahamäärää lainkaan.
Seuraava pääohjelma testaa luokan toimintaa:
public class Main { public static void main(String[] args) { LyyraKortti kortti = new LyyraKortti("Olli Opiskelija"); kortti.lisaaRahaa(20); System.out.println(kortti); kortti.syoEdullisesti(); System.out.println(kortti); kortti.syoMaukkaasti(); kortti.syoEdullisesti(); System.out.println(kortti); } }
Ohjelman tulostuksen tulisi olla seuraava:
Olli Opiskelija (20.0 euroa) Olli Opiskelija (17.6 euroa) Olli Opiskelija (11.2 euroa)
Varmista myös, että seuraava pääohjelma toimii:
public class Main { public static void main(String[] args) { LyyraKortti kortti = new LyyraKortti("Olli Opiskelija"); kortti.lisaaRahaa(2.4); System.out.println(kortti); kortti.syoMaukkaasti(); System.out.println(kortti); kortti.syoEdullisesti(); System.out.println(kortti); } }
Ohjelman tulostuksen tulisi olla seuraava:
Olli Opiskelija (2.4 euroa) Olli Opiskelija (2.4 euroa) Olli Opiskelija (0.0 euroa)
Lue materiaalista luku 2 ja tee seuraavat tehtävät:
Lisää LyyraKortti
-luokkaan vaihtoehtoinen konstruktori, jossa
voi ilmoittaa nimen lisäksi kortilla aluksi olevan rahamäärän.
Seuraava ohjelma testaa luokkaa:
public class Main { public static void main(String[] args) { LyyraKortti kortti1 = new LyyraKortti("Olli Opiskelija"); LyyraKortti kortti2 = new LyyraKortti("Kaisa Koodari", 10); System.out.println(kortti1); System.out.println(kortti2); } }
Ohjelman tulostuksen tulisi olla seuraava:
Olli Opiskelija (0.0 euroa) Kaisa Koodari (10.0 euroa)
Kortille ladataan rahaa käytännössä Unicafen kassapäätteen kautta. Tee
luokka Unicafe
, jonka sisältönä on kassassa oleva rahamäärä. Tee
lisäksi metodit lataaKateisella
ja lataaKortilla
,
jotka lataavat Lyyra-kortille annetun rahamäärän käteisellä tai pankkikortilla.
Jos lataus tapahtuu käteisellä, kassan rahamäärä lisääntyy.
Seuraava pääohjelma testaa luokkia:
public class Main { public static void main(String[] args) { Unicafe exactum = new Unicafe("Exactum"); LyyraKortti kortti = new LyyraKortti("Olli Opiskelija"); System.out.println(exactum); System.out.println(kortti); exactum.lataaKateisella(kortti, 20); System.out.println(exactum); System.out.println(kortti); exactum.lataaKortilla(kortti, 10); System.out.println(exactum); System.out.println(kortti); } }
Ohjelman tulostuksen tulisi olla seuraava:
Exactum (0.0 euroa) Olli Opiskelija (0.0 euroa) Exactum (20.0 euroa) Olli Opiskelija (20.0 euroa) Exactum (20.0 euroa) Olli Opiskelija (30.0 euroa)
Tee tätä tehtäväsarjaa varten NetBeans-projekti
Kirjanpito
.
Tässä tehtäväsarjassa teemme luokan, jonka avulla voi pitää kirjaa menoista ja tuloista. Kirjanpitoon tallennetaan merkintöjä, joihin liittyy kuvaus ja rahamäärä (positiivinen tai negatiivinen).
Tee luokka Merkinta
, jonka sisältönä on merkinnän kuvaus ja
rahamäärä. Lisää luokkaan konstruktori, jolle annetaan kuvaus ja rahamäärä,
metodit haeKuvaus
ja haeRahamaara
sekä sopiva metodi
toString
.
Seuraava pääohjelma testaa luokkaa:
public class Main { public static void main(String[] args) { Merkinta eka = new Merkinta("palkka", 2500); System.out.println(eka.haeKuvaus()); System.out.println(eka.haeRahamaara()); System.out.println(eka); } }
Ohjelman tulostuksen tulisi olla seuraava:
palkka 2500.0 palkka (2500.0 euroa)
Tee luokka Kirjanpito
, jonka sisältönä on joukko
Merkinta
-olioita. Käytännössä oliot kannattaa tallentaa
ArrayList
-rakenteeseen. Lisää luokkaan metodi
lisaaMerkinta
, joka lisää merkinnän kirjanpitoon, sekä metodi
tulostaMerkinnat
, joka tulostaa kaikki merkinnät.
Seuraava pääohjelma testaa luokkia:
public class Main { public static void main(String[] args) { Kirjanpito kirjanpito = new Kirjanpito(); kirjanpito.lisaaMerkinta(new Merkinta("palkka", 2500)); kirjanpito.lisaaMerkinta(new Merkinta("ravintola", -20)); kirjanpito.lisaaMerkinta(new Merkinta("ostokset", -45)); kirjanpito.tulostaMerkinnat(); } }
Ohjelman tulostuksen tulisi olla seuraava:
palkka (2500.0 euroa) ravintola (-20.0 euroa) ostokset (-45.0 euroa)
Lisää luokkaan Kirjanpito
metodi laskeSumma
, joka
palauttaa kaikkien merkintöjen rahamäärien summan. Lisää myös metodit
etsiSuurin
ja etsiPienin
, jotka palauttavat suurinta
ja pienintä rahamäärää vastaavan merkinnän.
Seuraava pääohjelma testaa luokkaa:
public class Main { public static void main(String[] args) { Kirjanpito kirjanpito = new Kirjanpito(); kirjanpito.lisaaMerkinta(new Merkinta("palkka", 2500)); kirjanpito.lisaaMerkinta(new Merkinta("ravintola", -20)); kirjanpito.lisaaMerkinta(new Merkinta("ostokset", -45)); System.out.println("Summa: " + kirjanpito.laskeSumma()); System.out.println("Suurin: " + kirjanpito.etsiSuurin()); System.out.println("Pienin: " + kirjanpito.etsiPienin()); } }
Ohjelman tulostuksen tulisi olla seuraava:
Summa: 2435.0 Suurin: palkka (2500.0 euroa) Pienin: ostokset (-45.0 euroa)
Tee tätä tehtäväsarjaa varten NetBeans-projekti
KielenTunnistaminen
.
Tekstiaineistojen perusteella on laskettu, että suomenkielisessä tekstissä keskimäärin 48 % kirjaimista on vokaaleja, kun taas englanninkielisessä tekstissä keskimäärin 40 % kirjaimista on vokaaleja. Tämän tuloksen perusteella voimme tehdä ohjelman, joka yrittää päätellä tekstin kielen sen vokaalien määrästä.
Lue materiaalista luku 3 ja tee seuraavat tehtävät:
Tee staattinen luokka Kielitutkimus
, jonka metodeilla
laskeVokaalit
ja laskeKonsonantit
voi laskea annetun
lauseen vokaalien ja konsonanttien määrän.
Seuraava pääohjelma testaa luokkaa:
public class Main { public static void main(String[] args) { String lause = "Lyhyestä virsi kaunis."; int vokaalit = Kielitutkimus.laskeVokaalit(lause); int konsonantit = Kielitutkimus.laskeKonsonantit(lause); System.out.println("Vokaaleja: " + vokaalit); System.out.println("Konsonantteja: " + konsonantit); } }
Ohjelman tulostuksen tulisi olla seuraava:
Vokaaleja: 9 Konsonantteja: 10
Lisää luokkaan Kielitutkimus
metodi
laskeVokaalisuhde
, jolla voi laskea annetun lauseen
vokaalisuhteen. Jos lauseessa on v vokaalia ja k konsonanttia,
vokaalisuhteen saa laskettua kaavalla v / (v + k).
Seuraava pääohjelma testaa luokkaa:
public class Main { public static void main(String[] args) { String lause = "Lyhyestä virsi kaunis."; double vokaalisuhde = Kielitutkimus.laskeVokaalisuhde(lause); System.out.println("Vokaalisuhde: " + vokaalisuhde); } }
Ohjelman tulostuksen tulisi olla seuraava:
Vokaalisuhde: 0.47368421052631576
Lauseen kirjaimista reilut 47 % oli siis vokaaleja.
Tee ohjelma, joka kysyy käyttäjältä lauseen ja päättelee sen kielen (suomi tai englanti) vokaalisuhteen avulla. Käytännössä ohjelman kannattaa veikata sitä kieltä, jonka vokaalisuhde on lähempänä käyttäjän antaman lauseen vokaalisuhdetta.
Suomen kielen vokaalisuhde on 48 %, ja englannin kielen vokaalisuhde on 40 %.
Ohjelmasi tulisi toimia seuraavasti:
Anna lause: Lyhyestä virsi kaunis. Lause on suomea.
Anna lause: Does this program work? Lause on englantia.
Vokaalisuhteen lisäksi on monia muitakin tapoja päätellä, onko käyttäjän antama lause suomea vai englantia. Esimerkiksi jos lauseessa on kirjain ä tai ö, lause on lähes varmasti suomea. Toisaalta jos lauseessa on sana "the", lause on lähes varmasti englantia.
Lisää kielentunnistajaan haluamasi lisäominaisuus, joka parantaa sen luotettavuutta.
Lisätehtävät alkavat tästä:
Tee tätä tehtäväsarjaa varten NetBeans-projekti Tikkupeli
.
Tikkupelissä pöydällä on kasa tikkuja, ja pelaajat nostavat vuorotellen 1–3 tikkua. Pelin häviää se, joka nostaa viimeisen tikun.
Seuraavassa on esimerkki tikkupelin kulusta:
Yksi tapa tehdä tikkupeliin tekoäly on analysoida peli matemaattisesti ja laatia tekoäly sen perusteella. Ehkä hauskempi tapa on tehdä oppiva tekoäly, joka opettelee itse tikkupelin strategian. Juuri näin teemme tässä tehtäväsarjassa.
Tekoälyn toiminta tulee olemaan seuraava:
Tekoälyllä on jokaista tikkujen määrää vastaava hattu, jossa on joukko palloja. Jokaiseen palloon on merkitty luku väliltä 1–3. Aluksi jokaisessa hatussa on yksi jokaista palloa.
Pelin joka vaiheessa tekoäly nostaa yhden pallon tikkumäärää vastaavasta hatusta ja ottaa pöydältä siihen merkityn määrän tikkuja. Aina kun tekoäly ottaa hatusta pallon, se asettaa pallon hatun viereen.
Pelin päätteeksi jos tekoäly voitti, se lisää jokaiseen hattuun hatun vieressä olevan pallon ja toisen samanlaisen pallon. Jos taas tekoäly hävisi, se heittää menemään hattujen vieressä olevat pallot. Ideana on siis, että voittoon johtavat valinnat muuttuvat todennäköisimmiksi ja häviöön johtavat valinnat muuttuvat epätodennäköisimmiksi.
Tarkastellaan esimerkkiä, jossa tikkujen määrä on aluksi 10. Tekoälyn hattujen sisällöt ovat seuraavat:
hattu | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
sisältö | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3 |
Peli saattaa edetä seuraavasti:
Pelin kuluessa tekoälyn hattujen tilanne on muodostunut seuraavaksi:
hattu | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
sisältö | 1,2,3 | 1,2,3 | 1,2,3 | 1,2 | 1,2,3 | 1,2,3 | 1,3 | 1,2,3 | 1,2,3 | 1,2,3 |
vieressä | 3 | 2 |
Koska peli päättyi tekoälyn voittoon, pelin jälkeen tekoälyn hattujen tilanteeksi tulee seuraava:
hattu | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
sisältö | 1,2,3 | 1,2,3 | 1,2,3 | 1,2,3,3 | 1,2,3 | 1,2,3 | 1,2,2,3 | 1,2,3 | 1,2,3 | 1,2,3 |
Nyt tekoäly ottaa tästä lähtien 4 tikun tapauksessa luultavammin 3 tikkua ja 7 tikun tapauksessa luultavammin 2 tikkua.
Tee luokka Hattu
, johon on tallennettu hatussa olevat pallot
sekä mahdollinen hatun viereen asetettu pallo. Luokkaan tulevat seuraavat
metodit:
nostaPallo
nostaa satunnaisen pallon hatun
viereen ja palauttaa sen lukuarvon
lisaaPallo
lisää hattuun sen vieressä olevan pallon ja
toisen samanlaisen pallon
poistaPallo
heittää menemään hatun vieressä olevan
pallon
Toteuta metodit niin, että hatussa on aina ainakin yksi kappale jokaista palloa ja yhteensä korkeintaan 1000 palloa.
Lisää myös luokkaan jokin keino testata sen toimintaa, ja varmista, että luokka toimii oikein.
Tee luokka Tekoaly
, johon on tallennettu tikkumääriä
1–100 vastaavat hatut. Luokkaan tulevat seuraavat metodit:
haeSiirto
valitsee siirron hatusta tikkumäärän
perusteella
paivitaVoitto
päivittää hattujen sisältöä, kun tekoäly
voitti lopulta pelin
paivitaHavio
päivittää hattujen sisältöä, kun tekoäly
hävisi lopulta pelin
Lisää myös luokkaan jokin keino testata sen toimintaa, ja varmista, että luokka toimii oikein.
Tee ohjelma, jonka avulla ihminen voi pelata tekoälyä vastaan. Aina pelin jälkeen tekoäly päivittää hattujaan pelin tuloksen mukaisesti. Tekoäly pelaa aluksi satunnaisesti mutta alkaa oppia pikkuhiljaa strategiaa.
Tekoälyn oppiminen edistyy hitaasti, jos se pelaa vain ihmistä vastaan. Ratkaisu ongelmaan on antaa tekoälyjen pelata keskenään todella monta kertaa. Tee ohjelma, joka luo kaksi tekoälyä ja antaa niiden pelata miljoona kertaa toisiaan vastaan. Tämän jälkeen ohjelma valitsee toisen tekoälyistä, joka on valmis taistoon ihmistä vastaan.
Miten hyvin koulutettu tekoäly pärjää ihmistä vastaan? Millaisen strategian se on omaksunut?
Tee tätä tehtäväsarjaa varten NetBeans-projekti
JarjestyksetJaOsajoukot
.
Lukujen 1, 2 ja 3 järjestykset (permutaatiot) ovat seuraavat:
Lukujen 1, 2 ja 3 osajoukot (kombinaatiot) ovat seuraavat:
Tee ohjelma, joka kysyy käyttäjältä lukujen määrän ja tulostaa vastaavat järjestykset ja osajoukot.
Ohjelmasi tulisi toimia seuraavasti:
Lukujen määrä: 3 Järjestykset: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 Osajoukot: 1 2 3 1 2 1 3 2 3 1 2 3
Lukujen määrä: 4 Järjestykset: 1 2 3 4 1 2 4 3 1 3 2 4 1 3 4 2 1 4 2 3 1 4 3 2 2 1 3 4 2 1 4 3 2 3 1 4 2 3 4 1 2 4 1 3 2 4 3 1 3 1 2 4 3 1 4 2 3 2 1 4 3 2 4 1 3 4 1 2 3 4 2 1 4 1 2 3 4 1 3 2 4 2 1 3 4 2 3 1 4 3 1 2 4 3 2 1 Osajoukot: 1 2 3 4 1 2 1 3 1 4 2 3 2 4 3 4 1 2 3 1 2 4 2 3 4 1 2 3 4