Arvutiteaduse instituut
  1. Kursused
  2. 2018/19 kevad
  3. MOOC Programmeerimise alused II (LTAT.TK.001)
EN
Logi sisse

MOOC Programmeerimise alused II 2018/19 kevad

  • Kursuse info
  • 1. Kahemõõtmeline järjend
  • 2. Kahekordne tsükkel
  • 3. Andmestruktuurid
  • 4. Viitamine ja muteerimine

4.1 Viitamine 4.2 Muteerimine 4.3 Järjendi muteerimine 4.4 Funktsioon ja muteerimine 4.5 Kordamine 4.6 Silmaring: Objekt-orienteeritud programmeerimine

  • 5. Testimine ja silumine. Rekursioon
  • 6. Rekursioon II
  • Korraldajad
IV OSA sisukord

4.5 KORDAMINE

Töövoost, mida ikka kasutame

Vaatleme nüüd kordavalt töövoogu, mis mõningate variatsioonidega võib ette tulla paljude ülesannete puhul.

Olgu algandmed teatud kujul failis. Näiteks on vaadeldavate objektide kohta andmed ridade kaupa esitatud. Ridadel on eraldajateks tühikud või mingid muud sümbolid, näiteks semikoolonid. Selleks et üldse andmetega toimetada, peab programm need sisse lugema. Sisselugemisel võib juba midagi nende andmetega ette võtta, näiteks kuidagi teisendada või mõned andmed üldse välja jätta.

Sisselugemisel peaks andmed paigutama sobivasse andmestruktuuri näiteks kahemõõtmelisse järjendisse või sõnastikku.

Nüüd saab selle struktuuri abil juba andmeid analüüsida. Vajadusel saab näiteks nende andmete põhjal ka mingi teise andmestuktuuri tekitada. Ja siis ka juba tollega midagi teha.

Lõpuks saab tulemused ekraanile väljastada või hoopis mingitesse failidesse kirjutada.

Püüame nüüd näite varal kõik need etapid läbi teha.

Olgu andmed mingile üritusele, näiteks Tartusse laulupeole tulijate kohta. Olgu igal real kirjas maakond, selle keskuse kaugus Tartust, mitu meest on tulemas ja mitu naist.

Tartumaa : 0 : 302 : 400
Hiiumaa : 293 : 24 : 44
Harjumaa : 186 : 350 : 300
Ida-Virumaa : 131 : 280 : 270 
Lääne-Virumaa : 123 : 200 : 160 
Raplamaa  : 149 : 56 : 46 
Põlvamaa : 49 : 87 : 65 
Viljandimaa : 78 : 170 : 170
Saaremaa : 322 : 154 : 128
Läänemaa : 238 : 105 : 102  
Jõgevamaa : 53 : 79 : 82
Võrumaa : 70 : 75 : 89 
Valgamaa : 90 : 65 : 76
Järvamaa : 103 : 124 : 120
Pärnumaa : 170 : 143 : 145

Küsime faili nime.

Failist sisselugemisel tahame andmed panna sõnastikku, kus võtmeks on maakonna nimi ja väärtuseks ennik, mis koosneb ülejäänud andmetest, mis maakonna kohta teada on. Seejuures paneme ennikusse kahekordse kauguse (Tartusse ja tagasi).

Teeme selleks funktsiooni, mis saab argumendiks failinime ja tagastab nõutud sõnastiku.

Arvutame, mitu kilomeetrit sõidavad kõik inimesed kokku.

Seejärel teeme selle sõnastiku põhjal kahemõõtmelise järjendi, mille ühes reas on meeste arvud ja teises reas naiste arvud. Selle järjendi põhjal arvutame, mitmes maakonnas on tulijate hulgas mehi rohkem, kui naisi.

Küsime faili nime, kuhu kirjutada.

def failist_sonastikku(failinimi):
    fail = open(failinimi)
    maakondade_sonastik = {}

    for rida in fail:
        #Teeme koolonite juurest katki
        jupid = rida.split(":")

        #Leiame väärtused järjendist
        maakond = jupid[0].strip()
        kaugus = int(jupid[1]) * 2 #edasi ja tagasi
        mehed = int(jupid[2])
        naised = int(jupid[3])

        #Moodustame sõnastiku
        ennik = (kaugus, mehed, naised)
        maakondade_sonastik[maakond] = ennik

    fail.close()

    return maakondade_sonastik

def sonastikust_kauguste_summa(maakondade_sonastik):
    summa = 0

    for maakond, vaartused in maakondade_sonastik.items():
        kaugus = vaartused[0]   
        mehi = vaartused[1]
        naisi = vaartused[2]

        summa += kaugus * mehi + kaugus * naisi

    return summa

def sonastikust_tulijate_jarjend(maakondade_sonastik):
    mehed = []
    naised = []

    for maakond, vaartused in maakondade_sonastik.items():
        mehed.append(vaartused[1])
        naised.append(vaartused[2])

    return [mehed, naised]

