Takaisin kurssin pääsivulle

Tehtävät, osa 1

Kesän 2011 Ohjelmoinnin jatkokurssi muodostuu kolmesta tehtäväsarjasta, joissa jokaisessa on 16 tehtävää:

Palautus

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ä.

Lyyra-kortti

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:

1. LyyraKortti

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)

2. Kortilla maksaminen

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:

3. Uusi konstruktori

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)

4. Unicafe

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)

Kirjanpito

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).

5. Merkinta

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)

6. Kirjanpito

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)

7. Tilastointi

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)

Kielen tunnistaminen

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:

8. Vokaalit ja konsonantit

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

9. Vokaalisuhde

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.

10. Kielentunnistaja

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.

11. Oma ominaisuus

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ä:

Tikkupeli

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 idea

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.

Esimerkki

Tarkastellaan esimerkkiä, jossa tikkujen määrä on aluksi 10. Tekoälyn hattujen sisällöt ovat seuraavat:

hattu123456 78910
sisältö1,2,31,2,31,2,31,2,3 1,2,31,2,31,2,31,2,31,2,3 1,2,3

Peli saattaa edetä seuraavasti:

Pelin kuluessa tekoälyn hattujen tilanne on muodostunut seuraavaksi:

hattu123456 78910
sisältö1,2,31,2,31,2,31,2 1,2,31,2,31,31,2,31,2,3 1,2,3
vieressä    3  2    

Koska peli päättyi tekoälyn voittoon, pelin jälkeen tekoälyn hattujen tilanteeksi tulee seuraava:

hattu123456 78910
sisältö1,2,31,2,31,2,31,2,3,3 1,2,31,2,31,2,2,31,2,31,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.

12. Hattu

Tee luokka Hattu, johon on tallennettu hatussa olevat pallot sekä mahdollinen hatun viereen asetettu pallo. Luokkaan tulevat seuraavat metodit:

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.

13. Tekoaly

Tee luokka Tekoaly, johon on tallennettu tikkumääriä 1–100 vastaavat hatut. Luokkaan tulevat seuraavat metodit:

Lisää myös luokkaan jokin keino testata sen toimintaa, ja varmista, että luokka toimii oikein.

14. Ihminen vs. tekoäly

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.

15. Teho-opetus

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?

Pähkinä

Tee tätä tehtäväsarjaa varten NetBeans-projekti JarjestyksetJaOsajoukot.

16. Järjestykset ja osajoukot

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

Takaisin kurssin pääsivulle