Naloge

Vreme

Napišite funkcijo preberi_vrstice(ime_datoteke), ki prebere in vrne seznam vrstic v datoteki ime_datoteke.

Primer za datoteko podatki.txt:

>>> preberi_vrstice('podatki.txt')
['Ljubljana;oblačno;12.1', 'Maribor;sončno;9', 'Koper;sončno;14.7']

Rešitev

Z zanko for

def preberi_vrstice(ime_datoteke):
    f = open(ime_datoteke, "r", encoding="utf-8")
    lines = []
    for line in f:
        lines.append(line.strip())
    f.close()
    return lines

ali z metodama read in splitlines

def preberi_vrstice(ime_datoteke):
    return open(ime_datoteke, "r", encoding="utf-8").read().splitlines()    

Napiši funkcijo preberi_csv(ime_datoteke), ki odpre in prebere datoteko ime_datoteke, ki v vsaki vrstici vsebuje s podpičji ločene vremenske podatke (kraj, vreme in temperaturo), ter jih vrne kot seznam terk.

>>> podatki = preberi_csv('podatki.txt')
>>> podatki
[('Ljubljana', 'oblačno', 12.1), ('Maribor', 'sončno', 9.0), ('Koper', 'sončno', 14.7)]

Rešitev

def preberi_csv(fname):
    sez = []
    for vrstica in preberi_vrstice(fname):
        kraj, vreme, temp = vrstica.split(';')
        sez.append((kraj, vreme, float(temp)))
    return sez

Napiši funkcijo oblikuj(podatki), ki sprejme seznam terk podatki z vremenskimi podatki in vrne seznam nizov, ki so oblikovani, kot je prikazano spodaj:

>>> oblikuj(podatki)
['Kraj: Ljubljana, Vreme: oblačno, Temperatura: 12.1°C', 
 'Kraj: Maribor, Vreme: sončno, Temperatura: 9.0°C',
 'Kraj: Koper, Vreme: sončno, Temperatura: 14.7°C']

Rešitev

def oblikuj(podatki):
    sez = []
    for kraj, vreme, temp in podatki:
        sez.append(f'Kraj: {kraj}, Vreme: {vreme}, Temperatura: {temp}°C')
    return sez

Izpis iz prejšnje naloge se nam ni najbolj posrečil, zato se odločimo, da bomo podatke zapisali v tabeli. V ta namen napiši funkcijo oblikuj_tabelo(podatki), ki vrne seznam nizov, ki so oblikovani na prikazan način.

>>> oblikuj_tabelo(podatki)
['Kraj            Vreme           Temperatura (°C)',
 '------------------------------------------------',
 'Ljubljana       oblačno                     12.1',
 'Maribor         sončno                       9.0',
 'Koper           sončno                      14.7']

Rešitev

def oblikuj_tabelo(podatki):
    sez = ['Kraj            Vreme           Temperatura (°C)',
           '------------------------------------------------']
    for kraj, vreme, temp in podatki:
        sez.append(f'{kraj:16}{vreme:16}{temp:16}')
    return sez

Napiši funkcijo oblikuj_tabelo_f(podatki) tako, da se bo temperatura izpisala v Fahrenheitovi lestvici. Rezultat zaokroži na eno decimalno mesto.

>>> oblikuj_tabelo_f(podatki)
['Kraj            Vreme           Temperatura (°F)',
 '------------------------------------------------',
 'Ljubljana       oblačno                     53.8',
 'Maribor         sončno                      48.2',
 'Koper           sončno                      58.5']

Rešitev

def oblikuj_tabelo_f(podatki):
    sez = ['Kraj            Vreme           Temperatura (°F)',
           '------------------------------------------------']
    for kraj, vreme, temp in podatki:
        temp_f = temp * 9 / 5 + 32
        sez.append(f'{kraj:16}{vreme:16}{temp_f:16.1f}')
    return sez

Izpis bi lahko bil še preglednejši, če bi tabelo oblikovali, kot je prikazano spodaj (dokumentacija). V ta namen napiši funkcijo oblikuj_pike(podatki).

>>> oblikuj_pike(podatki)
['Kraj            Vreme           Temperatura (°F)',
 '------------------------------------------------',
 'Ljubljana.......oblačno.....................53.8',
 'Maribor.........sončno......................48.2',
 'Koper...........sončno......................58.5']

Rešitev

def oblikuj_pike(podatki):
    sez = ['Kraj            Vreme           Temperatura (°F)',
           '------------------------------------------------']
    for kraj, vreme, temp in podatki:
        temp_f = temp * 9 / 5 + 32
        sez.append(f'{kraj:.<16}{vreme:.<16}{temp_f:.>16.1f}')
    return sez

V zadnjem stolpcu izpiši temperaturo v Fahrenheitih in Celzijah s funkcijo oblikuj_fc(podatki)

>>> oblikuj_fc(podatki)
['Kraj            Vreme        Temperatura °F (°C)',
 '------------------------------------------------',
 'Ljubljana.......oblačno..............53.8 (12.1)',
 'Maribor.........sončno................48.2 (9.0)',
 'Koper...........sončno...............58.5 (14.7)']

Rešitev

def oblikuj_fc(podatki):
    sez = ['Kraj            Vreme        Temperatura °F (°C)',
           '------------------------------------------------']
    for kraj, vreme, temp in podatki:
        temp_f = temp * 9 / 5 + 32
        temp_fc = f'{temp_f:.1f} ({temp:.1f})'
        sez.append(f'{kraj:.<16}{vreme:.<16}{temp_fc:.>16}')
    return sez

Napiši funkcijo shrani(vrstice, ime_datoteke), ki seznam nizov vrstice shrani vsakega v svojo vrstico v datoteko ime_datoteke.

