(toiminnot)

hwechtla-tl: Ohjelmoinnin perusteet -kurssi

Kierre.png

Mikä on WikiWiki?
nettipäiväkirja
koko wiki (etsi)
viime muutokset


Tämän kurssin tämänhetkinen virallinen sivu on http://www.ling.helsinki.fi/kit/2008s/clt230/

tehtävien palauttamisesta

Tehtävät jakaantuvat toiminta- ja kysymysosioihin. Tehtävä on "tehty", kun olet lähettänyt sähköpostilla kurssiassarille toiminnan (kopioi kirjoittamasi asiat ja niiden tulokset sähköpostiin) sekä vastaukset kysymyksiin. Tehtävästä saa täydet pisteet, jos vastaus on oikein, ja puolet pisteistä, jos sitä on selvästi yritetty.

Tehtäväpalautuksen deadline on aina kaksi viikkoa sen luentokerran jälkeen, johon tehtävät liittyvät.

materiaali

Muita hyviä (?) Python-aiheisia ohjelmoinnin peruskurssimateriaaleja:

1. viikko

Aiheet: ohjelma, ohjelmointikieli, ohjelmointikielen toteutus, primitiivi, IDLE, ohjelmointikielen ilmausten modaliteetit (määritelmä / käsky / kysymys), syöte, tuloste, ohjelma(koodi)n suhde käynnissä olevaan ohjelmaan (suorittaminen eli ajaminen). Pythonista: aritmetiikka, print, def (alustavasti).

Tehtävät:

1) Toiminta: Käynnistä IDLEn keskustelutila ja sano IDLElle jotain satunnaista, joka ei ole Python-kielinen ilmaus. Varmista, että IDLE vastaa sanomaasi asiaan jonkinlaisella virheilmoituksella. Kysymykset: a. Yritä arvata, mitä saamasi virheilmoitus tarkoittaa. b. Arvioi, kuinka suuri osuus kaikista mahdollisista merkkijonoista on virheettömiä Python-kielen ilmauksia. c. Pitäisikö Python-kielen olla sallivampi tai vähemmän salliva, toisin sanoen pitäisikö suuremman / pienemmän osan kaikista ilmauksista olla (jotain tarkoittavia) Python-kielen ilmauksia? Miksi?

2) Toiminta: Määritä IDLEssä ohjelma, joka ottaa syötteekseen lämpötilan Celsius-asteina ja palauttaa saman lämpötilan Fahrenheit-asteina. Muunnoskaavan saa wikipediasta (http://fi.wikipedia.org/wiki/Fahrenheit-asteikko). Kokeile ohjelmaa ainakin kolmella eri syötteellä. Vihje: voit käyttää seuraavaa runkoa ohjelman määrittelyssä:

def celsiuksesta_fahrenheitiksi(celsius): return ... celsius ...
Korvaa ellipsikset ("...") jollain kunnollisella.

2. viikko (torstai)

Aiheet: muuttuja, funktio / aliohjelma, kompositio, ohjelmatiedosto. Pythonista: merkkijonojen käsittelyä, vertailut, sijoituslause, help(), dir().

Tehtävät:

1) Toiminta: Määritä ohjelma pitkako_merkkijono(merkkijono), joka kertoo, onko merkkijono pitkä (olkoot tässä tapauksessa pitkiä kaikki merkkijonot, joissa on yli kymmenen merkkiä). Kokeile ohjelmaa ainakin kolmella eri syötteellä. Vihje: tämän voi siis tehdä laskemalla ensin merkkijonon pituuden len-funktiolla ja sitten katsomalla, onko tulos suurempi kuin kymmenen.

