From 6dbe02d844b81d455dda3086fc0f212f7abdca06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Mo=C5=BEina?= Recimo, da smo zbrali teže šestih študentov. Seznam tež zapišemo takole: Seznam (angl. list)
+ je zaporedje česarkoli, recimo števil, lahko pa tudi česa drugega. Števila
+ ali kaj drugega naštejemo, vmes pišemo vejice in vse skupaj zapremo v
+ oglate oklepaje in seznam, ki bo povedal, ali gre za študenta ali študentko Seznami lahko vsebujejo tudi še hujšo eksotiko. Imamo lahko, recimo, seznam
+ seznamov - vanj bomo, prikladno, stlačili (pod)sezname teža-ime-spol: To sicer navadno delamo malo drugače (pogosto celo precej drugače), a dokler
+ tega še ne znamo, bo dobro tudi tako. Mimogrede opazimo še dve stvari:
+ seznam lahko, če želimo, raztegnemo v več vrst, preprosto tako, da ne
+ zapremo oklepaja. Naredili bi lahko tudi tole Seznami lahko vsebujejo tudi še hujšo hujšo eksotiko. V resnici lahko
+ vsebujejo karkoli, celo, recimo, funkcije: Čemu bi kdo hotel narediti seznam funkcij?! I, zato da jih bo klical,
+ seveda. Pa kdaj kdo kliče funkcije s seznama?! Da, včasih pride prav. Nikjer tudi ne piše, da morajo biti vsi elementi seznama istega tipa. To smo
+ pravzaprav že izkoristili: podseznami s težo, imenom in spolom so vsebovali
+ število, niz in logično vrednost. Navrgli bi lahko še dve funkciji in en
+ seznam; pa ne bomo, to se ne dela. Če želimo sezname različnih tipov,
+ raje uporabimo terke. Kaj so terke, bomo izvedeli vsak čas.) Seznam je lahko tudi prazen ali pa ima en sam element Ali pa je poln praznih seznamov Terka (angl. tuple) je podobna seznamu. Kakšna je pomembna razlika,
+ bomo še videli, manj pomembna pa je ta, da pri terki namesto oglatih
+ oklepajev uporabljamo kar okrogle. (Skoraj) vse ostalo ostane enako: Pri terkah se nam - zaradi tega, kje in kako jih uporabljamo, pogosteje
+ zgodi, da vsebuje elemente različnih tipov. Recimo takole: Tudi seznam teža-ime-spol bi raje naredil takole: Tako kot seznami so tudi terke lahko prazne ( Terko smemo, zanimivo, pisati tudi brez oklepajev. Ker to ni preveč pregledno, pa to počnemo le v posebnih primerih, na katere
+bomo sproti opozorili. Včasih imamo seznam ali terko z nekaj elementi, ki bi jih radi priredili
+ več spremenljivkam. Recimo, da imamo Če želimo podatke prirediti spremenljivkam Doslej smo imeli pri prirejanju na levi strani vedno eno samo spremenljivko,
+ ki smo ji želeli prirediti vrednost na desni strani enačaja. Tu pa smo na
+ levi našteli več imen spremenljivk (tri), na desni pa mora biti za to terka
+ z enakim številom elementov (tremi). Terka? No, lahko je tudi seznam ali
+ niz. Več ko boste programirali v Pythonu, bolj boste čutili moč terk. Omenimo,
+recimo, da je z njimi mogoče napisati funkcijo, ki ne vrača ene, temveč več
+stvari. Vzemimo funkcijo V resnici funkcija ki pa smo jo kar mimogrede razpakirali v Seveda bi lahko rezultat funkcije priredili tudi eni sami spremenljivki -
+ v tem primeru bi bila ta spremenljivka terka. In seveda bi lahko terko nato še razpakirali. Kako v Pythonu zamenjamo vrednosti dveh spremenljivk? Želeli bi, da bi To seveda ne deluje. V prvi vrstici V drugih jezikih se navadno rešimo tako, da vrednost V Pythonu pa to ni potrebno. Spremenljivki preprosto zapakiramo v terko, ki
+ jo takoj razpakiramo nazaj, a v obratnem vrstnem redu. V resnici navadno ne pišemo tako, temveč izpustimo oklepaje. Oklepaje okrog terke izpuščamo preprosto zato, ker je takšno prirejanje
+ tako pogosto, da ga programer vajen Pythona takoj prepozna. Pri tem tudi
+ ne razmišljamo o terkah, temveč prirejanje preberemo preprosto tako, da
+ Python ima dve vrsti zank: zanki Zastavimo si preprosto nalogo (in ne čisto smiselno) nalogo: izpišimo teže
+ in kvadrate tež vseh študentov v seznamu. Se pravi (po slovensko): V Pythonu pa prav tako, samo brez sklonov: V zanki Zdaj pa izpišimo vse teže, ki so večje od 70. Napišimo program, ki pove, kako težak je najlažji študent. Je potrebno prevesti v slovenščino? Pa dajmo. Deluje ta program samo na seznamih števil? Ali pa bi znal poiskati tudi
+ najmanjši niz? Kako pravzaprav primerjamo nize? Nize primerja, seveda, po
+ abecedi. In, da, program deluje tudi na nizih, vrne "najmanjši" niz - prvi
+ niz po abecedi. Le v začetku moramo napisati
+ Mimogrede, Python ima že vdelano funkcijo Kako bi izračunali vsoto elementov seznama? Pa poprečno vrednost? Za to moramo poznati dolžino seznama. Pove nam jo
+funkcija Samo... malo previdni moramo biti. Seznam bi lahko bil tudi prazen.
+ Dogovorimo se, da bo poprečna vrednost v tem primeru 0. Pravilno delujoč
+ program bi bil takšen. Zanka for ne deluje le na seznamih. Tako, kot gre prek seznamov, lahko
+ gre tudi prek terk, nizov in še prek mnogih drugih reči. V Pythonu celo za
+ branje datotek pogosto uporabimo Kako bi ugotovili, ali vsebuje seznam kako sodo število? V začetku si rečemo, da nimamo nobenega sodega števila. Nato gremo prek
+vseh števil in čim naletimo na kakega sodega, zabeležimo, da smo, aleluja,
+našli sodo število. Ne naredite klasične napake. Tole je narobe: Ta program se bo ob vsakem lihem številu delal, da doslej ni bilo še
+nobenega sodega - zaradi Kako pa ugotovimo, ali ima seznam sama soda števila? Spet bomo naredili podobno napako kot prej, če bomo pisali: Program že takoj, ko vidi 1, ugotovi, da niso vsa števila v seznamu soda,
+in postavi Ko smo prejšnji teden pisali zanko Včasih to ni potrebno. Pravzaprav smo pravkar videli takšen primer:
+ rezultat gornjega programa je znan že, čim naletimo na prvo liho
+ število. Torej bi bilo čisto vseeno, če računalnik v tistem trenutku neha
+ pregledovanje. To mu v resnici lahko naročimo. Ukaz Mimogrede, na podoben način lahko prekinemo tudi Tule je bil Brez S tem, ko smo dodali Namesto dodatnega pogoja lahko napišemo S tem se program lahko pravzaprav še bolj poenostavi. Ko zanko prekinemo,
+ Medtem, ko je ukaz Oglejmo si še enkrat gornji program. Kar smo počeli v njem, je kar pogosto:
+ v zanki nekaj iščemo (recimo kako liho število). Če to reč najdemo, nekaj
+ storimo (ga izpišemo) in prekinemo zanko. Sicer (torej, če ga ne najdemo),
+ storimo kaj drugega (izpišemo, da ga nismo našli). Zgornji odstavek se približno, a ne čisto povsem prilega zadnjemu kosu
+programa. V resnici je napisan po spodnjem programu: Se pravi: če najdemo liho število, napišemo, da seznam vsebuje liho število
+in prekinemo zanko. Ta del je jasen. Ne spreglejte pa, kje je Preden naredimo še kakšen primer, si oglejmo še nekaj drugega. Tisti, ki poznajo kak drug, C-ju podoben jezik, so najbrž pričakovali
+ nekoliko
+ drugačno zanko. Poglejmo resnici v oči: v C, C++, C#, Javi sta zanka for in while le dva
+načina, na katera povemo eno in isto. je isto kot Če je ideja zanke for v C-ju podobnih jezikih ta, da se z njo šteje, pa
+ imamo v Pythonu za to nekaj priročnejšega in splošnejšega. V programih pogosto potrebujemo še dva tipa zank. Pogosto bomo želeli nekaj
+ponoviti vnaprej predpisano oziroma pred zanko izračunano število ponovitev, recimo
+petkrat ali desetkrat. Prav tako bomo pogosto želeli, da program "šteje" od
+10 do 20, od 0 do 100 ali kaj takega. Za oboje bo poskrbela kar zanka for, ob pomoči priročne funkcije
+ Funkcija V Pythonu 3.0 je ta funkcija narejena boljše kot v različicah pred njim,
+ vendar je nova oblika za začetnika manj očitna, zato bomo za trenutek
+ skočili v stari Python 2.7. Kar sledi, v novem Pythonu namreč ne bi dalo
+ enakih izpisov. Funkcija Funkcija Lepo se tudi sešteva. Funkcija ima lahko še en, tretji argument. Ta predstavlja korak. Korak je lahko tudi negativen. Funkcijo V prvi zanki Z zanko Seveda ostaja odprto vprašanje, zakaj bi si kdo tako želel izpisati števila
+od 1 do 10. Štetje je kljub temu uporabno tudi za kaj drugega, ne le za
+izpisovanje.
+ Napisati želimo program, ki pove, ali je dano število praštevilo. Za to bomo
+ preverili vsa števila od 2 do n-1: če katerokoli od njih deli
+ V začetku predpostavimo, da je število praštevilo
+ ( Ko je število enkrat obsojeno kot sestavljeno, ga ne moremo več "pomilostiti"
+ nazaj v praštevilo. Če je tako, pa tudi ni potrebe, da bi po tem, ko enkrat
+ odkrijemo delitelj, sploh še preverjali naslednje potencialne delitelje.
+ Zdaj pač že vemo: Nekoč na začetku predavanja smo imeli seznam študentov in njihovih tež: Recimo, da bi radi izpisali imean študentov in njihove teže. Če gremo prek seznama z zanko Gre pa še dosti elegantneje: razpakiranje lahko opravimo kar znotraj
+glave zanke, brez (nepotrebne) terke Program torej pravi Lahko pa se tudi malo igramo in izrišemo graf: Skoraj, ampak ne čisto. Vse skupaj bi radi še poravnali. O tem, kako se v
+ resnici oblikuje izpis, se bomo pogovarjali drugič, danes pa bomo s tem
+ opravili nekoliko po domače.
+ Predpostavimo, da so imena dolga največ 15 znakov. Pred vsako ime bomo
+ dopisali toliko presledkov, da bo skupna dolžina enaka 15. (Mimogrede
+ bom izdal, da dolžino niza dobimo s funkcijo Zdaj pa izpišimo imena in teže, pri tem, da se le-ta nahajajo v ločenih
+ seznamih. Naivno bi se lotili takole in potem obstali, ker na tem mestu ne moremo priti do teže študenta s tem
+ imenom. Do običajne in zelo zelo zelo napačne rešitve nas pripelje ta
+ zgrešeni premislek: zanko moramo speljati prek imen in prek tež, torej Rezultat je nepričakovan za vse tiste, ki ga niso pričakovali. Program
+ namreč izpiše Računalniki imajo to nadležno navado, da vedno naredijo natanko
+ tisto, kar jim naročimo. In v tem primeru smo mu naročili tole: Kdor ne razume, kaj se je zgodilo in zakaj, naj to nujno premisli, da se ne
+bo kasneje učil na lastnih napakah. Ko bo to opravljeno, bo razumel: potrebujemo samo eno zanko, ki gre
+ istočasno po obeh seznamih. Aha, takole? Ummm, ne. Ena zanka je ena zanka. To sta dve. Običajni rešitvi tega problema
+ sta dve. To, ki bi bila večini bližje, bom danes zamolčal, iz vzgojnih
+ razlogov (kdor jo bo odkril sam, jo pač bo; žal). Funkcija Opomba: tudi tale izpis je iz starega Pythona. Od verzije 3.0 si
+ lahko le predstavljamo, da Zipamo lahko vse, prek česar lahko naženemo zanko for. Torej ne le seznamov,
+ temveč tudi nize, terke in še kaj. Rešimo torej nalogo: izpišimo imena in teže iz ločenih seznamov. Za konec pa izpišimo še poprečno težo študentk. Seznami, terke in naši stari znanci nizi imajo nekaj skupnega. Pravzaprav
+ veliko skupnega. Razlikujejo se le v podrobnostih. Skupno jim je, recimo,
+ da imajo vsi trije dolžino. Gornji seznami šestih tež, šestih imen in
+ šestih indikatorjev spola so dolžine 6. Terka Seznami
+
+teze = [74, 82, 58, 66, 61, 84]
+
+[
in ]
. Za primer sestavimo še
+ seznam imen študentov:imena = ["Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc"]
+
+studentka = [False, False, True, False, True, False]
+
+podatki = [
+ [74, "Anze", False],
+ [82, "Benjamin", False],
+ [58, "Cilka", True],
+ [66, "Dani", False],
+ [61, "Eva", True],
+ [84, "Franc", False],
+ ]
+
+teze = [74, 82, 58,
+ 66, 61, 84]
+
+from math import *
+
+par_funkcij = [sin, cos, radians]
+
+prazen = []
+
+samo_edini = [42]
+
+polnoprazen = [[], [], [], [], [], []]
+
+
+
+Terka
+
+teze = (74, 82, 58, 66, 61, 84)
+imena = ("Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc")
+
+student = (74, "Anze", False)
+
+podatki = [
+ (74, "Anze", False),
+ (82, "Benjamin", False),
+ (58, "Cilka", True),
+ (66, "Dani", False),
+ (61, "Eva", True),
+ (84, "Franc", False),
+ ]
+
+()
) ali pa imajo
+ po en sam element. Tu imamo težavo pri terki z enim samim elementom: Če bi
+ napisali (42)
to ni seznam, temveč le 42 v oklepaju (odvečnem,
+ seveda). Da bi povedali, da gre za terko, moramo dodati še vejico:samo_en = (42, )
+
+>>> t = 1, 2, 3, 4
+>>> t
+(1, 2, 3, 4)
+
+Razpakiranje v elemente
+
+student = (74, "Anze", False)
+
+teza
,
+ ime
in je_zenska
, bi to lahko storili takole:>>> teza, ime, je_zenska = student
+
+>>> a, b, c = [1, 2, 3]
+>>> a
+1
+>>> a, b, c = "xyz"
+>>> a
+'x'
+>>> b
+'y'
+>>> c
+'z'
+
+splitext
, ki ji damo ime datoteke,
+pa vrne njeno osnovno ime in njeno končnico.>>> from os.path import *
+>>> film = "Babylon 5 - 3x04 - Passing through Gethsemane.avi"
+>>> zac, konc = splitext(film)
+>>> zac
+'Babylon 5 - 3x04 - Passing through Gethsemane'
+>>> konc
+'.avi'
+
+splitext
vrne terko,>>> from os.path import *
+>>> splitext(film)
+('Babylon 5 - 3x04 - Passing through Gethsemane', '.avi')
+
+zac
in
+ konc
.>>> t = splitext(film)
+>>> t
+('Babylon 5 - 3x04 - Passing through Gethsemane', '.avi')
+
+ime, koncnica = t
+
+a = "Alenka"
+b = "Tina"
+
+a
postal "Tina" in b
"Alenka".
+ Naivnež bi napisal tale nesmisel:a = b
+b = a
+
+a
-ju priredimo
+ b
, se pravi, "Tina", v drugi vrstici pa b
-ju
+ a
, ki pa je medtem postal "Tina". Tako sta po tem
+ a
in b
enaka "Tina".a
-ja
+ spravimo na varno, preden ga povozimo.tmp = a
+a = b
+b = tmp
+
+a, b = (b, a)
+
+a, b = b, a
+
+a
-ju priredimo b
in b
-ju
+ a
.Zanka for
+
+while
, ki jo že poznamo, dela
+ družbo for
.za vsako težo s seznama teze stori tole:
+ izpiši težo in težo na kvadrat
+
+for teza in teze:
+ print(teza, teza ** 2)
+
+for
se skriva prirejanje. Zanka najprej
+ priredi spremenljivki teza
prvi element seznama
+ teze
. Nato se izvrši vsa koda bloka znotraj bloka
+ for
- tako, kot se je dogajalo v zanki while
.
+ V naslednji rundi priredi spremenljivki teza
drugi element in
+ spet izvede kodo znotraj bloka, ... ter tako naprej do konca seznama.for teza in teze:
+ if teza > 70:
+ print(teza)
+
+najlazji = 1000
+for teza in teze:
+ if teza < najlazji:
+ najlazji = teza
+print(najlazji)
+
+za začetek naj bo najlažja teža 1000 (gotovo bomo kasneje našli koga lažjega)
+za vsako težo iz seznama tež:
+ če je teža manjša od najmanjše doslej:
+ najlažja je ta teža
+izpiši najmanjšo težo
+
+najlazji = "ŽŽŽŽŽŽŽŽŽŽŽŽ"
namesto najlazji = 1000
.
+ (Tole se da sprogramirati tudi tako, da deluje za nize in za števila. A ne
+ bomo ubijali začetnikov s prezapletenimi programi.)min
, ki vrne
+ najmanjši element seznama.s = 0
+for teza in teze:
+ s += teza
+
+len
(okrajšava za length, če ji kot argument
+podamo nek seznam).s = 0
+for teza in teze:
+ s += teza
+s /= len(teze)
+
+s = 0
+for teza in teze:
+ s += teza
+if len(teze) > 0:
+ s /= len(teze)
+
+for
, kot se bomo kmalu
+ naučili.>>> ime = "Cilka"
+>>> for crka in ime:
+... print(crka)
+'C'
+'i'
+'l'
+'k'
+'a'
+
+
+Najdi takšnega, ki...
+
+s = [11, 13, 5, 12, 5, 16, 7]
+
+imamo_sodo = False
+for e in s:
+ if e % 2 == 0:
+ imamo_sodo = True
+if imamo_sodo:
+ print("Seznam vsebuje sodo število")
+else:
+ print("Seznam ne vsebuje sodega števila")
+
+s = [11, 13, 5, 12, 5, 16, 7]
+
+imamo_sodo = False
+for e in s:
+ if e % 2 == 0:
+ imamo_sodo = True
+ else:
+ imamo_sodo = False
+if imamo_sodo:
+ print("Seznam vsebuje sodo število")
+else:
+ print("Seznam ne vsebuje sodega števila")
+
+imamo_sodo = False
bo pozabil, da je
+kdajkoli videl kako sodo število. V gornjem seznamu bo, recimo, pregledal
+vsa števila, končal bo s 7 in si ob tem rekel imamo_sodo = False
.
+Rezultat bo tako napačen.sama_soda = True
+for e in s:
+ if e % 2 != 0:
+ sama_soda = False
+if sama_soda:
+ print("Seznam vsebuje sama soda število")
+else:
+ print("Seznam ne vsebuje samo sodih števil")
+
+s = [11, 13, 5, 12, 5, 16, 72]
+
+sama_soda = True
+for e in s:
+ if e % 2 != 0:
+ sama_soda = False
+ else:
+ sama_soda = True
+
+sama_soda = False
. Vendar melje seznam naprej in ob
+vsakem koraku znova nastavlja sama_soda
. Ko pride do 72, postavi
+sama_soda
na True
. To pa je ravno zadnje število;
+sama_soda
ostane True
... pa smo tam.Prekinjanje zank
+
+while
, smo postavili pogoj,
+ do kdaj naj se izvaja. Zanka for bo, če se vmes ne pripeti kaj posebnega,
+ šla vedno od začetka do konca seznama (terke, niza, datoteke...)sama_soda = True
+for e in s:
+ if e % 2 != 0:
+ sama_soda = False
+ break
+if sama_soda:
+ print("Seznam vsebuje sama soda število")
+else:
+ print("Seznam ne vsebuje samo sodih števil")
+
+break
pomeni, da želimo prekiniti zanko. Program skoči
+"ven" iz zanke in nadaljuje z izvajanjem ukazov, ki sledijo zanki.while
.break
skoraj bolj zaradi lepšega - da računalnik
+ne izgublja časa brez potrebe. Poskusimo napisati program, ki takrat, ko seznam
+ni vseboval samo sodih števil, izpiše prvo liho število.sama_soda = True
+for e in s:
+ if e % 2 != 0:
+ sama_soda = False
+ liho = e
+if sama_soda:
+ print("Seznam vsebuje samo soda števila")
+else:
+ print("Seznam ne vsebuje samo sodih števil: prvo liho število je", liho)
+
+break
tole ne deluje: namesto prvega izpiše zadnje liho
+število. Rešimo se lahko z dodatnim pogojem:sama_soda = True
+for e in s:
+ if e % 2 != 0 and sama_soda:
+ sama_soda = False
+ liho = e
+if sama_soda:
+ print("Seznam vsebuje samo soda števila")
+else:
+ print("Seznam ne vsebuje samo sodih števil: prvo liho število je", liho)
+
+and sama_soda
smo poskrbeli, da se bosta
+sama_soda = False
in liho = e
izvedla le prvič. Ko
+bomo postavili sama_soda
na False
, bomo dosegli, da
+pogoj ne bo nikoli nikoli več resničen.break
.sama_soda = True
+for e in s:
+ if e % 2 != 0 and sama_soda:
+ sama_soda = False
+ liho = e
+ break
+if sama_soda:
+ print("Seznam vsebuje samo soda števila")
+else:
+ print("Seznam ne vsebuje samo sodih števil: prvo liho število je", liho)
+
+e
ostane, kar je bil. Torej ne potrebujemo več spremenljivke
+liho
.sama_soda = True
+for e in s:
+ if e % 2 != 0:
+ sama_soda = False
+ break
+if sama_soda:
+ print("Seznam vsebuje samo soda števila")
+else:
+ print("Seznam ne vsebuje samo sodih števil: prvo liho število je", e)
+
+Else po zanki
+
+break
zelo običajna žival v vseh
+ programskih jezikih, ima Python še eno posebnost, povezano z zankami. V
+ večini programskih jezikov lahko else
uporabimo kot "odgovor"
+ na if
. V Pythonu pa lahko else
sledi tudi zanki
+ for
ali while
. V pogojnem stavku (if
)
+ se koda v else
izvede, če pogoj ni bil resničen. Po zanki se
+ else
izvede, če se zanka ni prekinila zaradi
+ break
. Torej, else
se izvede pri zankah, ki so
+ se iztekle "po naravni poti".for e in s:
+ if e % 2 != 0:
+ print("Seznam ne vsebuje samo sodih števil: prvo liho število je", e)
+ break
+else:
+ print("Seznam vsebuje samo soda števila")
+
+else
:
+poravnan je s for
ne z if
! Ta else
+se torej nanaša na for
. Kar napišemo v else
-u za
+for
, se zgodi, če se zanka ni prekinila z break
om.Štetje z zanko
+
+for
for(zacetek; pogoj; korak) {
+ koda;
+}
+
+zacetek;
+while(pogoj) {
+ koda;
+ korak;
+}
+
+range
.range
je na prvi pogled povsem neimpresivna. Vrača
+ sezname zaporednih števil.>>> range(5, 10)
+[5, 6, 7, 8, 9]
+>>> range(10, 20)
+[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
+>>> range(7)
+[0, 1, 2, 3, 4, 5, 6]
+>>> range(16)
+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
+
+range
je vrnila seznam celih števil, ki se začne pri
+ prvi vrednosti in konča eno pred zadnjo. Koliko elementov ima seznam,
+ ki ga vrne range(7)
? Sedem. Zato
+ ker vsebuje prvi element in ne zadnjega, in ker se začne z 0.range
je torej narejena praktično, ker se težko zmotimo
+glede tega, koliko elementov bo vrnila.range(10, 15) + range(15, 20)
so ravno
+vsa števila od 10 do 20. Če bi bil range(10, 15)
enak
+[10, 11, 12, 13, 14, 15]
, bi se v
+range(10, 15) + range(15, 20)
število 15 ponovilo dvakrat.>>> range(5, 15, 2)
+[5, 7, 9, 11, 13]
+
+>>> range(10, 0, -1)
+[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
+>>> range(10, 0, -3)
+[10, 7, 4, 1]
+>>> range(10, 0, -5)
+[10, 5]
+
+range
uporabljamo skoraj izključno v zankah
+ for
.while
, ki smo jo napisali, smo izpisali števila
+od 1 do 10, takole nekako:i = 1
+while i < 11:
+ print(i)
+ i += 1
+
+for
je preprostejši.for i in range(1, 11):
+ print(i)
+
+Praštevila
+
+n
, potem n
ni praštevilo.n = int(input("Vpiši število"))
+je_prastevilo = True
+for i in range(2, n):
+ if n % i == 0:
+ je_prastevilo = False
+
+je_prastevilo = True
), če med števili med 2 in n
+ (for i in range(2, n)
) naletimo na njegov delitelj
+ (if n % i == 0
), pa presodimo, da število pač ne more biti
+ praštevilo (je_prastevilo = False
). Mimogrede naj opozorimo
+ na napako, na katero stalno opozarjamo:n = int(input("Vpiši število"))
+je_prastevilo = True
+for i in range(2, n):
+ if n % i == 0:
+ je_prastevilo = False
+ else:
+ je_prastevilo = True # TO JE NAROBE!
+
+break
in else
po zanki.
+
+n = int(input("Vpiši število"))
+
+for i in range(2, n):
+ if n % i == 0:
+ print(n, "ni praštevilo, saj je deljivo z", i)
+ break
+else:
+ print(n, "je praštevilo")
+
+Razpakiranje v zanki
+
+for
code> in še malo telovadbepodatki = [
+ (74, "Anze", False),
+ (82, "Benjamin", False),
+ (58, "Cilka", True),
+ (66, "Dani", False),
+ (61, "Eva", True),
+ (84, "Franc", False),
+ ]
+
+for
, bomo dobivali terke. Te
+lahko, vemo, razpakiramo.for student in podatki:
+ teza, ime, spol = student
+ print(ime, ": ", teza)
+
+t
:for teza, ime, je_zenska in podatki:
+ print(ime, ": ", teza)
+
+za vsako trojko (teza, ime, je_zenska) iz seznama podatki:
+ izpisi ime in tezo
+
+for teza, ime, je_zenska in podatki:
+ print(ime + " " + "*"*teza)
+
+len
.)for teza, ime, je_zenska in podatki:
+ print(" "*(15 - len(ime)) + ime + " " + "*"*teza)
+
+
+Zanka po dveh seznamih
+
+teze = [74, 82, 58, 66, 61, 84]
+imena = ["Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc"]
+studentka = [False, False, True, False, True, False]
+
+
+for ime in imena:
+ print(ime, ":")
+
+
+
+for ime in imena:
+ for teza in teze:
+ print(ime, ": ", teza)
+
+
+Anze : 74
+Anze : 82
+Anze : 58
+Anze : 66
+Anze : 61
+Anze : 84
+Benjamin : 74
+Benjamin : 82
+Benjamin : 58
+Benjamin : 66
+Benjamin : 61
+Benjamin : 84
+Cilka : 74
+Cilka : 82
+Cilka : 58
+Cilka : 66
+Cilka : 61
+Cilka : 84
+Daniel : 74
+Daniel : 82
+Daniel : 58
+Daniel : 66
+Daniel : 61
+Daniel : 84
+Eva : 74
+Eva : 82
+Eva : 58
+Eva : 66
+Eva : 61
+Eva : 84
+Franc : 74
+Franc : 82
+Franc : 58
+Franc : 66
+Franc : 61
+Franc : 84
+
+
+
+za vsako ime na seznamu ime stori tole:
+ za vsako tezo na seznamu tez stori tole:
+ izpisi ime in tezo
+
+
+for ime in imena:
+for teza in teze:
+ print(ime, ": ", teza)
+
+
+zip
+ združi dva seznama (ali več seznamov) v seznam terk.>>> zip(teze, imena)
+[(74, 'Anze'), (82, 'Benjamin'), (58, 'Cilka'), (66, 'Daniel'), (61, 'Eva'), (84, 'Franc')]
+>>> zip(teze, imena, studentka)
+[(74, 'Anze', False), (82, 'Benjamin', False), (58, 'Cilka', True), (66, 'Daniel', False), (61, 'Eva', True), (84, 'Franc', False)]
+>>> zip(teze, imena, studentka, teze)
+[(74, 'Anze', False, 74), (82, 'Benjamin', False, 82), (58, 'Cilka', True, 58), (66, 'Daniel', False, 66), (61, 'Eva', True, 61), (84, 'Franc', False, 84)]
+
+zip
dela takole. V resnici naredi
+ nekaj majčkeno drugačnega (kaj, je za nas ta mesec še prezapleteno),
+ rezultat pa je isti.>>> zip("abcd", "ABCD")
+[('a', 'A'), ('b', 'B'), ('c', 'C'), ('d', 'D')]
+>>> zip("abcd", range(4))
+[('a', 0), ('b', 1), ('c', 2), ('d', 3)]
+
+
+for ime, teza in zip(imena, teze):
+ print(ime, ": ", teza)
+
+
+skupna_teza = 0
+studentk = 0
+for teza, je_zenska in zip(teze, studentka):
+ if je_zenska:
+ skupna_teza += teza
+ studentk += 1
+print(skupna_teza / (studentk or 1))
+
+
+
+Dolžina seznama, terke, niza
+
+1, 2, 3, 4
je
+ dolžine 4 in niz "Benjamin" je dolžine 8. Dolžine reči, ki imajo dolžino,
+ nam pove funkcija len
. To sem napisal tako imenitno, da bom
+ moral še enkrat, da bo sploh kdo razumel: funkcija len
sprejme
+ en argument, recimo seznam, terko ali niz in kot rezultat vrne dolžino
+ tega seznama, terke ali niza.>>> b = 'Benjamin'
+>>> len(b)
+8
+>>> len(podatki)
+6
+>>> len((1, 2, 3))
+3
+>>> len(12)
+Traceback (most recent call last):
+ File "
Morda je koga presenetilo zadnje: številka 12 bi lahko bila dolga 12, ne?
+ Ali pa 2, ker ima dve števki? Ne. Funkcija len
v bistvu pove
+ število elementov, ki jih vsebuje podani argument. Niz "Benjamin"
+ vsebuje 8 znakov, seznam podatki
vsebuje 6 podseznamov in
+ terka (1, 2, 3)
ima tri elemente. Število 12 pa nima
+ elementov.
Še ena prikladna značilnost seznamov (nizov, terk in še česa): prazni + seznami so, tako kot prazni nizi, neresnični. Seznam lahko uporabimo v + pogoju. +
if s: + print("Seznam s ni prazen") +else: + print("Seznam s je prazen")+ + +
Do elementov seznamov, terk in nizov ne pridemo le z zanko for. Dobimo jih + lahko tudi tako, da preprosto zahtevamo element na tem in tem mestu. + Vzemimo za primer seznam imen. Spomnimo se, kako je videti.
+ +>>> imena +['Anze', 'Benjamin', 'Cilka', 'Dani', 'Eva', 'Franc']+ +
Spremenljivka imena
vsebuje šest elementov. Če hočemo dostopati
+ do posameznega elementa - recimo izpisati njegovo vrednost - povemo njegov
+ indeks, "zaporedno številko". Zapišemo jo v oglate oklepaje za imenom
+ spremenljivke, takole:
>>> imena[2] +'Cilka'+ +
Se pravi, imena[2]
vrne drugi element seznama.
Emmm, drugi?! Mar ni drugi element Benjamin, ne Cilka? Drži, ampak kakor + šteje python, je drugi element Cilka. Anže je pa ničti. Ne le v pythonu, + skoraj v vseh jezikih štejemo od 0. Prvi element ima indeks 0, + drugi element 1 in tretji 2. Zakaj? Razlogi so tehnični in praktični. + Tehničnega boste razumeli, ko boste (če boste) poslušali predavanja iz Cja. + Tradicionalno indeks pomeni "odmik od začetka": ko je odmik 0, dobimo prvi + element in ko je odmik 2, se odmaknemo dva elementa, torej pristanemo na + tretjem. Medtem ko je v Cju (in še nižjih jezikih) ta, tehnični, argument + morda smiseln, upravičimo štetje od ničle v Pythonu in drugih višjih + jezikih s praktičnostjo: reči se tako lepše izidejo. Boste videli.
+ +Če je koga zmedlo, povejmo na glas: oglati oklepaji imajo dve vlogi. Prej + smo jih uporabljali, da smo vanje zaprli seznam, zdaj vanje zapiramo + indekse. Naj vas to ne vznemirja, python bo že pravilno razumel, kaj + mislite, celo v tako hecnih situacijah, kot je tale:
+ +>>> [3, 1, 4, 1, 5, 9][2] +4+ +
Prvi oklepaji definirajo seznam, drugi zaprejo indeks, 2, ki pove, kateri
+ element tega seznama nas zanima.
+[
+Zveni bedasto in neuporabno? Potem mi povejte, ali je bedasto in neuporabno
+ tole:
+
["moski", "zenska"][spol[0]]+in tole +
"MZ"[spol[0]]+] + + +
Na enak način kot sezname indeksiramo tudi terke in nize.
+>>> 'Benjamin'[0] +'B' +>>> 'Benjamin'[2] +'n'+ +
Kadar seznam vsebuje sezname, bomo včasih uporabljali dvojne indekse.
+ Spomnimo se seznama podatki
: vsebuje šest elementov, in ti
+ elementi so spet seznami s po tremi elementi, ki predstavljajo težo, ime
+ in spol. Vzemimo, recimo, drugi element:
>>> en_student = podatki[2] +>>> en_student +[58, "Cilka", True]+ +
Zdaj lahko o Cilki nekaj povemo.
+ +>>> print(en_student[1], "tehta", en_student[0], "kilogramov.") +Cilka tehta 58 kilogramov.+ +
Lahko pa opravimo oboje v enem zamahu.
+ +>>> print(podatki[2][1], "tehta", podatki[2][0], "kilogramov.")+ +
podatki[2][0]
pomeni (če preberemo z desne) ničti element
+ drugega elementa seznama podatki
. Če se vam zdi to hudo, vas
+ lahko potolažim, da ni: v resnici je še bolj grozno. Ker je
+ podatki[2][1]
niz, se lahko vprašamo po, recimo, tretji črki
+ tega niza.
+
+
>>> print("Tretja crka niza", podatki[2][1], "je", podatki[2][1][3])+ +
(V kost za glodanje C-jašem pa naj vprašam, ali
+ podatki[2][1][3][0][0][0][0]
kaj izpiše ali se pritoži, da je
+ tu nekaj narobe. Ampak to je pa res neuporabno.)
Kaj se zgodi, če je indeks prevelik? Nič lepega.
+ +>>> "Benjamin"[100] +Traceback (most recent call last): + File "+ +", line 1, in +IndexError: string index out of range
Kako velik pa je lahko indeks? Če ima niz osem črk in je prva ničta, je
+ zadnja sedma. Indeks mora biti torej manjši od dolžine - največji dovoljeni
+ indeks je tisto, kar vrne funkcija len
, minus 1.
Python (in še marsikateri današnji jezik) ima še en trik: indeksiranje s + konca: -1 je zadnji element, -2 predzadnji in tako naprej.
+ +>>> 'Benjamin'[-1] +'n' +>>> 'Benjamin'[-2] +'i' +>>> 'Benjamin'[-3] +'m'+ + +
Poleg indeksiranja, ki vrača elemente nizov, seznamov, terk (in še česa), + pozna Python še rezanje (slice), ki vrača dele nizov, seznamov, + terk (in še česa). Rezino opišemo z indeksom prvega elementa in indeksom + prvega elementa, ki ga ne želimo več vključiti v rezino. Med indeksa + postavimo dvopičje. Se pravi, rezina 2:5 pomeni vse elemente od onega z + indeksom 2 do tistega z indeksom 4 (ne 5!).
+ +Smo to že kje videli? Smo, seveda. Funckija range
uporablja
+natančno isto logiko. Tako kot pri range
, je tudi pri rezanju
+to odlična ideja.
Oglejmo si, kaj na to pravi Benjamin.
+>>> b[2:5] +'nja' +>>> b[5:8] +'min' +>>> b[2:5]+b[5:8] +'njamin'+ +
Spodnjo ali zgornjo mejo smemo tudi izpustiti. V tem primeru dobimo vse + elemente od začetka oz. do konca. Tu bosta izkazali svojo moč prav obe + navidez neintuitivni pravili - štetje od 0 in to, da rezina ne vključuje + zadnjega elementa.
+ +>>> b[:5] +>>> b[:5] +'Benja' +>>> b[5:] +'min'+ +
b[:5]
vrne prvih pet elementov. b[5:]
vrne vse
+ od petega naprej; ker štejemo od 0, to pomeni, da izpustimo prvih pet. Se
+ pravi, če želimo nizu s
odbiti prvih pet znakov, bomo rekli
s = s[5:]+ +
Da peti študent vstane le enkrat, nam pride prav, če želimo v niz kaj + vriniti. Če bi radi za petim znakom niza vrinili X, to storimo takole:
+ +>>> b[:5]+"X"+b[5:] +'BenjaXmin'+ +
Ste opazili, da nam sploh ni bilo treba pomisliti na to, da štejemo od 0? + Vidite, kako naravno je to. Če bi šteli od 1, bi bilo tole precej bolj + zapleteno.
+ +Še dodatne možnosti prinese indeksiranje od zadaj. Iz niza lahko poberemo, + recimo, elemente od predpredpredzadnjega (-5) do predzadnjega (-2). Koliko + jih bo? Trije, seveda.
+ +>>> b[-5:-2] +'jam'+ +
No, tegale najbrž ne uporabimo velikokrat. Pač pa nas pogosto zanimajo, + recimo, zadnji štirje znaki. Ali pa vsi razen zadnjih štirih.
+ +>>> film = "Babylon 5 - 3x04 - Passing through Gethsemane.avi" +>>> film[-4:] +'.avi' +>>> film[:-4] +'Babylon 5 - 3x04 - Passing through Gethsemane'+ +
Mimogrede, tole sicer varneje delamo s funkcijo, ki smo jo že omenili,
+ namreč splitext
, ki prejme kot argument ime datoteke in vrne
+ terko z dvema elementoma, imenom datoteke brez končnice in končnico.
Kako pa bi od niza odbili prve tri in zadnja dva znaka? Takole:
+ +>>> b[3:-2] +'jam'+ +
Že tale primer pokaže, zakaj je štetje od 0 in čudno pravilo, po katerem je + prvi element rezine vključen, zadnji pa ne, tako smiselno in uporabno. + Tisti, ki bi v vsej stvari vendarle videli še kako logiko, pa bo morda + prepričala spodnja tabelica, ob kateri lahko še enkrat premislijo vse + primere.
+ +0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | + | ||||||||
B | e | n | j | a | m | i | n | +||||||||||
-8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 | + |
Vsi znaki med drugim in petim so 'nja', znaki od 3 do -2 so 'jam'... In tako + naprej.
+ +Vendar še nismo končali. Izpustimo lahko tudi zgornjo in spodnjo mejo. Kaj + dobimo v tem primeru? Cel niz. Je to uporabno? Na nizih pravzaprav ne. Pri + čem drugem pa nam bo prišlo še prav.
+ +Poleg meja rezine lahko podamo tudi korak. Namesto vsakega znaka + lahko zahtevamo, recimo, vsak drugi znak, tako da dodamo še eno dvopičje, + ki mu sledi velikost koraka.
+ +>>> '0123456789'[2:9] +'2345678' +>>> '0123456789'[2:9:2] +'2468' +>>> '0123456789'[2:9:3] +'258' +>>> '0123456789'[2:9:4] +'26'+ +
Korak je lahko, tako kot pri range
tudi negativen! V tem
+ primeru je potrebno zamenjati meji - prva mora biti višja od druge.
>>> '0123456789'[9:2:-1] +'9876543' +>>> '0123456789'[9:2:-2] +'9753'+ +
Meje smemo seveda spet tudi izpuščati:
+ +>>> '0123456789'[9::-1] +'9876543210'+ +
Takole obrnemo predavatelja.
+ +>>> 'demšar janez'[::-1] +'zenaj rašmed'+ +
Vse tole je videti nekoliko zapleteno in tuje. In morda je: povaditi bo
+ treba, pa se bo udomačilo. Pa se splača? Za odbijanje znakov od nizov? Se!
+ Lepota je v tem, da se natanko enako kot indeksiranje in rezanje nizov
+ obnaša tudi indeksiranje seznamov in vsega drugega. Pa še kaj - zanke
+ for
, recimo, ki jih bomo vsak čas spoznali.
Poglejmo si torej še rezanje seznamov.
+ +>>> imena = ["Anze", "Benjamin", "Cilka", "Dani", "Eva", "Franc"] +>>> imena[2:5] +['Cilka', 'Dani', 'Eva'] +>>> imena[2:] +['Cilka', 'Dani', 'Eva', 'Franc'] +>>> imena[:2] +['Anze', 'Benjamin'] +>>> imena[:-2] +['Anze', 'Benjamin', 'Cilka', 'Dani'] +>>> imena[-2:] +['Eva', 'Franc'] +>>> imena[::-1] +['Franc', 'Eva', 'Dani', 'Cilka', 'Benjamin', 'Anze']+ +
Že videno. Rezanje + seznamov se vede enako kot rezanje nizov. Rezanje terk pa prav tako.
+ + +Tole je preprosto. Vsak element seznama se vede na nek način kot + spremenljivka: lahko mu priredimo vrednost in s tem "povozimo" prejšnjo + vrednost.
+ +>>> imena +['Anze', 'Benjamin', 'Cilka', 'Dani', 'Eva', 'Franc'] +>>> imena[3] = "Daniel" +>>> imena +['Anze', 'Benjamin', 'Cilka', 'Daniel', 'Eva', 'Franc']+ +
Tako kot prej lahko tudi zdaj indeksiramo od spredaj ali od zadaj.
+ +(Za tiste, ki znate kak drug jezik, predvsem Php: elementov ni mogoče
+ dodajati s prirejanjem! Pythonovi seznami niso ekvivalentni Phpjevim: temu,
+ česar se v phpju reče array
, je bližji pythonov slovar
+ (dictionary, dict
), ki ga bomo spoznali v
+ prihodnosti.)
Pa rezine? Glede na to, da je rezina podseznam, moramo tudi pri prirejanju + rezin prirejati podsezname.
+ +>>> imena +['Anze', 'Benjamin', 'Cilka', 'Daniel', 'Eva', 'Franc'] +>>> imena[1:4]=["Ben", "Cecilija", "Dani"] +>>> imena +['Anze', 'Ben', 'Cecilija', 'Dani', 'Eva', 'Franc']+ +
Mora biti seznam, ki ga prirejamo, enako dolg kot rezina, ki jo bomo + povozili? Ne, čemu? Takole zamenjamo tri z dvema:
+ +>>> imena[1:4]=["Ben-Cecil", "Daniel"] +>>> imena +['Anze', 'Ben-Cecil', 'Daniel', 'Eva', 'Franc'] ++ +
Ali pa nobenega s tremi:
+ +>>> imena[2:2] = ["D2", "D3", "D4"] +>>> imena +['Anze', 'Ben-Cecil', 'D2', 'D3', 'D4', 'Daniel', 'Eva', 'Franc']+ +
Z rezinami lahko tudi pobrišemo del seznama.
+ +>>> imena +['Anze', 'Ben-Cecil', 'D2', 'D3', 'D4', 'Daniel', 'Eva', 'Franc'] +>>> imena[2:5] +['D2', 'D3', 'D4'] +>>> imena[2:5]=[] +>>> imena +['Anze', 'Ben-Cecil', 'Daniel', 'Eva', 'Franc']+ +
Za brisanje obstaja še veliko drugih načinov, recimo tale
+>>> imena +['Anze', 'Ben-Cecil', 'Daniel', 'Eva', 'Franc'] +>>> del imena[2] +>>> imena +['Anze', 'Ben-Cecil', 'Eva', 'Franc'] +>>> del imena[1:3] +>>> imena +['Anze', 'Franc']+ +
Če kdo pričakuje, da bomo zdaj povedali še, da enako delamo tudi z nizi in + terkami ... se moti. Nizov in terk ne moremo spreminjati!
+ +>>> b = 'Benjamin' +>>> b[2]='a' +Traceback (most recent call last): + File "+ +", line 1, in +TypeError: 'str' object does not support item assignment
Tu je torej osnovna razlika med seznamom in terko: seznam je spremenljiv, + terka ne. Tudi niza ne moremo spreminjati, kakor smo pravkar videli. Kako + pa bi potem zamenjali tretji znak niza b s črko 'a'?
+ +>>> b = b[:2]+'a'+b[3:] +>>> b +'Beajamin'+ +
To je seveda nerodno. Čemu je torej tako? Čemu ne moremo spreminjati nizov + tako, kot sezname? (In čemu sploh ta trapasta terka?) Videli bomo, da nam + pride včasih zelo zelo prav, da so nekateri objekti nespremenljivi. + (Nekateri - pogosto tudi jaz - pravijo celo, da jeziki sploh ne bi smeli + dopuščati spreminjanja spremenljivk.) Nize pa si v resnici redko želimo + spreminjati - da, pogosto jih bomo sestavljali ali obtesovali, zelo redko + pa si želimo spreminjati posamezne črke. Zato nas to, da so konstantni, ne + bo preveč motilo, velikokrat pa nam bo koristilo.
+ + +V svojem prvem soočenju s programiranjem smo spoznali aritmetične izraze:
+ seštevali in množili smo števila, jih kvadrirali in računali sinuse.
+ Zadnjič smo naleteli na logične izraze, kjer smo računali z logičnimi
+ vrednostmi, True
in False
. Danes je čas, da se
+ nehamo čuditi ob vsakem izrazu posebej in jim dajati pridevke "aritmetični"
+ "logični" in tako naprej. Računati se da pač z različnimi rečmi in ena od
+ teh reči so tudi seznami.
Lahko sezname seštevamo? Kaj dobimo, če seštejemo [2, 5, -1]
in
+ [3, 7, 4]
? Dobimo [5, 12, 3]
ali
+ [2, 5, -1, 3, 7, 4]
? Oboje bi bilo smiselno, odgovor pa je
+ takšen: če so se seznami doslej vedli tako podobno nizom, naj se še glede
+ seštevanja.Ker je 'abc' + 'def'
enako 'abcdef'
,
+ naj bo tudi [2, 5, -1] + [3, 7, 4]
enako
+ [2, 5, -1, 3, 7, 4]
.
Podobno je z množenjem. [2, 5, -1] * 2
bi moralo biti po vsej
+ logiki enako [2, 5, -1] + [2, 5, -1]
, se pravi
+ [2, 5, -1, 2, 5, -1]
. In tudi je.
K seznamu lahko prištejemo le seznam, k nizu niz, k terki terko. Vse tri pa + lahko pomnožimo s celim številom - in z ničemer drugim.
+ +Poleg +
in *
pa poznajo vsi trije še dva
+ operatorja, in
in not in
. S prvim vprašamo, ali
+ seznam oz. terka vsebujeta določen element in ali niz vsebuje določen
+ podniz.
>>> 1 in [1, 2, 3] +True +>>> 4 in [1, 2, 3] +False +>>> 'in' in 'Benjamin' +True +>>> 'an' in 'Benjamin'+ +
Drugi je seveda ravno nasproten, z njim se vprašamo ali seznam (niz) + ne vsebuje elementa (podniza).
+ +>>> 1 not in [1, 2, 3] +False +>>> 4 not in [1, 2, 3] +True +>>> 'in' not in 'Benjamin' +False +>>> 'an' not in 'Benjamin' +True+ +
V resnici not in
ni prav potreben, saj je
+ x not in l
isto kot not x in l
.
for
.'
\ No newline at end of file
diff --git a/python/problems/recursion/find_sum/common.py b/python/problems/recursion/find_sum/common.py
new file mode 100644
index 0000000..f61baa3
--- /dev/null
+++ b/python/problems/recursion/find_sum/common.py
@@ -0,0 +1,75 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc, \
+ all_tokens, has_comprehension, has_loop, almost_equal, get_ast
+from server.hints import Hint
+
+id = 20809
+number = 9
+visible = True
+
+solution = '''\
+def find_sum(xs, gs):
+ if gs < 0:
+ return False
+ if gs == 0:
+ return True
+ if not xs:
+ return False
+ return find_sum(xs[1:], gs-xs[0]) or find_sum(xs[1:], gs)
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code, aux_code=''):
+ func_name = 'find_sum'
+ tokens = get_tokens(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+ in_out = [
+ (([2,7,3,1,4], 10), True),
+ (([2,3,2,4], 10), False),
+ (([], 10), False),
+ (([1,2,3], 2), True),
+ (([1,2,3], 7), False),
+ (([2,7,3,1,4], 9), True),
+ (([2,7,3,2,4], 17), False),
+ ]
+
+ test_in = [('{0}{1}'.format(func_name, str(l[0])), None)
+ for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(code=aux_code+code, inputs=test_in, timeout=1.0)
+ n_correct = 0
+ tin, tout = None, None
+ for i, (ans, to) in enumerate(zip(answers, test_out)):
+ res = ans[0]
+ corr = res == to
+ n_correct += corr
+ if not corr:
+ tin = test_in[i][0]
+ tout = to
+
+ passed = n_correct == len(test_in)
+ hints = [{'id': 'test_results', 'args': {'passed': n_correct, 'total': len(test_in)}}]
+ if tin:
+ hints.append({'id': 'problematic_test_case', 'args': {'testin': str(tin), 'testout': str(tout)}})
+ if passed:
+ hints.append({'id': 'final_hint'})
+
+ return passed, hints
+
+
+def hint(python, code, aux_code=''):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(code=aux_code+code, inputs=[(None, None)], timeout=1.0)
+ exc = get_exception_desc(answer[0][3])
+ if exc: return exc
+
+ return None
diff --git a/python/problems/recursion/find_sum/en.py b/python/problems/recursion/find_sum/en.py
new file mode 100644
index 0000000..0d1807c
--- /dev/null
+++ b/python/problems/recursion/find_sum/en.py
@@ -0,0 +1,13 @@
+id = 20809
+name = 'Find sum'
+
+description = '''\
+(translation missing)
''' + +hint = { + 'plan': '''\ +(translation missing)
''', + + 'no_input_call': '''\ +(translation missing)
''', +} diff --git a/python/problems/recursion/find_sum/find_sum.py b/python/problems/recursion/find_sum/find_sum.py new file mode 100644 index 0000000..85f472b --- /dev/null +++ b/python/problems/recursion/find_sum/find_sum.py @@ -0,0 +1,19 @@ +def find_sum(xs, gs): + if gs < 0: + return False + if gs == 0: + return True + if not xs: + return False + return find_sum(xs[1:], gs-xs[0]) or find_sum(xs[1:], gs) + +print (find_sum([2,7,3,1,4], 10)) +print (find_sum([2,3,2,4], 10)) +print (find_sum([], 10)) +print (find_sum([1,2,3], 2)) +print (find_sum([1,2,3], 7)) +print (find_sum([2,7,3,1,4], 9)) +print (find_sum([2,7,3,2,4], 17)) + + + diff --git a/python/problems/recursion/find_sum/sl.py b/python/problems/recursion/find_sum/sl.py new file mode 100644 index 0000000..00aad43 --- /dev/null +++ b/python/problems/recursion/find_sum/sl.py @@ -0,0 +1,28 @@ +import server +mod = server.problems.load_language('python', 'sl') + +id = 20809 +name = 'Išči vsoto' + +description = '''\ +
+Napiši funkcijo find_sum(xs, gs)
, ki kot argument prejme seznam
+pozitivnih števil in število, ki predstavlja ciljno vsoto. Funkcija vrne
+True
, kadar lahko sestavimo ciljno vsoto iz števil v seznamu.
+>>> find_sum([2,7,3,1,4], 10) +True +>>> find_sum([2,3,2,4], 10) +False ++''' + +plan = [] + +hint = { + 'final_hint': ['''\ +
Program je pravilen!
+