>>> shrani(['prva vrstica', 'druga vrstica', 'tretja vrstica'], 'datoteka.txt')

Rešitev

def shrani(vrstice, ime_datoteke):
    f = open(ime_datoteke, "w")
    for vrstica in vrstice:
        f.write(vrstica + '\n')
    f.close()

Najdaljše besede

Napiši funkcijo najdaljse_besede(s), ki v nizu s poišče vse najdaljše besede in jih vrne, ločene z vejico.

>>> najdaljse_besede('ob znaku bo ura deset in pet minut')
'znaku, deset, minut'

Rešitev

def najdaljse_besede(s):
    xs = s.split()

    # Poišči dolžino najdaljše besede
    naj = 0
    for word in xs:
        if len(word) > naj:
            naj = len(word)

    # Poišči besede dolžine `naj`
    ys = []
    for word in xs:
        if len(word) == naj:
            ys.append(word)

    return ', '.join(ys)

.py

Izpišite vse datoteke v trenutnem direktoriju, ki imajo končnico .py.

Če se vam naloga zdi prelahka, poskusite napisati program, ki izpiše vse datoteke s končnico .py v trenutnem direktoriju in vseh poddirektorijih trenutnega direktorija. Torej, če se nahajate v direktoriju /home/glenda, mora vaš program najti tako datoteko /home/glenda/p9.py, kot tudi datoteko /home/glenda/plan9/from/outer/space.py.

Rešitev

import os

for f in os.listdir():
    if os.path.splitext(f)[1] == '.py':
        print(f)

Poglejmo si iterativno rešitev težje naloge. Iterativna rešitev nam je všeč, ker uporablja samo konstrukte, ki jih že poznamo:

ds = ['.']
while ds:
    d = ds.pop()
    for f in os.listdir(d):
        f = os.path.join(d, f)
        if os.path.isdir(f):
            ds.append(f)
        elif os.path.splitext(f)[1] == '.py':
            print(f)

Težjo nalogo lahko rešimo tudi z uporabo rekurzije.

def list(path):
    for f in os.listdir(path):
        f = os.path.join(path, f)
        if os.path.isdir(f):
            list(f)
        elif os.path.splitext(f)[1] == '.py':
            print(f)
list('.')

Ali pa uporabimo funkcijo os.walk.

for dirpath, dirnames, filenames in os.walk('.'):
    for filename in filenames:
        if os.path.splitext(filename)[1] == '.py':
            print(os.path.join(dirpath, filename))

ID3v1

Napiši funkcijo, ki v podanem direktoriju prebere vse datoteke s končnico .mp3 in sestavi prikazan izpis:

 Title: Nocoj
Artist: Slon in Sadez
 Album: Sponsorska plata - NeCenzurira
  Year: 2010
  File: 10 Slon in Sadez - Nocoj.mp3

 Title: Opozorilo
Artist: Slon in Sadez
 Album: Sponsorska plata - NeCenzurira
  Year: 2010
  File: 17 Slon in Sadez - Opozorilo.mp3

Podatke o pesmi ne smeš prebrati iz imena datoteke ampak iz njene vsebine. To storiš tako, da prebereš zadnjih 128 znakov datoteke. Če prvi trije znaki tega niza niso enaki "TAG" potem datoteka podatkov o izvajalcih ne vsebuje in jo je treba preskočiti. Sicer se v naslednjih 30 znakih nahaja naslov pesmi, v naslednjih 30 ime izvajalca, v naslednjih 30 ime albuma in naslednjih 4 leto izdaje. Če je naslov pesmi, ime izvajalca ali albuma krajše od 30 znakov, je na koncu niza dodano ustrezno število znakov "\x00", ki jih boš moral odstraniti.

Za testiranje lahko uporabiš izbrani pesmi Slona in Sadeža iz prosto dostopne Sponzorske plate.

Rešitev

import os

def id3v1(dir):
    os.chdir(dir)
    for fn in os.listdir(): 
        if os.path.splitext(fn)[1] == '.mp3':
            b = open(fn, 'rb').read()[-128:]
            if b[:3] != b'TAG': continue
            b = b[3:]
            for key, size in [('Title', 30), ('Artist', 30), ('Album', 30), ('Year', 4)]:
                print('{:>6}: {}'.format(key, b[:size].strip(b'x00').decode('ascii')))
                b = b[size:]
            print('  File:', fn)
            print()

id3v1('sponzorska_plata')

Plagiator

Razpakirajte direktorij z desetimi datotekami in poiščite plagiatorja! Napišite program, ki ugotovi v katerih dveh datotekah se ponovi vsaj 1000 znakov.

Rešitev Odgovor je 3.txt in 8.txt.

Počasnejša rešitev (čas izvajanja: 200 s)

datoteke = [open('datoteke/{}.txt'.format(i)).read() for i in range(10)]
for i in range(10):
    for j in range(i):
        for k in range(0, len(datoteke[i]) - 1000):
            if datoteke[i][k:k + 1000] in datoteke[j]:
                print(i, j)

Hitrejša rešitev (čas izvajanja: < 1 s) Ta rešitev ni več povsem pravilna, saj se lahko zgodi, da vrne tudi imena datotek v katerih se ponovi 500 znakov, nikoli pa ne spregleda datotek v katerih se ponovi vsaj 1000 znakov.

datoteke = [open('datoteke/{}.txt'.format(i)).read() for i in range(10)]
for i in range(10):
    for j in range(i):
        for k in range(0, len(datoteke[i]) - 500, 500):
            if datoteke[i][k:k + 500] in datoteke[j]:
                print(i, j)

Last modified: Friday, 11 December 2020, 12:49 PM