Rješenja nekih zadataka, koje ste rješavali u C-u, pomoću pythona =================================================================== Ideja je u pythonu riješiti zadatke koje ste već rješavali u C-u i time produbiti znanje pythona. Zadaća 1 (:func:`map`, :keyword:`lambda`, :func:`math.sin`, :obj:`sum`, `[ ... for ... in ...] `_, `( ... for ... in ...) `_ ) --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- .. _z1z3b: Zadatak 3b ^^^^^^^^^^^^^^^^^ .. literalinclude:: z1z3b_2.py :language: python Pokrenemo program i unesemo npr. ``10``, rezultat je: .. literalinclude:: z1z3b_2.py.filtered :language: text U interaktivnom modu možemo pratiti izvršavanje: .. literalinclude:: z1z3b.py.filtered :language: pycon .. attention:: Za razliku od samostalnog programa gdje smo svaki međurezultat koristili samo jednom u interaktivnom primjeru smo npr. ``L`` iz 4. retka koristili jednom u 5. a drugi put u 6. retku. To je važno uočiti jer u slučaju da nam neka lista treba samo jednom možemo koristiti tzv. iteratore koji **ne zauzimaju toliko memorije** koliko liste i računaju se tek kad zatreba. Mana iteratora je da ih se može koristiti samo jednom. Također treba uočiti da je rezultat od :func:`map` iterator, kao i rezultat od ``( ... for ... in ...)``. Naprotiv, rezultat od ``[ ... for ... in ...]`` je lista. Više o generatorima u odjeljku :ref:`gen`. Kako iteratore možemo upotrijebiti samo jednom, u drugom primjeru smo morali koristiti ``list()`` i pretvoriti iteratore u liste da bismo ih mogli koristiti više puta. Zadaća 2 (:meth:`str.join`, ``*args``) ----------------------------------------------------------------------------------------------------------------------------------------------- Zadatak 1b ^^^^^^^^^^^^^^^^^ Rješenje 1 """""""""""""""" .. literalinclude:: z2z1b_1.py :language: python Rješenje 2 """""""""""""""" Moguće je koristiti direktan upis stringa u ``stdout`` pomoću ``sys.stdout.write``. .. literalinclude:: z2z1b_2.py :language: python Rješenje 3 """""""""""""""" Za rješavanje ovog zadatka može poslužiti funkcija :meth:`str.join`. .. literalinclude:: join01.py :language: python .. literalinclude:: join01.py.filtered :language: text Počnemo tako da generiramo tablicu množenja kao dvodimenzionalnu listu ``L2``. .. literalinclude:: z2z1b_4.py :language: python .. literalinclude:: z2z1b_4.py.filtered :language: text Zatim povežemo unutarnju listu znakom ``"|"``, a vanjsku listu znakom za novi red ``"\n"``. .. literalinclude:: z2z1b_3.py :language: python .. _z2z1br4: Rješenje 4 """""""""""""""" .. literalinclude:: z2z1c_2.py :language: python .. literalinclude:: z2z1c_2.py.filtered :language: text Vidimo da ako je ``L=[1,2,3]`` tada je ``print(L)`` isto što i ``print([1,2,3])`` (ispis liste), a ``print(*L)`` isto što i ``print(1,2,3)`` (ispis 3 broja). .. literalinclude:: z2z1c_1.py :language: python .. literalinclude:: z2z1c_1.py.filtered :language: text Više o pozivima funkcija, ``*args`` i ``**kwargs`` u odjeljku :ref:`fun`. Zadaća 3 (:obj:`zip`, :obj:`input`, :func:`math.sqrt`) --------------------------------------------------------- Zadatak 4 ^^^^^^^^^^^^^^^^^ Promotrimo ovaj primjer: .. literalinclude:: z3z4_2.py.filtered :language: pycon Vidimo kako je moguće jednostavno raditi operacije nad dvjema listama, tako da se uzima prvi (100) s prvim (3), drugi (200) s drugim (4), itd. To iskoristimo za rješavanje zadatka. .. literalinclude:: z3z4_1.py :language: python Unesemo ``2 1 0 1 1`` kao input. Rezultat je: .. literalinclude:: z3z4_1.py.filtered :language: text Zadaća 4 ---------- Problemi opisani u zadaći 4 ne javljaju se u pythonu jer u pythonu "nema" pointera, a i provjerava se da indeks polja bude unutar trenutno dopuštenog opsega. [U CPythonu možemo doznati adresu pomoću funkcije :func:`id`, ali na adrese ne možemo upisivati direktno.] Zadaća 5 (:func:`str.replace`) ----------------------------------------------------------------------------------------------------------------------------------------------- Zadatak 3 ^^^^^^^^^^^^^^^^ Trivijalno jer python podržava rad s proizvoljno dugim cijelim brojevima. Zadatak 4 ^^^^^^^^^^^^^^^^ Trivijalno jer već postoji takva funkcija u pythonu. .. literalinclude:: z5z4_1.py :language: python .. literalinclude:: z5z4_1.py.filtered :language: text .. _zadaca6: Zadaća 6 (:func:`itertools.groupby`) ----------------------------------------------------------------------------------------------------------------------------------------------- Zadaci 2a i 2b ^^^^^^^^^^^^^^^^ Za rješavanje ovog zadatka dobro može poslužiti funkcija ``groupby`` iz modula ``itertools``. Ta funkcija razdvaja listu ili string na dijelove: .. literalinclude:: z6_1.py.filtered :language: pycon Koristeći to, lako je napraviti ``rle.py`` i ``unrle.py``. .. literalinclude:: rle.py :language: python .. literalinclude:: unrle.py :language: python Da bi se ti programi mogli pokretati kao samostalni, potrebno je dodati pravo izvršavanja. .. literalinclude:: z6.sh.filtered :language: text Kad datoteku ``z6src.py`` .. literalinclude:: z6src.txt :language: text komprimiramo .. literalinclude:: z6_1.sh.filtered :language: text dobijemo .. literalinclude:: z6out.txt :language: text Kad taj rezultat dekomprimiramo .. literalinclude:: z6_2.sh.filtered :language: text dobijemo nazad početni sadržaj .. literalinclude:: z6out2.txt :language: text Naravno, ovdje se pretpostavljalo, kako je rečeno u zadatku, da se znakovi neće ponavljati više od 9 puta. Zadaća 7 -------------- Zadatak 2 ^^^^^^^^^^^^^^^^ Rješenje je: .. literalinclude:: rr.py :language: python Tu smo koristili pythonov dictionary i time smo izbjegli potrebu za velikim brojem if-ova. Funkcija ``isprint`` ne postoji u pythonu, ali možemo pogledati kako je napravljena u C-u pa taj kôd prevesti u python. Gornju datoteku nazovemo ``rr.py``. Krećemo od datoteke iz jednog od prethodnih primjera: .. literalinclude:: z7_3.sh.filtered :language: text Kad postavimo flag izvršavanja datoteci ``rr.py`` možemo radi testiranja pokrenuti program nad podacima u ``bin1.bin``. .. literalinclude:: z7_21.sh.filtered :language: text Zaključujemo da postoji prazan prostor (zbog alignmenta) u byteovima redni broj 10 i 11. .. _exc: Zadaća 8 (:keyword:`try` ... :keyword:`except` ... ``else``, :keyword:`raise`) ----------------------------------------------------------------------------------------------------------------------------------------------- Zadatak 2 ^^^^^^^^^^^^^^^^ U pythonu postoji funkcija ``read`` slična traženoj. Python se brine oko dealokacije. Duljina ``N`` nam nije potrebna jer uvijek možemo koristiti ``len``. Prikazat ćemo dva rješenja: prvo nepotpuno ali iznimno jednostavno, a zatim, drugo, potpuno rješenje. Za obradu grešaka u pythonu je prirodno koristiti tzv. ``try..except`` konstrukciju. Izvršavanje krene u ``try`` blok i izvršava se red po red ali ako dođe do greške odmah se **nepovratno** napušta ``try`` blok i prelazi u prvi kompatibilan ``except`` blok. (U ``except`` blok se ulazi samo ako se dogodi greška u ``try`` bloku koji mu prethodi. U ``else`` blok se ulazi samo ako se čitav prethodni ``try`` blok izvršio bez greške.) .. literalinclude:: readfile.py :language: python Ako bismo baš htjeli da povratne vrijednosti budu diferencirane kao što se traži u zadatku potrebno je dodati još provjera. .. literalinclude:: readfile2.py :language: python Isprobajmo sad oba primjera. Pogledajmo output sljedećih naredbi upisanih u terminal: .. literalinclude:: z8_11.sh.filtered :language: text Isprobajmo kako rade kad im se zada pogrešno ime datoteke odnosno ime datoteke koja ne postoji: .. literalinclude:: z8_2.sh.filtered :language: text Isprobajmo što se događa u slučaju kad im se zada ime postojeće datoteke za koju je ukinuto pravo čitanja: .. literalinclude:: z8_3.sh.filtered :language: text Vidimo da oba programa ispravno obrađuju greške. Poanta je da koristeći ``try/except`` lako možemo postići osnovnu obradu grešaka kao u prvom primjeru, te po potrebi nadograđivati kao u drugom primjeru.