2) Toiminta: a. Määritä ohjelma hypotenuusan_pituus(kateetti1, kateetti2), joka kertoo suorakulmaisen kolmion hypotenuusan pituuden, kun kateettien pituudet ovat kateetti1 ja kateetti2. Kaavan saat wikipediasta (http://fi.wikipedia.org/wiki/Pythagoraan_lause), jossa hypotenuusan pituutta kutsutaan selkeästi nimellä c (etsi siis sivulta kohta, jossa sanotaan "c = ..."). Neliöjuuren saat Python-kielessä funktiokutsulla pow(luku, 0.5): esimerkiksi pow(9, 0.5) on 3. b. Määritä ohjelma sq(luku), joka kertoo luvun neliön (sen saa kertomalla luvun itsellään). Määrittele hypotenuusan_pituus(kateetti1, kateetti2) uudestaan käyttäen sq(luku)-aliohjelmaa. Kokeile ohjelmia ainakin kolmella eri syötteellä. Kysymys: kumpi määritelmä on mielestäsi kauniimpi ja miksi?

Muuten. hypotenuusan_pituus ei todellakaan ole kieliteknologille hyödytön ohjelma. Kerron tunnilla tarkemmin, miksi.

2. viikko (perjantai)

Aiheet: ehtolause, merkkijono, syntaksi, palvelu, operaattori. Pythonista: if, :, operaattorit, kutsurakenne.

Tehtävät:

1) Toiminta: a. Tee ohjelma heikko_aste(sana), joka palauttaa suomen kielen sanalle (joka on perusmuodossa) sen heikon asteen. (Ohjelman ei tietenkään tarvitse olla täydellinen; hyvä, jos se toimii yli 70%:lle sanoista.) Heikon asteen muodostamisohjeita saat wikipediasta (http://en.wikipedia.org/wiki/Consonant_gradation#Finnish tai http://fi.wikipedia.org/wiki/Astevaihtelu). Vihje: käytä vaikkapa tällaista runkoa:

def heikko_aste(sana):
  if sana.endswith(...): return sana[...:...] + "..."
  else:
    if sana.endswith(...): return sana[...:...] + "..."
    else:
      ...
      else: return sana
Korvaa ellipsikset jollain sisällökkäällä. b. Tee ohjelma genetiivi(sana), joka muodostaa sanan genetiivin liimaamalla sen heikkoon asteeseen n-kirjaimen perään. c. Kokeile ohjelmaa ainakin kolmella eri syötteellä. Kysymys: Oletetaan, että genetiivi-ohjelma olisikin kirjoitettu ilman heikko_aste-apuohjelmaa. Kumpi on siistimpi tapa ja miksi?

3. viikko (torstai)

Aiheet: tyyppi, lista, kokoelma. Pythonista: listaliteraalit, in, type(), sum(), len(), min(), max(), string.join, string.split.

Tehtävät:

1) Toiminta: Tee ohjelma virkkeet_sakeiksi(teksti), joka ottaa syötteeksi merkkijonon ja muuttaa siitä virke-erottimet (piste ja välilyönti eli ". ") säe-erottimiksi (väli, kauttaviiva ja rivinvaihto eli " /\n"). Esimerkiksi syötteellä "Tahdon maailman parantaa. Sitten kuljen verantaa. Katson kaukaista rantaa." tulos on: "Tahdon maailman parantaa /\nSitten kuljen verantaa /\nKatson kaukaista rantaa." (\n on Pythonin merkintä merkkijonon sisäiselle rivinvaihdolle; se näkyy oikeana rivinvaihtona, jos merkkijonon esim. tulostaa print-komennolla.) Kokeile ohjelmaa vähintään kolmella eri syötteellä. Vihje: pätki syöte ensin .split-palvelulla ja sitten yhdistä se .join-palvelulla.

2) Toiminta: Tee ohjelma sisaltaako_rivin(teksti, rivi), joka ottaa syötteeksi tekstiä ja rivin ja palauttaa, onko annettu rivi yhtenä rivinä tekstin seassa. Kokeile ohjelmaa vähintään kolmella eri syötteellä. Vihje: pätki teksti rivinvaihtojen ("\n") kohdalta ja katso in-operaattorilla, onko etsitty rivi tuloksena olevassa rivien listassa.

3. viikko (perjantai)

Aiheet: ohjelmakirjastot, funktioiden sisäiset muuttujat, suorittaminen eli ajaminen. Pythonista: elif, and, or, not, import.

