Naloga za vajo

Spoznali smo koncept imenskih prostorov. Predvsem bodo pomembni tisti, ki se nanašajo na funkcije, zato smo zanje porabili tudi največ časa. Žal si za to ne znam izmisliti primerno enostavne naloge. Pač pa je tule ena druga.

Inspiracija prihaja z Advent of code, naloga Some Assembly Required, ki smo jo imeli v malo predelani obliki tudi za domačo nalogo pri Programiranju 1. Zdaj jo bomo rešili preprosteje.

Uporabljali boste eno od naslednjih dveh funkcij.

  • eval kot argument podamo izraz in vrne njegovo vrednost. Kot drugi argument ji lahko damo slovar, ki ga bo eval uporabljal kot imenski prostor, iz katerega bo bral spremenljivke. (V dokumentaciji je še par detajlov v zvezi s tem.)

  • exec, ki ne dobi le izraza temveč blok, recimo nek račun, kot je z = a + 2 in ga izvede. Kot dodaten argument spet lahko podamo slovar, ki bo služil za imenski prostor.

    >>> t = {"a": 5}
    >>> exec("z = a + 2", t)
    >>> t["z"]
    7
    

Ogrevalna naloga

V datoteki urejeno.txt je seznam računov. Začne se takole:

c = 0
b = 1674
t = c << 1
v = b >> 1
f = b >> 5
d = b >> 2
e = b >> 3
g = e | f
h = e & f
i = ~ h
j = g & i
l = d & j
m = ~ l

Vrstice so urejene tako, da so v vsaki vrstici že znane vse vrednosti, ki so potrebne za njen izračun. Ko, recimo, pridemo do j = g & i, sta g in i že znana. Račune lahko torej računamo po vrsti.

Napišite program, ki s pomočjo funkcije exec ali eval izvaja vrstico za vrstico, na koncu pa izpiše vrednost, ki jo ima a. Vrednosti spremenljivk naj se shranjujejo v slovarju, ne v "resničnem" globalnem imenskem prostoru. (Z drugimi besedami, funkciji exec ali eval podajte tudi drugi argument, slovar.)

Ne komplicirajte: rešitev bi morala biti dolga štiri vrstice.

Obvezna naloga

Obveznih nalog ne bo. :)

Dodatna naloga

V bistvu isto, le da vrstice niso urejene (datoteka "neurejeno.txt"). Zanima nas le vrednost a.

Ena rešitev - ni najhitrejša, a se vseeno izvede v trenutku - je takšna. Spet uporabljamo imenski prostor, ki je kar v slovarju. Dokler se v tem slovarju ne pojavi a, ponavljamo tole. Gremo prek vseh izrazov v datoteki (imamo torej zanko znotraj zanke). Za vsak izraz preverimo, ali imamo vse spremenljivke, potrebne za njegov izračun. "Spremenljivke" so shranjene v imenskem prostoru, ki je v resnici naš slovar. Zanima nas torej, ali se spremenljivka pojavi kot ključ v slovarju (recimo t, če ga imenujete tako, kot smo ga zgoraj). Če imamo vse spremenljivke, izračunamo vrednost in jo shranimo v slovar (z exec ali eval, kakor se boste pač lotili).

Kako pridemo do spremenljivk? Da se ne boste, kot v oni domači nalogi, mučili s split, je tule regularni izraz, ki vrne vse spremenljivke.

>>> import re
>>> spr = re.compile("[a-z_]+")
>>>
>>> spr.findall("foo = bar - 7 * baz")
['foo', 'bar', 'baz']
>>> spr.findall("a = 7")
['a']

V programu vas bo zanimalo le, ali obstajajo vse spremenljivke, ki so desno od enačaja. Glede tega se boste pa že znašli.

Regularni izrazi so sicer tako uporabni, da se bomo o njih gotovo še pogovarjali.

Rešitev naj bi bila dolga kakih deset vrstic. Kot rečeno, to ni najhitrejša možna rešitev. Iskanje te sodi v domeno predmeta Algoritmi in podatkovne strukture, ne sem. :)

Datoteke