Demo 10

Palauta viimeistään ma klo 11:59.

Ajankäyttösi tällä viikolla

Työtuntien kirjaamisesta saa 0.5 demopistettä. Aseta pisteesi Set Custom Points -toiminnolla.

Demokerran päätteeksi kirjoita arvio tällä viikolla käyttämästäsi työmäärästä. Laske työmäärään mukaan kaikki tällä viikolla käyttämäsi aika: lähiopetukseen osallistuminen, oppimateriaalin lukeminen, demotehtävien tekeminen, luentovideon katsominen, demojen purkutilaisuuteen osallistuminen (maanantaina) ja niin edelleen. Voit päivittää lukua viikon edetessä, se voi helpottaa arvion tekemistä. Huom! Siis tähän ei laiteta kurssin alusta kaikkia tunteja yhteensä, vaan vain tämän viikon tunnit.

# d10tunnit


Huomautus tehtävien pisteytyksistä

Oppimistavoitteet

Tämän demokerran jälkeen

  • muistat mitä rekursio tarkoittaa ja miten tehdään rekursiivinen funktio
  • osaat soveltaa silmukoita kombinaatiotehtävään
  • olet tutustunut poikkeuksiin (Exception) ja poikkeusten käsittelyyn

Tehtävä 1

Tee funktio TulostaNollaanSaakka, joka tulostaa annetusta luvusta nollaan saakka. Funktio tulee toteuttaa käyttäen rekursiota, silmukkarakenteita ei saa käyttää.

Esimerkiksi

TulostaNollaanSaakka(5);
// tulostaa
// 5
// 4
// 3
// 2
// 1
// 0

Ohjelmassa on valmiina luokka, ja lisäksi pääohjelma jota et näe (ks. Näytä koko koodi). Palautuslaatikkoon tulee kirjoittaa ainoastaan pyydetty funktio.

Arviointi: Tehtävässä on automaattitarkistin. Oikea tuloste 1 p., väärä tuloste 0 p.

# d10_t1

Tehtävä 2

Tee funktio SummaNollaanSaakka, joka palauttaa lukujen summan annetusta luvusta nollaan saakka. Funktio tulee toteuttaa käyttäen rekursiota, silmukkarakenteita ei saa käyttää.

Esimerkiksi

int summa = SummaNollaanSaakka(5);
Console.WriteLine(summa); // 15, koska 5+4+3+2+1+0 = 15

Ohjelmassa on valmiina luokka, ja lisäksi pääohjelma jota et näe (ks. Näytä koko koodi). Palautuslaatikkoon tulee kirjoittaa ainoastaan pyydetty funktio.

Arviointi: Tehtävässä on automaattitarkistin. Oikea tulos 1 p., väärä tulos 0 p.

# d10_t2

Tehtävä 3

Tee funktio LaskeMerkit, joka palauttaa halutun merkin esiintymien määrän merkkijonossa. Jos etsitään aakkosta, tulee mukaan laskea sekä suur- että pienaakkoset. Funktio tulee toteuttaa käyttäen rekursiota, silmukkarakenteita ei saa käyttää.

Esimerkiksi

string mjono = "Kolme miestä istuu saunassa";
int lkm = LaskeMerkit(mjono, 'A');
Console.WriteLine(lkm); // 3

Vinkki: Saat otettua merkkijonosta osan Substring-metodilla. Esimerkiksi

string mjono = "Kolme miestä istuu saunassa";
string kaikkiPaitsiEka = mjono.Substring(1);
// kaikkiPaitsiEka on nyt "olme miestä istuu saunassa"

Vaihtoehtoisesti voit ottaa merkkijonosta kaiken paitsi viimeisen merkin:

string mjono = "Kolme miestä istuu saunassa";
string kaikkiPaitsiVika = mjono.Substring(0, mjono.Length - 1);
// kaikkiPaitsiVika on nyt "Kolme miestä istuu saunass"

Lisätietoa kiinnostuneille: Voit Substringin sijaan käyttää ns. range indexer -ominaisuutta. Saman tapainen "oikotie" on yleistynyt viime vuosina monissa kielissä. Esimerkiksi:

string kaikkiPaitsiEka = mjono[1..]

Ohjelmassa on valmiina luokka, ja lisäksi pääohjelma jota et näe (ks. Näytä koko koodi). Palautuslaatikkoon tulee kirjoittaa ainoastaan pyydetty funktio.

Arviointi: Tehtävässä on automaattitarkistin. Oikea tulos 1 p., väärä tulos 0 p.

# d10_t3

Tehtävä 4

M: 23. Dynaamiset tietorakenteet. Tee Lotto-niminen funktio, joka arpoo ja tulostaa 7 numeroa ja 3 varanumeroa 40:stä.