Tehtävät:

1) Toiminta: a. Tee tähän mennessä kirjoittamistasi ohjelmista kaksi moduulia: toisessa (jonka nimi voi olla esim. laskenta.py) ovat kaikki numeroiden käsittelyyn liittyvät ohjelmat, toisessa (jonka nimi voi olla esim. teksti.py) ovat kaikki merkkijonojen ja tekstiaineiston käsittelyyn liittyvät ohjelmat. Moduuleissa pitää siis olla vähintään edellisten tehtävien ohjelmat (celsiuksesta_fahrenheitiksi, pitkako_merkkijono, hypotenuusan_pituus, heikko_aste, genetiivi, virkkeet_sakeiksi, sisaltaako_rivin) sekä mahdollisesti muita, tunnilla tai omatoimisesti huvin vuoksi tehtyjä määrittelyjä. b. Tuo kyseiset moduulit importilla IDLEen ja tarkasta niiden tarjoamat palvelut dir()-funktiolla. c. Kokeile ainakin kolmea ohjelmaa jollain syötteellä.

4. viikko (torstai)

Varoitus: tämän tunnin aihe on useille vaikea!

Aiheet: listojen läpikäynti, listakeräelmä, toistorakenne, aggregaatti. Pythonista: listakeräelmät, file(), file.readlines().

Tehtävät:

1) Toiminta: a) Kirjoita ohjelmat sq(x) eli neliöönkorotus, sqrt(x) eli neliöjuuri ja keskiarvo(x) tai ota ne aiempien luentojen muistiinpanoista / ohjelmista. b) Määritä ohjelma otoskeskihajonta(aineisto), joka laskee halutun aineiston (joka on lista lukuja) otoskeskihajonnan. Kaavan saat wikipediasta (http://fi.wikipedia.org/wiki/Hajontaluku kohta "keskihajonnan harhaton estimaatti") tai jos et tajua sitä, katso yo. sivulta linkattu artikkeli (http://www.techbookreport.com/tutorials/stddev-30-secs.html). c. Testaa ohjelma ainakin kolmella eri syötteellä. Vihje: käytä seuraavaa runkoa:

def otoskeskihajonta(aineisto):
    ka = keskiarvo(aineisto)
    erojen_neliot = [... for luku in aineisto]
    varianssi = ... / float(len(aineisto) - 1)
    return ... varianssi ...
Korjaa ellipsikset (...) jollain syntaktisesti korrektilla. (Poliittisesti korrektilla?)

2) Toiminta: a. tee ohjelma ilmauksen_genetiivi(ilmaus), joka muuntaa ilmauksen jokaisen sanan genetiiviin aiemmin määritellyllä genetiivi-ohjelmalla. Vihje: hajota ilmaus sanoiksi, kerää näiden sanojen genetiivit listakeräelmällä, ja yhdistä tuloslista takaisin ilmaukseksi. b. testaa a-kohdan ohjelma jollain suurehkolla suomenkielisellä tiedostolla. Vihje: tiedoston sisällön saa ilmauksella

open("tiedoston_nimi").read()