def mehi_rohkem_kui_naisi(maakondade_sonastik):
    tulijad = sonastikust_tulijate_jarjend(maakondade_sonastik)
    maakondade_arv_kus_mehi_rohkem = 0

    for i in range(len(tulijad[0])): #teame, et mõlemad järjendid on sama pikad
        mehi = tulijad[0][i]
        naisi = tulijad[1][i]
        if mehi > naisi:
            maakondade_arv_kus_mehi_rohkem += 1

    return  maakondade_arv_kus_mehi_rohkem 

maakondade_sonastik = failist_sonastikku("maakonnad.txt")
kauguste_summa = sonastikust_kauguste_summa(maakondade_sonastik)
print("Inimesed sõidavad kokku " + str(kauguste_summa) + " km.")
print("Leidub", mehi_rohkem_kui_naisi(maakondade_sonastik), "maakonda, kus mehi tuleb laulupeole rohkem kui naisi.")

Sama programm hoopis funktsiooniga

Konkreetset probleemi saab lahendada mitmel erineval moel. Nüüd vaatlemegi sellist tüüpi ülesannet, kus on programm antud ja on ka öeldud, mida see programm teeb. Antud on ka teine programm, mis peaks tegema sama, aga kasutab seejuures ühte funktsiooni, millest on aga teada vaid nimi. Ülesandeks ongi nüüd koostada nõutud funktsioon, et kaks programmi võrdväärselt töötaksid.

Proovime siin ühte sellis ülesannet lahendada.

Järgnev programmilõik leiab kahemõõtmelise järjendi korral, kui paljudes ridades on positiivseid elemente.

positiivsega_ridu = 0
for i in range(len(a)):
    leidub_positiivne = False
    for j in range(len(a[i])):
        if a[i][j] > 0:
            leidub_positiivne = True
            break
    if leidub_positiivne:
        positiivsega_ridu += 1
print(positiivsega_ridu)

Koostada funktsioon on_positiivseid, mille puhul alltoodud programmilõik töötaks ülaltooduga võrdväärselt.

positiivsega_ridu = 0
for i in range(len(a)):
    if on_positiivseid(a[i]):
        positiivsega_ridu += 1
print(positiivsega_ridu)

On selge, et selleks, et esimene programm üldse töötaks peab enne antud lõiku olema defineeritud kahemõõtmeline arvude järjend a.

Võiksime võtta testimiseks sellise järjendi, mille osades ridades on positiivseid elemente, aga osades mitte.

Ennekõike tuleb i põhjalikult selgeks saada, mis toimub esimeses programmis, siis on lootust teine programm samamoodi tööle saada. Paneme ka tähele, et mõlema programmi algus ja lõpp on täiesti samad.

Kui ridarealt läbi analüüsida, saame järgmised ideed.

positiivsega_ridu = 0

# Paneme tähele, et see suurus lõpuks väljastatakse

for i in range(len(a)):

# len(a) on 2d järjendi pikkus ehk ridade arv
# Seega välimine tsükkel võtab igal sammul uue reaindeksi 

    leidub_positiivne = False

# Igal välimise tsükli sammul saab leidub_positiivne väärtuseks False

    for j in range(len(a[i])):

# len(a[i]) on konkreetse rea elementide arv 
# Sisemine tsükkel vaatab konkreetse rea elemente järjest

        if a[i][j] > 0:
            leidub_positiivne = True
            break

# Kui vaadeldav element on positiivne, siis saab leidub_positiivne 
# väärtuseks True ja sisemisest tsüklist tullakse välja, sest ongi 
# positiivne leitud ja edasi pole vaja otsida

    if leidub_positiivne:
        positiivsega_ridu += 1

# Kui konkreetse reaga on klaar, siis otsustatakse, kas tuleb 
# suurendada loendajat

print(positiivsega_ridu)

#  Lõpuks loendaja väärtus väljastatakse. 

Kui vaatame nüüd teist programmi, siis näeme, et selle kontroll, kas konkreetses reas on positiivseid elemente, on usaldatud funktsioonile on_positiivseid.

positiivsega_ridu = 0
for i in range(len(a)):
    if on_positiivseid(a[i]):
        positiivsega_ridu += 1
print(positiivsega_ridu)

Mõtleme läbi, mis tüüpi on funktsiooni on_positiivseid argument ja mis tüüpi väärtus tuleb tagastada. Näeme, et funktsioonile antakse ette a[i], mis antud kontekstis on kahemõõtmelise järjendi rida ehk siis arvude järjend. Paneme tähele, et seda funktsiooni kasutatakse if-lause tingimusena. Seega peab tagastatav väärtus olema tõeväärtustüüpi - True või False.

True peaks tagastatama, kui selles reas on vähemalt üks positiivne element ja False vastasel juhul. Lahenduseks sobib näites selline variant.

def on_positiivseid(rida):
     for i in range(len(rida)):
         if rida[i] > 0:	
                return True
     return False

Palun katsetage ja veenduge selles ise.


IV OSA sisukord
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Tartu Ülikooli arvutiteaduse instituudi kursuste läbiviimist toetavad järgmised programmid:
euroopa sotsiaalfondi logo