Funktiota kutsutaan pääohjelmasta ilman argumentteja.

public static void Main()
{
  Lotto();
}

Funktion antaman tulosteen tulisi näyttää tältä:

Onnennumerot: 17 10 6 25 30 12 24 
Lisänumerot: 9 20 13 

Funktion ei tarvitse palauttaa mitään arvoa.

Ohjelmassa on valmiina luokka, ja lisäksi pääohjelma jota et näe (ks. Näytä koko koodi). Palautuslaatikossa on valmiina pieni pätkä valmista koodia. Täydennä funktio.

Arviointi: Tehtävässä on automaattitarkistin. Oikea tuloste 1 p., väärä tuloste 0 p.

# d10_lotto

Sotkemisen voit tehdä myös lisäämällä projektin referensseihin Jypeli:n ja sitten

Jypeli.RandomGen.Shuffle(pallot);

Tai voit ottaa alta valmiin sekoitusalgoritmin.

Valmis sekoitusalgoritmi

Tehtävä 4-5 (1-2 p.)

Tee funktio GeneroiSalasana. Funktio ottaa parametreina seuraavat tiedot:

  • salasanan pituus (int),
  • voiko salasana sisältää suuraakkosia (bool),
  • voiko salasana sisältää numeroita (bool),
  • voiko salasana sisältää erikoismerkkejä (bool)

Funktio palauttaa salasanan näiden parametrien perusteella.

Erikoismerkkejä ovat:

!@#$%&-

Muita erikoismerkkejä ei tässä oteta huomioon.

Esimerkiksi kutsu GeneroiSalasana(r, 10, true, true, true) voisi palauttaa rV30b5E!o1.

Vinkkejä:

  • Tarvitset ohjelmassasi satunnaisuutta käyttäen Random-oliota. Esimerkiksi luvun arpominen väliltä 0-9 onnistuu seuraavasti.
Random r = new Random();
int luku = r.Next(0, 10);
  • Kirjaimen arpominen: (1) Luo sopivista pienaakkosista yksi pitkä merkkijono, (2) arvo Random-olion Next-metodin avulla kokonaisluku väliltä [0, ... merkkijonon pituus], ja (3) ota merkkijonosta kirjain arpomasi luvun mukaisesta indeksistä.
  • Erikoismerkin arpominen: Samoin näistä kannattaa tehdä yksi merkkijono ja arpoa siitä yksi.
  • "Kolikon heiton" (esim. tuleeko yksittäisen kirjaimen olla suuraakkonen vai ei) saat toteutettua esimerkiksi käyttämällä Random-olion NextDoublea, joka antaa desimaaliluvun väliltä 0-1:
Random r = new Random();
if (r.NextDouble() > 0.5) 
{
  ...
}

Huomautus 1: Useiden Random-olioiden luomista pitäisi C#:n dokumentaation mukaan välttää. Niinpä jos haluat generoida salasanoja silmukassa (esimerkiksi pääohjelmassa), tulee Random-olio r luoda yhden kerran koko ohjelmassa (pääohjelman aluksi) ja antaa sitten r argumenttina, sillä muuten arpominen ei käytännössä onnistu. Luonnollisesti Random-olio pitää tällöin lisätä funktion esittelyriville parametrilistaan ensimmäiseksi. Esimerkki pääohjelmasta (voit copy-pastettaa tämän itsellesi):

Random r = new Random();
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(GeneroiSalasana(r, 10, true, true, true));
}

Huomautus 2: Olisi hyvä arvioida, kuinka todennäköisiä kunkin merkin esiintyminen on. Esimerkiksi ovatko kaikki merkit yhtä todennäköisiä, vai onko tietty merkki yhtä todennäköisesti (a) kirjain, (b) numero tai (c) erikoismerkki? Tähän ei ole yhtä ja oikeaa vastausta.

Arviointi: Käytä Set Custom Pointsia. Jos salasanan tuottaminen toimii "jotenkin" voit merkata itsellesi yhden pisteen. Jos kaikkien parametrien huomioon ottaminen toimii, voit merkata kaksi pistettä.

# generoisalasana

Tehtävä 6

M: 24. Poikkeukset. Kirjoita funktio MuutaJono(String s, double oletus), siten, että seuraava ohjelma toimii:

# poikkeuksetd10

Huom Jos kotikoneesi asetukset ovat suomalaisittain, Double.Parse-metodi olettaa argumentin erotinmerkiksi pilkun. Timissä erotinmerkkinä on piste. Jos haluat omalle koneellesi pisteen erotinmerkiksi, laita Parse-metodin argumentiksi:
new System.Globalization.CultureInfo("en-US")