3) Toiminta: a. Määritä ohjelma sama_sana_paitsi(sana, kielletty, korvike), joka palauttaa sana:n paitsi jos sana on kielletty, jolloin ohjelma palauttaa korvikkeen. Tarkoitus on käyttää tätä ohjelmaa sensurointiin: kielletty on "sensuroitava sana", joka pitää korvata jollain poliittisesti korrektilla; kaikki muut sanat saa palauttaa sellaisinaan. b. Määritä ohjelma siivoa_salaisuudet(sanalista, salaisuus, korvike), joka palauttaa sanalistan muuten samanlaisena paitsi että salaisuus-muuttujassa syötteeksi annetut sanat korvataan korvike-muuttujan korvikkeilla. c. Määritä ohjelma sensuroi(teksti, kielletty_sana), joka korvaa tekstistä kaikki kielletyt sanat merkkijonolla "****". d. Kokeile sensuroida jostain sopivasta koetiedostosta esim. sana "the", "fuck" tai "fnord". (Lisätietoa: http://en.wikipedia.org/wiki/Fnord) Vihjeet: a tehdään if-rakenteella. b tehdään a-kohdan ohjelmalla ja listakeräelmällä. c tehdään hajottamalla teksti sanoiksi, b-kohdan ohjelmalla ja yhdistämällä tulos takaisin tekstiksi.

4. viikko (perjantai)

Aiheet: listoista valikointi. Pythonista: listakeräelmien if-alilause.

5. viikko

Aiheet: useamman syöteaineiston käsitteleminen listakeräelmillä. Pythonista: listakeräelmien sisäkkäiset for-alilauseet.

Tehtävät:

1) Toiminta: a. Määritä ohjelma osumat(aineisto, merkkijono), joka palauttaa listan niistä aineiston sanoista, joista löytyy annettu merkkijono. Aineisto on siis lista merkkijonoja. Esimerkiksi osumat(['yksi', 'kaksi', 'kolme'], 'ks') palauttaa ['yksi', 'kaksi']. b. Testaa ohjelmaa jonkin tiedoston sanoilla. Ne saa ilmauksella:

open("tiedoston_nimi").read().split()
Vihje: käytä listakeräelmää, jossa on ehto sille, mitkä aineiston osat keräillään. Merkkijonon sisältymistä toiseen voi testata in-operaattorilla.

2) Toiminta: a. Määritä ohjelma portmanteaut(aineisto, n), joka palauttaa sanat, jotka saa aineistosta siten, että yhdistää kaksi aineiston sanaa siten, että toisen sanan n viimeistä kirjainta on samat kuin toisen sanan n ensimmäistä kirjainta. Esimerkiksi sanoista "pikku" ja "ikkuna" tulee "pikkuna" n:n arvolla 4 ja niinpä portmanteaut(["tuttu", "katu", "poika"], 2) palauttaa listan ["tuttuttu", "katuttu", "poikatu"]. (Oikea portmanteau-sanojen määritelmä on paljon laajempi, katso http://en.wikipedia.org/wiki/Portmanteau) b. Testaa ohjelma ainakin kolmella syötteellä. c. Mitä tapahtuu, jos n=0, ja miksi? Vihje: käytä seuraavaa runkoa:

def portmanteaut(aineisto, n):
  return [... for sana1 in aineisto for sana2 in aineisto if ...]
Korvaa ellipsikset (...) jollain järkevällä.

6. viikko

Aiheet: säännölliset lausekkeet ja niiden käyttö. Pythonista: re-moduuli, re.search(), re.findall(), re.split(), re.sub(), match.group()

Tehtävät:

1) Toiminta: a. Määritä ohjelma tavut(sana), joka palauttaa listan sanan tavuista. Tarkkuuden ei tietenkään tarvitse olla 100%: riittää, että se toimii suurimmalle osalle suomen sanoista. b. Testaa ohjelma ainakin kolmella eri syötteellä. Vihje: käytä re.findall()ia ja jotain seuraavanlaista säännöllistä lauseketta:

[klptns...]*([aeiouyäö]|[aeiouyäö]i|...)[klptns...]*(?![aeiouyäö])
Ensimmäinen osa siis täsmää mahdolliseen konsonanttiyhdelmään, toinen osa vokaaleista koostuvaan ytimeen, kolmas osa mahdolliseen konsonanttiyhdelmään ja neljäs osa varmistaa, että heti seuraava merkki ei ole vokaali. Lisää tietoa suomen kielen diftongeista on wikipediassa (http://fi.wikipedia.org/wiki/Vokaali#Monoftongit.2C_diftongit_ja_triftongit)

2) Toiminta: a. Määritä ohjelma rimmaako(sana1, sana2), joka kertoo, onko sana1:n ja sana2:n kaksi viimeistä tavua samat. b. Määritä ohjelma riimiparit(aineisto), joka etsii aineistosta kaikki sanaparit, jotka rimmaavat mutta eivät ole sama sana. c. Testaa ohjelma jollain suomenkielisellä aineistolla. Vihje: a-kohta tehdään tavut-ohjelman avulla, b-kohtaa varten runko on tämä:

def riimiparit(aineisto):
    return [[sana1, sana2] for sana1 in aineisto
                           for sana2 in aineisto
                           if ...]
c-kohdassa käytä tunnilla (tai omin päin) määriteltyä sanat()-ohjelmaa.

7. viikko

Aiheet: sivuvaikutukset, imperatiiviset toistorakenteet. Pythonista: raw_input(), f.write(), f.close(), for-lause, while-lause, muuttujasijoitus, listasijoitus

Tehtävät:

1) a. Tee ohjelma input_lines(), joka lukee käyttäjältä tekstirivejä ja palauttaa ne listana, kun käyttäjä syöttää tyhjän rivin. b. Luettele, mitä kaikkia sivuvaikutuksellisia rakenteita käytät ohjelmassasi. c. Testaa ohjelma ainakin kolmella syötteellä.

Vihje: käytä seuraavaa runkoa:

def input_lines():
    syote = ...
    tulos = ...
    while ...:
        syote = raw_input()
        tulos.append(...)
    return tulos

2) Tee ohjelma koyhan_henkilon_selain(), joka lukee käyttäjältä www-sivujen osoitteita ja näyttää jokaiselle osoitteelle kyseisen www-sivun sisällön. Tätä toistetaan ikuisesti (ja sehän on pitkä aika). www-sivuihin saa jonkinlaisen kosketuspinnan urllib-moduulilla, jonka palvelu urllib.urlopen(osoite) palauttaa www-sivun tiedostona. urllib.urlopen(osoite) ja open(tiedosto) tekevät siis samaa, paitsi että ensinmainitulle annetaan syötteeksi www-osoite (esim. "http://www.ling.helsinki.fi/"), jälkemmäiselle tiedoston nimi. Tiedoston sisällön, kuten ennenkin, saa .read()-palvelulla.

8. viikko

Aiheet: kahden aineiston rinnakkainen läpikäynti, aineiston peräkkäisten elementtiparien läpikäynti. Pythonista: zip(), destrukturointi sijoituksessa, range().

Tehtävät:

1) Kirjoita ohjelma sisaltaako_tavuduplikaation(sana), joka kertoo (palauttaa), onko tavussa peräkkäin kaksi samaa tavua. Esimerkiksi sana "kontata" sisältää tavuduplikaation, koska siinä tavu "ta" esiintyy kaksi kertaa peräkkäin. Samoin "hihhih". Sana "aivina" ei sen sijaan sisällä tavuduplikaatiota. Testaa ohjelma ainakin kolmella eri syötteellä.

Vihje: käytä seuraavaa runkoa:

def sisaltaako_tavuduplikaation(sana):
    tavulista = tavut(sana)
    return ... [tavu == seuraava_tavu for tavu, seuraava_tavu in zip(...)]

2) Kirjoita ohjelma sotke_sanajarjestys(lause), joka palauttaa lauseen siten, että jokainen parillinen sana (ensimmäinen sana tulkitaan parilliseksi) on vaihdettu seuraavan parittoman sanan kanssa. Esimerkiksi sotke_sanajarjestys("hei poika hoi, miksei soittosi jo soi") palauttaa "poika hei miksei hoi, jo soittosi soi". Testaa ohjelma ainakin kolmella eri syötteellä.

Vihje: tähän on varsin monta tapaa. Listan joka toisen sanan saa sanomalla lista[::2] ja loput sanat (siis ne väliin jääneet) sanomalla lista[1::2]. Toisaalta listan indeksit saa sanomalla range(len(lista)) ja indeksin parittomuuden voi testata sanomalla (indeksi % 2).

Hajota lause sanoiksi, uudelleenjärjestele se listakeräelmällä ja yhdistä takaisin merkkijonoksi. Parillisen sanamäärän ja parittoman sanamäärän tapaus kannattaa ehkä käsitellä erikseen.

