summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Možina <martin.mozina@fri.uni-lj.si>2016-10-11 14:39:50 +0200
committerMartin Možina <martin.mozina@fri.uni-lj.si>2016-10-11 14:39:50 +0200
commit29bc34810cb1d1fbd208f6b5f2dad73188ca7f12 (patch)
tree0501d9274c6f87aa8a0aa4d273c364f0923d9063
parent8fd61c5d99aee8bf08871d306f1392b1bebd97aa (diff)
- new exercises on recursion
- added text (lectures) on conditions and loops
-rw-r--r--python/problems/recursion/binary/common.py75
-rw-r--r--python/problems/recursion/binary/en.py13
-rw-r--r--python/problems/recursion/binary/sl.py30
-rw-r--r--python/problems/recursion/factorial/common.py75
-rw-r--r--python/problems/recursion/factorial/en.py13
-rw-r--r--python/problems/recursion/factorial/sl.py37
-rw-r--r--python/problems/recursion/sum/common.py70
-rw-r--r--python/problems/recursion/sum/en.py13
-rw-r--r--python/problems/recursion/sum/sl.py32
-rw-r--r--python/problems/while_and_if/conditions_sl.html159
-rw-r--r--python/problems/while_and_if/ifclause_sl.html330
-rw-r--r--python/problems/while_and_if/loops_sl.html179
-rw-r--r--python/problems/while_and_if/sl.py4
13 files changed, 1029 insertions, 1 deletions
diff --git a/python/problems/recursion/binary/common.py b/python/problems/recursion/binary/common.py
new file mode 100644
index 0000000..585c5ff
--- /dev/null
+++ b/python/problems/recursion/binary/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 = 20808
+number = 8
+visible = True
+
+solution = '''\
+def binary(n):
+ if n <= 1:
+ return str(n)
+ return binary(n // 2) + str(n % 2)
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint'),
+ 'has_loop': Hint('has_loop')
+}
+
+def test(python, code, aux_code=''):
+ func_name = 'binary'
+ tokens = get_tokens(code)
+ ast = get_ast(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+ in_out = [
+ (3, '11'),
+ (2, '10'),
+ (1, '1'),
+ (0, '0'),
+ (42, '101010')
+ ]
+
+ 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:
+ if has_loop(ast):
+ hints.append({'id': 'has_loop'})
+ else:
+ 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/binary/en.py b/python/problems/recursion/binary/en.py
new file mode 100644
index 0000000..01440f7
--- /dev/null
+++ b/python/problems/recursion/binary/en.py
@@ -0,0 +1,13 @@
+id = 20808
+name = 'Binary'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/recursion/binary/sl.py b/python/problems/recursion/binary/sl.py
new file mode 100644
index 0000000..8360a46
--- /dev/null
+++ b/python/problems/recursion/binary/sl.py
@@ -0,0 +1,30 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+id = 20808
+name = 'Binarno'
+
+description = '''\
+<p>
+Napiši rekurzivno funkcijo <code>binary(n)</code>, ki kot argument prejme število
+<code>n</code> in kot rezultat vrne niz s tem številom v dvojiškem zapisu. </p>
+
+<pre>
+>>> binary(42)
+'101010'
+</pre>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+
+ 'has_loop': ['''\
+<p>Program sicer deluje pravilno, vendar vsebuje zanko.
+</p>
+'''],
+}
diff --git a/python/problems/recursion/factorial/common.py b/python/problems/recursion/factorial/common.py
new file mode 100644
index 0000000..fec787b
--- /dev/null
+++ b/python/problems/recursion/factorial/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 = 20806
+number = 6
+visible = True
+
+solution = '''\
+def factorial(n):
+ if n == 0:
+ return 1
+ return n * factorial(n - 1)
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint'),
+ 'has_loop': Hint('has_loop')
+}
+
+def test(python, code, aux_code=''):
+ func_name = 'factorial'
+ tokens = get_tokens(code)
+ ast = get_ast(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+ in_out = [
+ (0, 1),
+ (1, 1),
+ (2, 2),
+ (12, 479001600),
+ (20, 2432902008176640000)
+ ]
+
+ 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:
+ if has_loop(ast):
+ hints.append({'id': 'has_loop'})
+ else:
+ 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/factorial/en.py b/python/problems/recursion/factorial/en.py
new file mode 100644
index 0000000..616eacd
--- /dev/null
+++ b/python/problems/recursion/factorial/en.py
@@ -0,0 +1,13 @@
+id = 20806
+name = 'Factorial'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/recursion/factorial/sl.py b/python/problems/recursion/factorial/sl.py
new file mode 100644
index 0000000..a0269e3
--- /dev/null
+++ b/python/problems/recursion/factorial/sl.py
@@ -0,0 +1,37 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+id = 20806
+name = 'Fakulteta'
+
+description = '''\
+<p>
+Napiši rekurzivno funkcijo <code>faktorial(n)</code>, ki izračuna n!.
+Funkcija je definirana z enačbama <code>0! = 1</code> in
+<code>n! = n * (n - 1)!</code>.
+Rešitev ne sme vsebovati zanke <code>for</code> ali zanke <code>while</code>.</p>
+<pre>
+>>> faktorial(0)
+1
+>>> faktorial(1)
+1
+>>> faktorial(5)
+120
+>>> faktorial(20)
+2432902008176640000
+</pre>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+
+ 'has_loop': ['''\
+<p>Program sicer deluje pravilno, vendar vsebuje zanko.
+</p>
+'''],
+}
diff --git a/python/problems/recursion/sum/common.py b/python/problems/recursion/sum/common.py
new file mode 100644
index 0000000..9625a76
--- /dev/null
+++ b/python/problems/recursion/sum/common.py
@@ -0,0 +1,70 @@
+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 = 20807
+number = 7
+visible = True
+
+solution = '''\
+def sum(xs):
+ if not xs:
+ return 0
+ if isinstance(xs[0], list):
+ return sum(xs[0]) + sum(xs[1:])
+ return xs[0] + sum(xs[1:])
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code, aux_code=''):
+ func_name = '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 = [
+ ([], 0),
+ ([1,2,3,4,5], 15),
+ ([1, [], [2, 3, [4]], 5], 15),
+ ([1, [], [2, 3, [4]], 5, [[[[10], 6], [[7], 9], 8]]], 55),
+ ]
+
+ 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/sum/en.py b/python/problems/recursion/sum/en.py
new file mode 100644
index 0000000..a61f900
--- /dev/null
+++ b/python/problems/recursion/sum/en.py
@@ -0,0 +1,13 @@
+id = 20807
+name = 'Sum'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/recursion/sum/sl.py b/python/problems/recursion/sum/sl.py
new file mode 100644
index 0000000..e23bd97
--- /dev/null
+++ b/python/problems/recursion/sum/sl.py
@@ -0,0 +1,32 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+id = 20807
+name = 'Vsota seznama'
+
+description = '''\
+<p>
+Napiši funkcijo <code>sum(xs)</code>, ki sešteje elemente vgnezdenega seznama xs.
+Pomagajte si s funkcijo isinstance.</p>
+<pre>
+>>> isinstance([1, 2, 3], list)
+True
+>>> isinstance(1, list)
+False
+>>> sum([])
+0
+>>> sum([1, 2, 3, 4, 5])
+15
+>>> sum([1, [], [2, 3, [4]], 5])
+15
+</pre>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/while_and_if/conditions_sl.html b/python/problems/while_and_if/conditions_sl.html
new file mode 100644
index 0000000..6d6f838
--- /dev/null
+++ b/python/problems/while_and_if/conditions_sl.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html lang="sl">
+<head>
+ <meta charset="utf-8" />
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="/css/codeq.css" />
+ <link rel="stylesheet" type="text/css" href="../../style.css" />
+</head>
+<body>
+
+<h2>Pogoji</h2>
+
+<p>Zdaj pa povejmo nekaj splošnejšega o pogojih. Kakšni vse so lahko? Najprej,
+ pogoj je izraz. Torej nekaj, kar se da izračunati (po naši garažni
+ definiciji izraza). Doslej so bili vsi naši izrazi nekako številski,
+ aritmetični: v njih so nastopala števila in le-ta smo seštevali, množili,
+ odštevali in kar se še takega dela s števili. Pogoji pa so logični izrazi.
+ (V resnici se "logičnost" in "številskost" lahko poljubno prepletata, a to
+ bomo mimogrede odkrili sproti.)</p>
+
+<p>Rezultat logičnega izraza je logična vrednost. Logične vrednosti niso števila
+ (torej niso <code>int</code> ali <code>float</code>) in niso nizi, torej so
+ nekaj četrtega. Podatkovni tip, ki hrani logične vrednosti, se imenuje
+ <code>bool</code> (iz Boolean, po slovensko Booleov). Medtem ko je
+ različnih števil (<code>int</code>, <code>float</code>) kar veliko,
+ ima tip <code>bool</code> lahko le eno od dveh
+ vrednosti, <code>True</code> ali <code>False</code>. Tudi <code>True</code>
+ in <code>False</code> rezervirani besedi. </p>
+
+<p>S števili že znamo računati. Z nizi tudi malo. Kako pa računamo z logičnimi
+ vrednostmi? Menda jih ne moremo kar tako seštevati in odštevati?</p>
+
+<p>Za zdaj se delajmo, da ne. Kasneje bomo videli, da zna Python z logičnimi
+ izrazi početi še to in ono zanimivo reč, ki pa za začetnika niso tako
+ pomembne.</p>
+
+<p>Za logične izraze so nam na voljo trije operatorji: <code>or</code>,
+ <code>and</code> in <code>not</code>.
+
+<pre>
+>>> True and True
+True
+>>> True and False
+False
+>>> False or True
+True
+>>> not False
+True
+>>> False or not False
+True
+</pre>
+
+<p>(<code>and</code>, <code>or</code> in <code>not</code> so rezervirane besede.</p>
+
+<p>Operator <code>not</code> ima prednost pred <code>and</code>,
+ <code>and</code> pa pred <code>or</code>. Spet si lahko pomagamo z
+ oklepaji: <code>a or b and c</code> pomeni isto kot
+ <code>a or (b and c)</code> in bo resničen (<code>True</code>), če je resničen
+ <code>a</code> ali pa sta resnična <code>b</code> in <code>c</code>. Izraz
+ <code>(a or b) and c</code> pa bo resničen, če sta resnična <code>a</code>
+ ali <code>b</code> (ali oba), poleg tega pa nujno še <code>c</code>. Pri
+ tem seveda predpostavljamo, da <code>a</code>, <code>b</code> in
+ <code>c</code> vsebujejo logične vrednosti.</p>
+
+<p>Da bo reč lažje razumljiva, jo potrenirajmo na prav tem izrazu, vendar tako,
+ da namesto <code>a</code>, <code>b</code> in <code>c</code> oziroma namesto
+ "golih" <code>True</code> in <code>False</code> pišemo bolj "konkretne"
+ izraze.</p>
+
+<pre>
+>>> 352 > 0
+True
+>>> 5 < 3
+False
+>>> 352 > 0 or 5 < 3
+True
+>>> 352 > 0 or 5 > 3
+True
+>>> 352 > 0 and 5 > 3
+True
+>>> 352 > 0 and 5 < 3
+False
+>>> 352 > 0 and not 5 < 3
+True
+>>> 10 > 8 or 352 > 0 and 5 < 3
+True
+>>> 10 > 8 or (352 > 0 and 5 < 3)
+True
+>>> (10 > 8 or 352 > 0) and 5 < 3
+False
+>>> (10 > 8 or 352 > 0) and not 5 < 3
+True
+</pre>
+
+<p>Operatorja &gt; in &lt; pričakujeta na levi in desni neke reči, ki jih je
+ mogoče primerjati; zadovoljna nista le s števili, temveč tudi z, recimo,
+ nizi (primerjala jih bosta po abecedi), ne moreta pa primerjati števila z
+ nizom. Njun rezultat je logična vrednost. Za "večje ali enako" in "manjše
+ ali enako" uporabimo <code>&gt;=</code> in <code>&lt;=</code>.</p>
+
+<p>Če želimo preveriti enakost dveh števil (ali, v splošnem, enakost dveh
+ stvari), uporabimo dvojni enačaj, <code>==</code>. Enojni enačaj je dobil
+ svojo zadolžitev prejšnjo uro, namenjen je namreč prirejanju. Ali sta dve
+ stvari različni, preverimo z <code>!=</code>.</p>
+
+<pre>>>> 1 + 1 == 2
+True
+>>> 1 + 1 != 2
+False</pre>
+</p>
+
+<p>Ne zamenjujte dvojnih in enojnih enačajev. Če pomotoma napišemo (a to se nam
+ bo rekdo zgodilo),</p>
+<pre> a == 1 + 1</pre>
+<p>s tem nismo priredili <code>a</code>-ju dvojke, temveč smo le preverili, ali je
+ enak 2. Pogostejša napaka pa bo</p>
+<pre> if a = 1:
+ print("Vrednost a je ena")</pre>
+<p>Ta program pa je sintaktično nepravilen, saj Python za <code>if</code>
+pričakuje pogoj, mi pa smo napisali prireditveni stavek.</p>
+
+
+
+<p>Zdaj pa Pythonova posebnost, ki je v drugih jezikih ne bo: operatorje smemo nizati. Izraz
+ <code>10 &lt; T &lt; 20</code> je resničen, če je <code>T</code> med 10 in
+ 20. Izraz <code>10 &lt; T1 &lt; T2 &lt; 20</code> je resničen, če sta
+ <code>T1</code> in <code>T2</code> med 10 in 20, pri čemer je
+ <code>T1</code> manjši od <code>T2</code>. Izraz
+ <code>T1 &lt; 10 &lt; T2</code> je resničen, če je <code>T1</code> manjši
+ od 10, <code>T2</code> pa večji od deset.
+ <code>10 &lt; T1 == T2 &lt; 20</code> je resničen, če sta
+ <code>T1</code> in <code>T2</code> enaka in sta nekje med 10 in 20.</p>
+
+<p>Če se torej končno vrnemo k suhcem in debeluhom: če bi se hoteli
+ skoncentrirati le na te, ki so ravno pravšnji, bi lahko napisali,
+ recimo</p>
+
+<pre>if bmi > 18.5 and bmi < 25:
+ print("Čestitamo, ravno pravšnji ste.")</pre>
+
+<p>Če kdo napiše</p>
+
+<pre>if (bmi > 18.5) and (bmi < 25):
+ print("Čestitamo, ravno pravšnji ste.")</pre>
+
+<p>ali celo</p>
+
+<pre>if ((bmi > 18.5) and (bmi < 25)):
+ print("Čestitamo, ravno pravšnji ste.")</pre>
+
+<p>Ga bomo čudno gledali (((kdor hoče oklepaje, naj gre raje programirat v
+<a href="http://xkcd.com/297/">Lisp</a>))). Prav po Pythonovsko pa se reče:</p>
+
+<pre>if 18.5 < bmi < 25:
+ print("Čestitamo, ravno pravšnji ste.")</pre>
+
+
+</body>
+</html>
diff --git a/python/problems/while_and_if/ifclause_sl.html b/python/problems/while_and_if/ifclause_sl.html
new file mode 100644
index 0000000..c1f9134
--- /dev/null
+++ b/python/problems/while_and_if/ifclause_sl.html
@@ -0,0 +1,330 @@
+<!DOCTYPE html>
+<html lang="sl">
+<head>
+ <meta charset="utf-8" />
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="/css/codeq.css" />
+ <link rel="stylesheet" type="text/css" href="../../style.css" />
+</head>
+<body>
+
+<h2>Pogojni stavki</h2>
+
+<p> Sledijo zapiski predavanj prof. Demšarja. Najnovejšo verzijo zapiskov dobite na
+ <a href="https://ucilnica.fri.uni-lj.si/course/view.php?id=166">spletni
+ učilnici</a>.</p></p>
+
+<p>Začnimo s preprostim programom za izračun indeksa telesne teže.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)</pre>
+
+<p>Želimo si, da bi program povedal še, ali je uporabnik slučajno
+ preobilen. Prvi, seveda napačni poskus, bi bil takšen.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+print("Potrebno bo shujšati!")</pre>
+
+<p>Program v tej obliki bi, v širši rabi, povzročal anoreksijo, saj vse po
+vrsti pošilja na hujšanje. Zadnjo vrstico, izpis poziva k hujšanju, mora izvesti
+le, če je <code>bmi</code> večji od 25 (ta meja namreč velja za mejo debelosti,
+oziroma, politično korektno, prekomerne telesne teže).</p>
+
+<p>To storimo tako, da pred vrstico dodamo pogoj. Ta se glasi "če bmi &gt; 25",
+le v angleščini.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")</pre>
+
+<p>Ne spreglejmo dveh pomembnih reči. Prva: na konec pogoja smo postavili
+ dvopičje. To ne služi le za okras: dvopičja ne smemo izpustiti. Python na
+ tem mestu <em>zahteva</em> dvopičje.</p>
+
+<p>Druga: za <code>if</code>-om sem vrstico nekoliko zamaknil. Obilajno je zamik
+ štiri presledke. Ni obvezno, a če boste uporabljali štiri presledke, boste
+ pisali enako kodo kot drugi. In nikoli nikoli ne uporabljajte tabulatorjev,
+ ti naredijo zmedo!</p>
+
+<p>Zamaknjenih vrstic bi lahko bilo še več. Vse se izvedejo le, če
+je pogoj izpolnjen.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Tako kot smo zastavili zdaj, se <code>print</code>a, ki sta zamaknjena,
+izvedeta le, če je oseba preobilna. Zadnji <code>print</code> ni več znotraj
+pogoja, zato se izvede v vsakem primeru, za suhe in debele.</p>
+
+<p>Program bi bil še bolj simpatičen, če bi tiste, ki niso predebeli, pohvalil.
+</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Pogojnemu stavku lahko sledi še
+ <code>else</code>, ki vsebuje tisto, kar naj se zgodi, če pogoj ni
+ izpolnjen.</p>
+
+<p>Znotraj pogojnih stavkov seveda lahko pišemo tudi druge reči, ne le
+<code>print</code>ov. Takole: uporabniki programa se bodo pogosto zmotili in
+namesto višine v metrih vpisali višino v centimetrih, zato jih bo program
+obtožil težke anoreksije. To lahko popravimo preprosto tako, da program še pred
+računanjem BMI preveri, ali je višina slučajno večja od, recimo, treh metrov.
+V tem primeru sklepa, da je uporabnik podal višino v centimetrih, zato številko,
+ki jo je vpisal uporabnik, deli s 100.</p>
+
+<p>Začetek programa tako postane takšen.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+if visina > 3:
+ visina = visina / 100
+bmi = teza / visina ** 2</pre>
+
+<p>Še ena estetska zadeva: za dvopičjem vedno pojdite v novo vrsto. Kot boste
+ zvedavi kmalu odkrili, Python sicer dovoli, da napišete tudi
+<pre>if bmi > 25: print ("Potrebno bo shujšati")</pre>
+vendar to vodi v nepregledne programe. To se ne dela.</p>
+
+<p>Tule pa je še nekaj primerov napačno zamikanih programov.</p>
+
+<pre>if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Tretja vrstica mora imeti enak zamik kot druga, sicer Python ne more vedeti,
+ ali je še znotraj pogoja ali ne.</p>
+
+<pre>if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Ne, tudi v to smer ne smemo. Tu se Python vpraša, zakaj je tretja vrstica
+ zamaknjena še bolj kot druga - smo pozabili še kakšen pogoj ali kaj?</p>
+
+<pre>if bmi > 25:
+print("Potrebno bo shujšati!")
+print("Da, gospod ali gospa, preveč vas je skupaj.")
+</pre>
+
+<p>Blok za stavkom <code>if</code> mora biti zamaknjen.</p>
+
+<pre>if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+ else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p><code>if</code> in <code>else</code> morata biti poravnana. Kmalu bomo videli
+programe z več <code>if</code>i in <code>else</code>i; zamiki bodo potrebni,
+da bomo vedeli, kateri <code>else</code> sodi h kateremu <code>if</code>.</p>
+
+<p>Če poskušamo zagnati kateregakoli od naštetih programov, bo Python javil
+ sintaktično napako. Za razliko od običajnih napak, ki jih boste delali, in
+ ko bodo programi naredili vsaj nekaj malega in potem crknili, ta ne bo niti
+ trznil, temveč kar takoj javil napako. Spodnji program pa je sintaktično
+ pravilen. Python ga lahko izvede. Najbrž pa to ni to, kar smo hoteli, saj
+ se zadnji <code>print</code> izvede le, če pogoj ni izpolnjen.</p>
+
+<pre>if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+ print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+
+<h2>Gnezdeni pogoji</h2>
+
+<p>Do sem vse lepo in prav, vendar: kaj bomo z anoreksičnimi? Program bi jim
+mirno svetoval, naj še naprej jedo toliko kot doslej (torej: premalo).
+Ne: pri takšnih, ki imajo BMI manjši od
+18.5, moramo zastokati, naj vendar že začnejo jesti.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ if bmi < 18.5:
+ print("Trlica!")
+ print("Zunaj so avtomati s sendviči in čokolado. Med pavzo si le postrezite!")
+ else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Vidimo? Znotraj <code>if</code>a ali <code>else</code>a smemo
+ugnezditi nov pogoj. Zamikamo ga lepo naprej.</p>
+
+<p>Da bodo reči še nekoliko daljše (a poučnejše), dodajmo še en
+ <code>print</code>.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ print("Predebeli ravno niste.")
+ if bmi < 18.5:
+ print("Trlica!")
+ print("Zunaj so avtomati s sendviči in čokolado. Med pavzo si le postrezite!")
+ else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Zdaj program vsem, ki niso predebeli, napiše dobro novico, da niso predebeli.
+Šele nato se loti preverjanja, da niso slučajno presuhi.</p>
+
+<p>Tule mimogrede (prvič - a še velikokrat bomo) posvarimo pred ponavljanjem
+kode. Gornji program bi lahko napisali tudi tako:</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+else:
+ if bmi < 18.5:
+ print("Predebeli ravno niste.")
+ print("Trlica!")
+ print("Zunaj so avtomati s sendviči in čokolado. Med pavzo si le postrezite!")
+ else:
+ print("Predebeli ravno niste.")
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>Ali celo tako.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+ print("Da, gospod ali gospa, preveč vas je skupaj.")
+ print("Pregled je končan, oglasite se spet čez dva tedna.")
+else:
+ if bmi < 18.5:
+ print("Predebeli ravno niste.")
+ print("Trlica!")
+ print("Zunaj so avtomati s sendviči in čokolado. Med pavzo si le postrezite!")
+ print("Pregled je končan, oglasite se spet čez dva tedna.")
+ else:
+ print("Predebeli ravno niste.")
+ print("Odlično, le še naprej jejte toliko kot doslej!")
+ print("Pregled je končan, oglasite se spet čez dva tedna.")</pre>
+
+<p>To ni dobra ideja, ker je program daljši, manj pregleden, težje mu je
+ slediti, težje ga je spreminjati... Vedno se izogibajte ponavljanju. Več
+ o tem pa čez dva ali tri tedne.</p>
+
+<h2>Sicerče</h2>
+
+<p>Da se ne izgubimo, spet malo skrajšajmo program.</p>
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+else:
+ if bmi < 18.5:
+ print("Trlica!")
+ else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")</pre>
+
+<p>Pogojni stavki se nam lahko hitro zagnezdijo precej globoko in vrstice
+zbežijo nekam daleč proti desni. (Da ne govorimo o tem, da pogojni stavki
+niso niti približno edina reč, za katero bomo morali zamikati vrstice.) Ker
+so situacija, kakršna je zgornja, kar pogoste, imajo nekateri programski jeziki
+- in Python je med njimi - poleg <code>if</code> in <code>else</code> še
+<code>elseif</code> oziroma <code>elif</code>. (Še ena rezervirana beseda!)
+V Pythonu se uporablja slednja različica, <code>elif</code>. V gornjem programu
+ga uporabimo takole:
+
+<pre>teza = float(input("Teža: "))
+visina = float(input("Telesna višina: "))
+bmi = teza / visina ** 2
+print("Indeks vaše telesne teže je", bmi)
+if bmi > 25:
+ print("Potrebno bo shujšati!")
+elif bmi < 18.5:
+ print("Trlica!")
+else:
+ print("Odlično, le še naprej jejte toliko kot doslej!")</pre>
+
+<p>Program se zdaj prebere še lepše kot prej: če je BMI prevelik, pozovemo
+ k hujšanju, sicerče je premajhen, ozmerjamo dotično najstnico s trlico,
+ sicer pa izrečemo pohvalo.</p>
+
+<p>Po izkušnjah je <code>elif</code> za študente huda, nenavadna skušnjava:
+ nekateri ga pogosto uporabljajo namesto <code>else</code>a. Recimo, da bi
+ hoteli sprogramirati skrajšano pesimistično različico, po kateri so vsi,
+ ki niso debeluhi, trlice. Radi bi torej tole:</p>
+<pre>if bmi > 25:
+ print("Potrebno bo shujšati!")
+else:
+ print("Trlica!")
+</pre>
+
+<p>Mnogi bi (iz meni neznanega razloga) naredili takole:</p>
+
+<pre>if bmi > 25:
+ print("Potrebno bo shujšati!")
+elif bmi < 25:
+ print("Trlica!")
+</pre>
+
+<p>Python ni pozabil <code>if</code>a in bo tudi, če napišemo le
+ <code>else</code>, čisto dobro vedel, kakšen je pogoj zanj. Drugi pogoj
+ je nepotreben; če <code>bmi</code> ni večji od 25, je pač očitno manjši.</p>
+
+<p>Torej: ne zamenjujte <code>else</code> brez potrebe z <code>elif</code>.</p>
+
+<p>Mimogrede, program ne izpiše ničesar za tiste, ki imajo BMI natančno
+25. Drugi pogoj, če ga res hočemo imeti, bi se moral vprašati, ali je
+<code>bmi</code> manjši <em>ali enak</em> 25.</p>
+
+
+
+</body>
+</html>
diff --git a/python/problems/while_and_if/loops_sl.html b/python/problems/while_and_if/loops_sl.html
new file mode 100644
index 0000000..17d89c4
--- /dev/null
+++ b/python/problems/while_and_if/loops_sl.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html lang="sl">
+<head>
+ <meta charset="utf-8" />
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="/css/codeq.css" />
+ <link rel="stylesheet" type="text/css" href="../../style.css" />
+</head>
+<body>
+
+<h1>Zanka <code>while</code></h1>
+
+<h2>Naša prva zanka</h2>
+
+<p>Najprej malo refleksije. Kaj znamo narediti doslej: znamo napisati program,
+ ki kaj vpraša, kaj računa in kaj izpiše. Naši programi se izvajajo od
+ začetka do konca, s tem da lahko vmes preskočijo kak blok ukazov, ki se
+ nahajajo znotraj kakega <code>if</code>, <code>else</code> ali
+ <code>elif</code>. Večino časa pa smo preživeli ob tem, kako napisati
+ pogoj, se pravi, izraz, katerega vrednost je lahko resnično ali neresnično,
+ <code>True</code> ali <code>False</code>. Zdaj pa se bomo naučili napisati
+ programe, v katerih se del programa ponavlja.</p>
+
+<p>V večini programskih jezikov to naredimo z nečim, čemur mi rečemo zanka,
+ Avstralci (razen aboriginov) pa <em>loop</em>. Jeziki imajo navadno več
+ vrst zank, navadno tri. Python premore samo dve in danes bomo spoznali prvo
+ od njiju: zanko <em>while</em>.</p>
+
+<p>Tisočletna tradicija veleva, da mora biti začetnikov prvi program z zanko
+ program, ki šteje do deset. V Pythonu je videti takole
+<pre>x = 1
+while x <= 10:
+ print(x)
+ x = x + 1
+print('Pa sva preštela')</pre>
+
+<p>Zanka <code>while</code> je po svoje podobna stavku <code>if</code>. Medtem
+ ko se stavki znotraj <code><b>if</b></code> izvedejo, <b>če</b> je pogoj
+ resničen, se stavki znotraj <code><b>while</b></code> ponavljajo,
+ <b>dokler</b> je pogoj resničen. "If" je "če" in "while" je "dokler", to
+ vedo celo učiteljice angleščine. (Mimogrede, če že štejemo,
+ <code>while</code> je zadnja, enajsta rezervirana beseda danes. Smo že na
+ tretjini!) Gornji program lahko torej kar dobesedno prevedemo iz Pythona v
+ slovenščino:
+
+<pre>
+postavi x na 1
+dokler je x manjši ali enak 10:
+ izpiši vrednost x
+ povečaj x za 1
+izpiši 'Pa sva preštela'
+</pre>
+
+<p>K temu ni potrebna več nobena razlaga, ne?</p>
+
+<p>Trenutek je tako dober kot katerikoli drugi, morda pa še boljši: tale
+ <code>x = x + 1</code> smo "prevedli" v "povečaj x za 1". V resnici nismo
+ napisali tega, računalniku smo naročili, naj izračuna, koliko je
+ <code>x + 1</code> in to shrani nazaj v <code>x</code>. Ker pa to reč
+ tolikokrat potrebujemo in ker je lepo, da se stvar napiše tako, kot se
+ misli - misli pa se "povečaj x za 1" -, obstaja tudi praktičnejši zapis:
+ <code>x += 1</code>. Točneje, napisali smo "k x prištej 1". Rečemo lahko
+ tudi, <code>x += 6</code> ali <code>x += 1.13</code>; kaj to pomeni, je
+ menda jasno. Podobno moremo pisati tudi <code>x -= 1</code> (zmanjšaj
+ <code>x</code> za 1) ali, recimo <code>x *= 2</code>, podvoji
+ <code>x</code> in <code>x /= 10</code>, zdesetkaj <code>x</code>.
+ Pazite: <code>+=</code> (in vse druge kombinacije) se štejejo kot ena
+ beseda in med znaka <code>+</code> in <code>=</code> ne smemo napisati
+ presledka.</p>
+
+<p>Tisti, ki veste še kaj več: <code>x++</code> boste v Pythonu zaman iskali.
+ Nima ga, iz več razlogov, ki pa so malo pregloboki za nas tule.</p>
+
+<h2>Kaj je domneval Collatz</h2>
+
+<p>Vzemimo poljubno število in z njim počnimo tole: če je sodo, ga delimo z 2,
+če je liho, pa ga pomnožimo s 3 in prištejmo 1. To ponavljamo, dokler ne dobimo
+1.</p>
+
+<p>Za primer vzemimo 12. Ker je sodo, ga delimo z 2 in dobimo 6. 6 je sodo,
+torej ga delimo z 2 in dobimo 3. 3 je liho, torej ga množimo s 3 in prištejemo
+1 - rezultat je 10. 10 je sodo, zato ga delimo z 2 in dobimo 5... Celotno
+zaporedje je 12, 6, 3, 10, 5, 16, 8, 4, 2, 1. Ko pridemo do 1, se ustavimo.</p>
+
+<p>Matematiki, ki vedno radi počnejo koristne reči, si belijo glavo z
+vprašanjem, ali se reč vedno izteče ali pa se lahko kdaj tudi zacikla tako, da
+se zaporedje ponavlja in ponavlja v nedogled. Lothar Collatz, konkretno je že od
+leta 1937
+<a href="https://en.wikipedia.org/wiki/Collatz_conjecture">domneval</a>, da se
+zaporedje vedno izteče. Kot pravi njegov
+<a href="https://en.wikipedia.org/wiki/Lothar_Collatz">življenjepis</a>, se je
+njegovo domnevanje končalo leta 1990, matematiki pa domnevajo domnevo še naprej.
+Eden sicer najbolj neustrašnih matematikov 20. stoletja,
+<a href="https://en.wikipedia.org/wiki/Paul_Erd%C5%91s#Personality">couch
+ surfer Erdos</a>, je na to temo rekel, da matematika za takšna vprašanja še
+ ni zrela.</p>
+
+<p>Naši cilji bodo skromnejši: napisali bomo program, ki mu bo uporabnik vpisal
+število in program bo izpisal zaporedje, kot je bilo gornje.</p>
+
+<p>Najprej povejmo kar po slovensko:</p>
+
+<pre>stevilo = kar vpiše uporabnik
+dokler stevilo != 1:
+ če je število sodo:
+ deli število z 2
+ sicer:
+ pomnoži število s 3 in prištej 1</pre>
+
+<p>Tole skoraj že znamo prevesti v Python (prevod bo pravzaprav dobeseden),
+ odkriti moramo le, kako preveriti, ali je število sodo. Če kdo misli, da
+ tudi za to obstaja funkcija, se, izjemoma, moti. Pač pa znamo izračunati
+ ostanek po deljenju, konkretno, ostanek po deljenju z 2. Če je enak 0, je
+ število sodo.</p>
+
+<p>Prevedimo torej one slovenske besede v pythonovske.</p>
+
+<pre>n = int(input("Vnesi število: "))
+while n != 1:
+ print(n)
+ if n % 2 == 0:
+ n //= 2
+ else:
+ n = n * 3 + 1
+print(1)</pre>
+
+<p>Ne spreglejte, da smo uporabili celoštevilsko deljenje. Če bi uporabili
+navadnega, <code>n /= 2</code>, bi se <code>n</code> spremenil v necelo število
+(<code>float</code>) in v izpisu bi se pojavile zoprne decimalke (za vsakim
+številom bi pisalo še .0).</p>
+
+<p>Popaziti je potrebno, da izpišemo tako prvo kot zadnje število, zato bomo
+potrebovali še en <code>print</code> izven zanke: po zanki izpišemo še zadnji
+člen zaporedja, 1. Namesto <code>print(1)</code> bi lahko napisali tudi
+<code>print(n)</code> - tako ali tako vemo, da je <code>n</code> enak 1, saj
+program sicer ne bi prišel do tam, do koder je prišel, namreč onstran zanke, ki
+teče, dokler je <code>n</code> različen od 1.</p>
+
+<p>Dodajmo še nekaj: na koncu naj se izpiše, koliko členov ima zaporedje.</p>
+
+<pre>n = int(input("Vnesi število: "))
+clenov = 1
+while n != 1:
+ clenov += 1
+ print(n)
+ if n % 2 == 0:
+ n //= 2
+ else:
+ n = n * 3 + 1
+print(1)
+print("Zaporedje, ki se začne z", n, "ima", clenov, "členov")</pre>
+
+<p>Ups. V zanki smo pokvarili <code>n</code>, spremenil smo ga v 1. To bomo
+rešili tako, da shranimo začetno število v še eno spremenljivko.</p>
+
+<pre>zac = n = int(input("Vnesi število: "))
+clenov = 1
+while n != 1:
+ clenov += 1
+ print(n)
+ if n % 2 == 0:
+ n //= 2
+ else:
+ n = n * 3 + 1
+print(1)
+print("Zaporedje, ki se začne z", zac, "ima", clenov, "členov")</pre>
+
+<p>Število smo si zapomnili v prvi vrstici, shranili smo ga v
+<code>zac</code>. (V tem programu tudi prvič vidimo, da lahko prirejanja kar
+nizamo - pisati smemo <code>a = b = c = 42</code>.) Ustrezno popravimo še
+izpis v zadnji vrsti.</p>
+
+<script type="text/javascript">
+ SyntaxHighlighter.config.tagName = "xmp";
+ SyntaxHighlighter.defaults["gutter"] = false;
+ SyntaxHighlighter.all()
+</script>
+</body>
+</html>
diff --git a/python/problems/while_and_if/sl.py b/python/problems/while_and_if/sl.py
index fbb177a..7caffb4 100644
--- a/python/problems/while_and_if/sl.py
+++ b/python/problems/while_and_if/sl.py
@@ -1,2 +1,4 @@
name = 'Pogojni stavki in zanke'
-description = 'Logični izrazi, pogojni stavek if-else, zanka while.'
+description = '''<a target="_blank" href="[%@resource ifclause_sl.html%]">Pogojni stavek if-else</a>,
+<a target="_blank" href="[%@resource conditions_sl.html%]">logični izrazi</a>
+<a target="_blank" href="[%@resource loops_sl.html%]">zanka <code>while</code></a>'''