Tämä funktio yrittää siis poimia annetusta merkkijonosta liukuluvun (double) ja palauttaa sen. Mikäli tämä ei onnistu, palauttaa se oletusarvon. Funktiolle on oikeassa elämässä käyttöä koska käyttäjältä saatu syöte on aina merkkijono ja se pitää pystyä muuttamaan reaaliluvuksi laskemista varten. Tuo desimaalierotin on vaikeampi. Parse käyttää sitä erotinta, mikä on järjestelmään asetettu. Oikeasti pitäisi siis vielä osata tulkita oikealla tavalla riippumatta siitä, antaako käyttäjä pilkun vai pisteen. Tässä tehtävässä tuosta ongelmasta ei tarvitse välittää vaan riittää yllä olevaan esimerkkiin käsin vaihtaa piste pilkun tilalle jos järjestelmässäsi on piste desimaalierottimena (C#-koodin vakioissahan se on aina piste).

Kun toteutat funktiota MuutaJono, käytä hyväksi Double-luokan funktiota Double.Parse ja sitä, että jos muuttaminen ei onnistu, Parse heittää poikkeuksen.

V1

Tee Ville-tehtävät: 8.1-8.5. Muista: Villen käyttöohje ja Ville-tehtävien palauttamisohjeet.

# villed10

TDD1

Jos tarkistat vähintään kahden funktion toiminnan automaattisella testillä (ComTest), saat merkitä yhden lisäpisteen. Voit antaa samassa tiedostossa palautetta ja kehitysehdotuksia Comtestin käytöstä.

Mikäli ComTest ei toimi yliopiston mikroluokissa, kokeile ensin asentaa ComTest-VS-plugin. Sitten tarkista, että ComTest haetaan oikeasta paikasta: Valitse Visual Studiossa Tools -> ComTest -> Options. Tarkista, että Path to ComTest.jar executable kentässä on N:\bin\ComTest.jar ja olet yhdistänyt koneesi N-verkkolevyyn. Kysy tarvittaessa ohjaajalta neuvoa.

# D10TDD1

Tehtävä Bonus 1-2 (2 p.)

M: 22. Rekursio.

Tee alla olevaa mallikoodia muokaten ohjelma, joka piirtää kuvan kaltaisen puun rekursiivisesti. Halutessasi voit katsoaa
ideaa Sierpinskin kolmion piirtämisestä.

Anna itsellesi enintään 2 pistettä Set custom points -toiminnolla.

# RekursioPallod10

Beginissä: Hyvä alkukulma piirtämiseen on vaikkapa pii/2 (saat piin arvon kirjoittamalla Math.PI). Pallon säteeksi voit antaa vaikka 100.

Pallo-aliohjelmassa: Kokeile vaihdella suuntaa ja sädettä muuttavia vakioita ja katso miten ne vaikuttavat kuvaan.

B1-2


M: 25. Tietojen lukeminen ulkoisesta lähteestä.

Avaa sivu ja klikkaa sivun "Csv-tiedosto". Huomaa että sivu antaa kuitenkin .xls tiedoston nappulan tekstistä huolimatta. Tästä ei tarvitse erityisesti välittää. Muuta tiedoston nimeksi valuutat.xls. Lisää projektiisi tämä tiedosto klikkaamalla projektin nimen päällä hiiren kakkosnäppäimellä Add -> Existing Item). Laita tiedosto myös kopioitumaan bin-hakemistoon klikkaamalla tiedoston päällä hiiren oikealla -> Properties -> Copy to output directory -> Always copy.

Tiedosto näyttää kutakuinkin tältä

EUR,000001.000000,000001.000000,000001.000000,23/03/2023,08:00
USD,000001.090550,000001.067100,000001.114000,23/03/2023,08:00
JPY,000142.624000,000139.552000,000145.696000,23/03/2023,08:00

Tiedosto voidaan nyt lukea seuraavasti. Lisää ensin Using-lauseisiin lause

using System.IO;

Sitten Main-pääohjelmaan (tämä on annettu palautuslaatikon pohjakoodissa)

string[] valuuttalista;
try
{
    valuuttalista = File.ReadAllLines("valuutat.xls");
}
catch (IOException ex)
{
    Console.WriteLine("Virhe: " + ex.Message);
    return;
}

Tee aliohjelma KyseleValuuttoja, joka kysyy silmukassa käyttäjältä valuuttatunnuksen, ja sitten tulostaa annetun valuutan tiedot ruudulle hieman mukavammin muotoiltuna. Luvut parsitaan double.Parsella jolloin ylimääräisiä nollia ei näytetä.

Anna valuutta >USD
USD: Keskikurssi 1.09055. Myynti 1.0671. Osto 1.114. (23/03/2023)
Anna valuutta >JPY
JPY: Keskikurssi 142.624. Myynti 139.552. Osto 145.696. (23/03/2023)

Ohjelma päättyy, kun käyttäjä antaa tyhjän syötteen.