Täällä on myös ohjelmointikurssin 8. viikon tehtävien esimerkkivastauksia.

9. viikko

Aiheet: rekursio, jäsennyspuut, puiden esittäminen Pythonissa.

Tehtävät:

Näissä tehtävissä voi käyttää syöteaineistona seuraavaa jäsennyspuuta:

esim = ["S", ["N", "porvari"],
             ["VP", ["V", "nukkuu"],
                    ["ADV", "huonosti"]]]

1) Kirjoita ohjelma korvaa_alipuu(puu, alipuu, korvaaja), joka palauttaa puun siten, että siitä on korvattu syötteenä annetun kanssa samanlaiset alipuut korvaajalla. Esimerkiksi korvaa_alipuu(esim, ["V", "nukkuu"], ["VP", ["V", "nukkui"], ["ADV", "aikoinaan"]]) tuottaa seuraavan puun:

["S", ["N", "porvari"],
      ["VP", ["VP", ["V", "nukkui"],
                    ["ADV", "aikoinaan"]],
             ["ADV", "huonosti"]]]

Testaa ohjelma ainakin kolmella syötteellä.

Vihje: idis on, että on kolme tapausta: joko puu itse kokonaisuudessaan on korvattava alipuu, jolloin palautetaan korvaaja; tai puu on jokin yhden sanan puu, josta korvattavia alipuita ei voi löytyä; tai sitten puu koostuu kahdesta alipuusta, joista korvataan haluttu alipuu ja tulokset yhdistetään takaisin (muuten aiemman kaltaiseksi) puuksi. Seuraavaa runkoa voipi käyttää.

def korvaa_alipuu(puu, alipuu, korvaaja):
    if puu == alipuu: return ...
    tyyppi = puu[0]
    if tyyppi in [...]: return puu
    if tyyppi in [...]:
        return ... korvaa_alipuu(puu[1], alipuu, korvaaja) ... korvaa_alipuu(puu[2], alipuu, korvaaja) ...

Tässä on näin paljon vihjeitä, koska ennakoin ihmisillä vaikeuksia tämän tehtävän tekemisessä. Muistakaa myös, että assarien tukitunti on olemassa!

2) Kirjoita ohjelma tasmaako_puu(puu, malli), joka kertoo, vastaako puu mallia. Malli on myös puu, paitsi että se saa sisältää alipuita, joiden tyyppi on "?". Täsmättävässä puussa saa tällaisen alipuun paikalla olla mikä puu vain (kyseessä on siis eräänlainen "jokerialipuu").

Esimerkiksi tasmaako_puu(esim, ["S", ["N", "porvari"], ["?"]]) = True (jolloin mallin "?"-tyyppinen alipuu vastaa koko "VP"-alipuuta) ja toisaalta tasmaako_puu(esim, ["S", ["?"], ["V", "nukkuu"]]) = False (koska mallin "V"-tyyppinen alipuu ei vastaa "VP"-alipuuta). Jos mallissa ei käytetä jokerialipuita, ainoa puuta vastaava malli on puu itse: esimerkiksi tasmaako_puu(esim, esim) = True.

Testaa ohjelma ainakin kolmella syötteellä.

Vihje: käytä seuraavaa runkoa:

def tasmaako_puu(puu, malli):
    tyyppi = malli[0]
    if tyyppi == "?": return ...
    if tyyppi in [...]: return puu == malli   # malli ei sisällä alipuita
    if tyyppi in [...]:
        return tyyppi == puu[0] and tasmaako_puu(...) and tasmaako_puu(...)

10. viikko

Aiheet: rekursio, listojen hajottaminen osiin, merkkijonojen hajottaminen.

Tehtävä:

Tutki seuraavaa määrittelyä:

def outo(ls):
    if len(ls) <= 1: return ls
    return [ls[1], ls[0]] + outo(ls[2:])
Mitä se tekee ja miksi?


kategoria: ohjelmointi


Pikalinkit:


kommentoi (viimeksi muutettu 11.06.2012 14:41)