Huomaa että TIMissä pitää varautua myös siihen, että lukemisesta voi tulla null:

            string komento = Console.ReadLine();
            if ( komento == null || komento.Equals("") ) break;

Kirjoita tähän tekemäsi tiedosto ja tallenna ennen kuin yrität käyttää sitä ohjelmassa.

# valuutattxtd10
# valuutatd10

B3-4

M: 16. Toistorakenteet. Erilaisten 7 numeroa sisältävien lottorivien määrä saadaan binomikertoimen kaavasta: Katso: http://fi.wikipedia.org/wiki/Kombinaatio.

\[\binom {40}{7} = \frac {40!}{7! * (40-7)!} = \frac{34*35*36*37*38*39*40}{ 1*2*3*4*5*6*7} = 18643560\]

Tulos voidaan laskea käyttämällä long -tyyppisiä lukuja. Tee funktio

long NYliK(int n, int k) 

jonka kutsulla

NyliK(40, 7)

saat mainitun tuloksen. Tulosta ei voi laskea keskimmäisestä kaavasta 2, koska \(40!\) ylittäisi reilusti pitkienkin (long) kokonaislukujen lukualueen.

Vinkki: Tässä tehtävässä ei tarvita listoja tms., pelkästään kerto- ja jakolaskuja sekä silmukoita. Vastaus saattaa olla nätimpi, jos avuksi kirjoittaa yhden pienen aliohjelman.

# kombinaatiotd10

B5

Tutki miten C#:issa toimii BigInteger -luokka ja tee NYliK(int n,int k) sen avulla. Tee siis tehtävää 4 vastaava toteutus erityyppisellä kokonaisluvulla. BigInteger luokan käyttö vaatii Numerics-assemblyn käyttöä. Lisää ohjelman alkuun

using System.Numerics;

Täysiin pisteisiin vaaditaan omat testit: Tehtävässä saa oikeasta tulosteesta 0.5 p., testien läpäisemisestä 0.4 p. ja dokumentaation katsomisesta 0.1 p.

# bigIntegerd10

G1-2

Tutki miten C#:ssa voidaan lukea syötettä WWW-osoitteesta ja tee tehtävä B1-2 niin, että tiedot luetaan suoraan netistä.

Voit lukea tiedostoa osoitteesta

https://tim.jyu.fi/files/183746/commercialTransaction.xls
# valuutatNetistad10

G3-4

PNS: Pienimmän neliösumman sovitus on eräs tapa laskea eräänlainen "keskiluku" tai trendi aineistolle. Esimerkiksi meillä on havaintopisteitä, joiden periaatteessa pitäisi muodostaa "suora". Laskemalla PNS-suoran (y = a + bx) kertoimet a ja b voimme piirtää aineistoa parhaiten kuvaavan suoran. Katso http://mathworld.wolfram.com/LeastSquaresFitting.html kertoimien laskukaavat (12) ja (14) ja tee ohjelma, joka piirtää aineiston ja sitä kuvaavan PNS-suoran. Aineisto piirretään tämän pohjatiedoston: Kuvaaja.cs avulla, eli voit käyttää siellä olevaa koodia pohjana itse aineiston piirtämiseen. Suora piirretään Paint -metodissa kutsumalla canvas.DrawLine-metodia. Esimerkki: pns.png (tuossa Javalla tehdyssä kuvassa pallot eivät ole täytettyjä, sitä ei tarvitse yrittää).

# PNSd10

G5-6

Euler problem 67. Laskun pitää mennä alle minuuttiin. Yksi lisäpiste jos lasku menee "erittäin nopeasti" (luokkaa millisekunteja.)

# treetxtshort
# treetxt
# euler

G10-15 (5 p.)

Steganografia: Tee funktio (ja tarvittavat apufunktiot) joilla saat salakirjoitettua merkkijonon Jypelin Image-kuvaan siten, että viesti koodataan kunkin värikomponentin (r, g, b, a) kahteen vähiten merkitsevään bittiin. Tee myös funktio jolla saat luettua viestin tällaisesta kuvasta.

Voit olettaa, että viesti tulee 8-bittisinä merkkeinä. Char-merkin 8 vähiten merkitsevää bittiä saat otettua sanomalla int lowerBits = myChar & 0xff; Tämä riittää ihan hyvin esim. englannin ja suomen kieleen. Toki erikoisemmat merkit jäävät tällä tavalla pois.

Pisteytys: Set Custom Points. 3 p. kun saat salakirjoitettua viestin kuvaan, 2 p. lisää kun saat luettua viestin kuvasta.

Esimerkki (avaa klikkaamalla)

Vinkkejä (avaa klikkaamalla)

# stegano

These are the current permissions for this document; please modify if needed. You can always modify these permissions from the manage page.