summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Možina <martin.mozina@fri.uni-lj.si>2016-08-24 15:32:22 +0200
committerMartin Možina <martin.mozina@fri.uni-lj.si>2016-08-24 15:32:22 +0200
commit12378810ee9207536bfa0c264c1bf2a2b0296171 (patch)
tree902e226e249a5369928e3fbc7e85739e14448b46
parentc2e782122d52acea0e69f8a5a92b40bbbb7072e5 (diff)
Added several new exercises for Python (related to dictionaries and sets).
-rw-r--r--python/problems/dictionaries/children/common.py75
-rw-r--r--python/problems/dictionaries/children/en.py13
-rw-r--r--python/problems/dictionaries/children/sl.py35
-rw-r--r--python/problems/dictionaries/common.py2
-rw-r--r--python/problems/dictionaries/en.py3
-rw-r--r--python/problems/dictionaries/family.pngbin0 -> 37655 bytes
-rw-r--r--python/problems/dictionaries/family/common.py80
-rw-r--r--python/problems/dictionaries/family/en.py14
-rw-r--r--python/problems/dictionaries/family/sl.py55
-rw-r--r--python/problems/dictionaries/following_words/common.py70
-rw-r--r--python/problems/dictionaries/following_words/en.py13
-rw-r--r--python/problems/dictionaries/following_words/sl.py36
-rw-r--r--python/problems/dictionaries/freq_following_word/common.py81
-rw-r--r--python/problems/dictionaries/freq_following_word/en.py13
-rw-r--r--python/problems/dictionaries/freq_following_word/sl.py30
-rw-r--r--python/problems/dictionaries/grandchildren/common.py84
-rw-r--r--python/problems/dictionaries/grandchildren/en.py13
-rw-r--r--python/problems/dictionaries/grandchildren/sl.py33
-rw-r--r--python/problems/dictionaries/max_characters/common.py72
-rw-r--r--python/problems/dictionaries/max_characters/en.py13
-rw-r--r--python/problems/dictionaries/max_characters/sl.py29
-rw-r--r--python/problems/dictionaries/most_frequent/common.py82
-rw-r--r--python/problems/dictionaries/most_frequent/en.py13
-rw-r--r--python/problems/dictionaries/most_frequent/sl.py30
-rw-r--r--python/problems/dictionaries/show_letters/common.py67
-rw-r--r--python/problems/dictionaries/show_letters/en.py13
-rw-r--r--python/problems/dictionaries/show_letters/sl.py33
-rw-r--r--python/problems/dictionaries/sl.py3
-rw-r--r--python/problems/dictionaries/successors/common.py82
-rw-r--r--python/problems/dictionaries/successors/en.py13
-rw-r--r--python/problems/dictionaries/successors/sl.py35
-rw-r--r--python/problems/dictionaries/text/common.py86
-rw-r--r--python/problems/dictionaries/text/en.py13
-rw-r--r--python/problems/dictionaries/text/sl.py45
-rw-r--r--python/problems/dictionaries/text/tmp.py29
-rw-r--r--python/problems/dictionaries/transactions/common.py71
-rw-r--r--python/problems/dictionaries/transactions/en.py13
-rw-r--r--python/problems/dictionaries/transactions/sl.py41
-rw-r--r--python/problems/dictionaries/waiter/common.py81
-rw-r--r--python/problems/dictionaries/waiter/en.py13
-rw-r--r--python/problems/dictionaries/waiter/sl.py50
41 files changed, 1577 insertions, 0 deletions
diff --git a/python/problems/dictionaries/children/common.py b/python/problems/dictionaries/children/common.py
new file mode 100644
index 0000000..437835e
--- /dev/null
+++ b/python/problems/dictionaries/children/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
+from server.hints import Hint
+
+id = 20607
+number = 8
+visible = True
+
+solution = '''\
+def children(tree, name):
+ if name in tree:
+ return tree[name]
+ return []
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+
+def test(python, code):
+ func_name = 'children'
+ tokens = get_tokens(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+ tree = {
+ 'alice': ['mary', 'tom', 'judy'],
+ 'bob': ['mary', 'tom', 'judy'],
+ 'ken': ['suzan'],
+ 'renee': ['rob', 'bob'],
+ 'rob': ['jim'],
+ 'sid': ['rob', 'bob'],
+ 'tom': ['ken']}
+
+ in_out = [
+ ((tree, 'alice'), ['mary', 'tom', 'judy']),
+ ((tree, 'mary'), []),
+ ((tree, 'renee'), ['rob', 'bob']),
+ ((tree, 'rob'), ['jim']),
+ ((tree, 'suzan'), []),
+ ]
+
+ test_in = [(func_name+'%s'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ corr = set(ans[0]) == set(to) and len(ans[0]) == len(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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/children/en.py b/python/problems/dictionaries/children/en.py
new file mode 100644
index 0000000..a3a40c1
--- /dev/null
+++ b/python/problems/dictionaries/children/en.py
@@ -0,0 +1,13 @@
+id = 20607
+name = 'Children (family tree 2)'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/children/sl.py b/python/problems/dictionaries/children/sl.py
new file mode 100644
index 0000000..2717a1b
--- /dev/null
+++ b/python/problems/dictionaries/children/sl.py
@@ -0,0 +1,35 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20607
+name = 'Otroci (družinsko drevo 2)'
+
+description = '''\
+<p>
+Napišite funkcijo <code>children(tree, name)</code>, ki v družinskem drevesu <code>tree</code>
+vrne seznam vseh otrok osebe. V primeru, da oseba nima otrok, vrnite prazen seznam.
+</p>
+
+<p>
+Družinsko drevo <code>tree</code> je slovar, kjer ključi predstavljajo imena
+staršev, vrednosti pa so njihovi otroci. Primer iz prejšnje naloge:
+<pre>
+>>> tree = {'renee': ['rob', 'bob'], 'ken': ['suzan'], 'rob': ['jim'],
+ 'sid': ['rob', 'bob'], ... , 'bob': ['mary', 'tom', 'judy']}
+>>> children(tree, 'alice')
+['mary', 'tom', 'judy']
+>>> children(tree, 'mary')
+[]
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/common.py b/python/problems/dictionaries/common.py
new file mode 100644
index 0000000..bc5cbc7
--- /dev/null
+++ b/python/problems/dictionaries/common.py
@@ -0,0 +1,2 @@
+id = 2006
+number = 6 \ No newline at end of file
diff --git a/python/problems/dictionaries/en.py b/python/problems/dictionaries/en.py
new file mode 100644
index 0000000..bf21767
--- /dev/null
+++ b/python/problems/dictionaries/en.py
@@ -0,0 +1,3 @@
+name = 'Dictionaries'
+description = 'Dictionaries and Sets'
+
diff --git a/python/problems/dictionaries/family.png b/python/problems/dictionaries/family.png
new file mode 100644
index 0000000..a5e1c03
--- /dev/null
+++ b/python/problems/dictionaries/family.png
Binary files differ
diff --git a/python/problems/dictionaries/family/common.py b/python/problems/dictionaries/family/common.py
new file mode 100644
index 0000000..8d175e1
--- /dev/null
+++ b/python/problems/dictionaries/family/common.py
@@ -0,0 +1,80 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20601
+number = 7
+visible = True
+
+solution = '''\
+def family_tree(family):
+ tree = {}
+ for parent, child in family:
+ if parent not in tree:
+ tree[parent] = []
+ tree[parent].append(child)
+ return tree
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'family_tree'
+ tokens = get_tokens(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+
+ tree = {
+ 'alice': ['mary', 'tom', 'judy'],
+ 'bob': ['mary', 'tom', 'judy'],
+ 'ken': ['suzan'],
+ 'renee': ['rob', 'bob'],
+ 'rob': ['jim'],
+ 'sid': ['rob', 'bob'],
+ 'tom': ['ken']}
+ in_out = [
+ ([('bob', 'mary')], {'bob':['mary']}),
+ ([('bob', 'mary'), ('bob', 'tom')], {'bob':['mary','tom']}),
+ ([], {}),
+ ([('bob','mary'),('mary','ken'),('alice','mary')],
+ {'bob':['mary'], 'mary':['ken'], 'alice':['mary']}),
+ ([('bob','mary'), ('bob', 'tom'), ('bob', 'judy'), ('alice', 'mary'),
+ ('alice', 'tom'), ('alice', 'judy'),('renee', 'rob'), ('renee', 'bob'),
+ ('sid', 'rob'), ('sid', 'bob'),('tom', 'ken'), ('ken', 'suzan'),
+ ('rob', 'jim')],tree)
+ ]
+
+ test_in = [(func_name+'(%s)'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ n_correct += dict(ans[0]) == to
+ if dict(ans[0]) != to:
+ 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/family/en.py b/python/problems/dictionaries/family/en.py
new file mode 100644
index 0000000..d04f58e
--- /dev/null
+++ b/python/problems/dictionaries/family/en.py
@@ -0,0 +1,14 @@
+id = 20601
+name = 'Family Tree'
+slug = 'Family Tree'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/family/sl.py b/python/problems/dictionaries/family/sl.py
new file mode 100644
index 0000000..2a572d3
--- /dev/null
+++ b/python/problems/dictionaries/family/sl.py
@@ -0,0 +1,55 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20601
+name = 'Družinsko drevo'
+
+description = '''\
+<p>
+V seznamu imamo spravljeno družinsko drevo. Primer:
+<pre>
+family = [('bob', 'mary'), ('bob', 'tom'),
+ ('bob', 'judy'), ('alice', 'mary'),
+ ('alice', 'tom'), ('alice', 'judy'),
+ ('renee', 'rob'), ('renee', 'bob'),
+ ('sid', 'rob'), ('sid', 'bob'),
+ ('tom', 'ken'), ('ken', 'suzan'),
+ ('rob', 'jim')]
+</pre>
+</p>
+<p>
+V vsaki terki sta zapisani dve imeni: ime starša in ime otroka. Terka
+<code>('bob', 'mary')</code> nam pove, da je Bob Maryjin oče, terka
+<code>('bob', 'tom')</code> pa, da je Bob Tomov oče, itd.
+Za lažje razumevanje si relacije predstavimo s sliko:
+<figure>
+ <a href="[%@resource family.png%]" target="_blank">
+ <img src="[%@resource family.png%]" />
+ </a>
+</figure>
+</p>
+<h3>Naloga</h3>
+<p>
+Napišite funkcijo <code>family_tree(family)</code>, ki sprejeme seznam
+v katerem je spravljeno družinsko drevo in vrne slovar v katerem je za vsakega
+starša spravljen seznam vseh njegovih otrok.</p>
+<pre>
+>>> family_tree(family)
+{'renee': ['rob', 'bob'],
+'ken': ['suzan'],
+'rob': ['jim'],
+'sid': ['rob', 'bob'],
+... ,
+'bob': ['mary', 'tom', 'judy']}
+</pre>
+</p>'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/following_words/common.py b/python/problems/dictionaries/following_words/common.py
new file mode 100644
index 0000000..501cfd2
--- /dev/null
+++ b/python/problems/dictionaries/following_words/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
+from server.hints import Hint
+
+id = 20610
+number = 11
+visible = True
+
+solution = '''\
+import collections
+
+def following_words(txt):
+ words = txt.split()
+ freq = collections.defaultdict(list)
+ for word, next_word in zip(words, words[1:]):
+ freq[word].append(next_word)
+ return freq
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'following_words'
+ 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 = [
+ ('in in in in', {'in': ['in', 'in', 'in']}),
+ ('in to in ono in to smo mi', {'smo': ['mi'], 'to': ['in', 'smo'],
+ 'ono': ['in'], 'in': ['to', 'ono', 'to']}),
+ ('danes je lep dan danes sije sonce',
+ {'lep': ['dan'], 'je': ['lep'], 'dan': ['danes'],
+ 'danes': ['je', 'sije'], 'sije': ['sonce']}),
+ ]
+
+ test_in = [(func_name+'("%s")'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ corr = dict(ans[0]) == 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/following_words/en.py b/python/problems/dictionaries/following_words/en.py
new file mode 100644
index 0000000..44de7c2
--- /dev/null
+++ b/python/problems/dictionaries/following_words/en.py
@@ -0,0 +1,13 @@
+id = 20610
+name = 'Following words'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/following_words/sl.py b/python/problems/dictionaries/following_words/sl.py
new file mode 100644
index 0000000..b9d6740
--- /dev/null
+++ b/python/problems/dictionaries/following_words/sl.py
@@ -0,0 +1,36 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20610
+name = 'Sledeče besede'
+
+description = '''\
+<p>
+Napišite funkcijo <code>following_words(txt)</code>, ki za vsako besedo <code>b</code>
+v nizu <code>txt</code> zgradi seznam besed, ki v tekstu nastopijo za
+besedo <code>b</code>. Nekaj primerov:
+<pre>
+>>> following_words('in in in in')
+{'in': ['in', 'in', 'in']}
+</pre>
+V besedilu se pojavi samo beseda <code>in</code>; beseda <code>in</code> se pojavi
+na treh mestih za <code>in</code>.
+<pre>
+>>> following_words('in to in ono in to smo mi')
+{'smo': ['mi'], 'to': ['in', 'smo'], 'ono': ['in'], 'in': ['to', 'ono', 'to']}
+</pre>
+Za besedo <code>smo</code> se pojavi samo beseda <code>mi</code>, medtem ko se
+recimo za besedo <code>to</code> pojavita tako beseda <code>smo</code> kot
+tudi beseda <code>in</code>.
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/freq_following_word/common.py b/python/problems/dictionaries/freq_following_word/common.py
new file mode 100644
index 0000000..e00b332
--- /dev/null
+++ b/python/problems/dictionaries/freq_following_word/common.py
@@ -0,0 +1,81 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20611
+number = 12
+visible = True
+
+solution = '''\
+import collections
+
+def following_words(txt):
+ words = txt.split()
+ freq = collections.defaultdict(list)
+ for word, next_word in zip(words, words[1:]):
+ freq[word].append(next_word)
+ return freq
+
+def freq_following_word(txt):
+ following = following_words(txt)
+ for f in following:
+ vals = collections.Counter(following[f])
+ s = sorted(vals.most_common(), key = lambda x: (-x[1], x[0]))
+ following[f] = s[0][0]
+ return following
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'freq_following_word'
+ 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 = [
+ ('in in in in', {'in': 'in'}),
+ ('in to in ono in to smo mi', {'smo': 'mi', 'to': 'in',
+ 'ono': 'in', 'in': 'to'}),
+ ('danes je lep dan danes sije sonce',
+ {'lep': 'dan', 'je': 'lep', 'dan': 'danes',
+ 'danes': 'je', 'sije': 'sonce'}),
+ ('danes je lep dan danes sije sonce danes sije dan ki je sonce',
+ {'lep': 'dan', 'je': 'lep', 'dan': 'danes',
+ 'danes': 'sije', 'sije': 'dan', 'ki': 'je', 'sonce':'danes'}),
+ ]
+
+ test_in = [(func_name+'("%s")'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ corr = dict(ans[0]) == 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/freq_following_word/en.py b/python/problems/dictionaries/freq_following_word/en.py
new file mode 100644
index 0000000..223eaa4
--- /dev/null
+++ b/python/problems/dictionaries/freq_following_word/en.py
@@ -0,0 +1,13 @@
+id = 20611
+name = 'Most frequent following word'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+} \ No newline at end of file
diff --git a/python/problems/dictionaries/freq_following_word/sl.py b/python/problems/dictionaries/freq_following_word/sl.py
new file mode 100644
index 0000000..eb12456
--- /dev/null
+++ b/python/problems/dictionaries/freq_following_word/sl.py
@@ -0,0 +1,30 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20611
+name = 'Najpogostejša sledeča beseda'
+
+description = '''\
+<p>
+Napišite funkcijo <code>freq_following_word(txt)</code>, ki za vsako besedo <code>b</code>
+v nizu <code>txt</code> zapiše v slovarju najpogostejšo besedo, ki
+sledi besedi <code>b</code>. Če je več takih besed, vzami prvo po abecedi.
+Nekaj primerov:
+<pre>
+>>> freq_following_word('in in in in')
+{'in': 'in'}
+>>> freq_following_word('in to in ono in to smo mi')
+{'smo': 'mi', 'to': 'in' , 'ono': 'in', 'in': 'to']}
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/grandchildren/common.py b/python/problems/dictionaries/grandchildren/common.py
new file mode 100644
index 0000000..0e71fba
--- /dev/null
+++ b/python/problems/dictionaries/grandchildren/common.py
@@ -0,0 +1,84 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20608
+number = 9
+visible = True
+
+solution = '''\
+def children(tree, name):
+ if name in tree:
+ return tree[name]
+ return []
+
+def grandchildren(tree, name):
+ names = []
+ for child in children(tree, name):
+ for grandchild in children(tree, child):
+ names.append(grandchild)
+ return names
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+
+def test(python, code):
+ func_name = 'grandchildren'
+ tokens = get_tokens(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+ tree = {
+ 'alice': ['mary', 'tom', 'judy'],
+ 'bob': ['mary', 'tom', 'judy'],
+ 'ken': ['suzan'],
+ 'renee': ['rob', 'bob'],
+ 'rob': ['jim'],
+ 'sid': ['rob', 'bob'],
+ 'tom': ['ken']}
+
+ in_out = [
+ ((tree, 'alice'), ['ken']),
+ ((tree, 'bob'), ['ken']),
+ ((tree, 'ken'), []),
+ ((tree, 'mary'), []),
+ ((tree, 'renee'), ['jim', 'mary', 'tom', 'judy']),
+ ((tree, 'sid'), ['jim', 'mary', 'tom', 'judy']),
+ ((tree, 'tom'), ['suzan']),
+]
+
+ test_in = [(func_name+'%s'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ corr = set(ans[0]) == set(to) and len(ans[0]) == len(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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/grandchildren/en.py b/python/problems/dictionaries/grandchildren/en.py
new file mode 100644
index 0000000..3f98328
--- /dev/null
+++ b/python/problems/dictionaries/grandchildren/en.py
@@ -0,0 +1,13 @@
+id = 20608
+name = 'Grandchildren (family tree 3)'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/grandchildren/sl.py b/python/problems/dictionaries/grandchildren/sl.py
new file mode 100644
index 0000000..b24c315
--- /dev/null
+++ b/python/problems/dictionaries/grandchildren/sl.py
@@ -0,0 +1,33 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20608
+name = 'Vnuki (družinsko drevo 3)'
+
+description = '''\
+<p>
+Napišite funkcijo <code>grandchildren(tree, name)</code>, ki v družinskem drevesu <code>tree</code>
+vrne seznam vseh vnukov in vnukinj osebe. V primeru, da oseba nima vnukov, vrnite prazen seznam.
+</p>
+
+<p>
+Družinsko drevo <code>tree</code> je slovar, kjer ključi predstavljajo imena
+staršev, vrednosti pa so njihovi otroci. Primer iz prejšnje naloge:
+<pre>
+>>> tree = {'renee': ['rob', 'bob'], 'ken': ['suzan'], 'rob': ['jim'],
+ 'sid': ['rob', 'bob'], ... , 'bob': ['mary', 'tom', 'judy']}
+>>> grandchildren(tree, 'renee')
+['jim', 'mary', 'tom', 'judy']
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/max_characters/common.py b/python/problems/dictionaries/max_characters/common.py
new file mode 100644
index 0000000..cb0c4b6
--- /dev/null
+++ b/python/problems/dictionaries/max_characters/common.py
@@ -0,0 +1,72 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20603
+number = 2
+visible = True
+
+solution = '''\
+def maxchars(words):
+ max_chars = 0
+ max_word = None
+ for w in words:
+ chars = len(set(w.lower()))
+ if chars > max_chars:
+ max_chars = chars
+ max_word = w
+ return max_word
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'maxchars'
+ 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 = [
+ ([], None),
+ (['RABarbara', 'izpit', 'zmagA'], 'izpit'),
+ (['RABarbara'], 'RABarbara'),
+ (['RABarbara', 'Izpit', 'izpit', 'zmagA'], 'Izpit'),
+ (['RABarbara', 'izpit', 'Izpit', 'zmagA'], 'izpit'),
+ (['Vesel', 'RABarbara', 'izpit', 'Izpit', 'zmagA'], 'Vesel'),
+ (['RABarbara', 'izpit', 'Izpit', 'zmagA', 'Vesel'], 'izpit'),
+ (['RABarbara', 'izpit', 'Izpit', 'zmagA', 'Veselica'], 'Veselica'),
+ ]
+
+ 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=code, inputs=test_in, timeout=1.0)
+ n_correct = 0
+ tin, tout = None, None
+ for i, (ans, to) in enumerate(zip(answers, test_out)):
+ n_correct += ans[0] == to
+ if ans[0] != to:
+ 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/max_characters/en.py b/python/problems/dictionaries/max_characters/en.py
new file mode 100644
index 0000000..e42996e
--- /dev/null
+++ b/python/problems/dictionaries/max_characters/en.py
@@ -0,0 +1,13 @@
+id = 20603
+name = 'Number of characters'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/max_characters/sl.py b/python/problems/dictionaries/max_characters/sl.py
new file mode 100644
index 0000000..835c84f
--- /dev/null
+++ b/python/problems/dictionaries/max_characters/sl.py
@@ -0,0 +1,29 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20603
+name = 'Število znakov'
+
+description = '''\
+<p>
+Napiši funkcijo <code>maxchars(words)</code>, ki kot argument prejme seznam nizov
+in kot rezultat vrne niz, ki ima največ različnih znakov. Male in velike črke
+upoštevaj kot iste znake - beseda <code>"MamA"</code> ima samo dva različna znaka.
+Če obstaja več besed z enakim številom različnih znakov, naj vrne prvo med njimi.
+Če je seznam prazen, naj funkcija vrne <code>None</code>.
+</p>
+<pre>
+>>> besede = ["RABarbara", "izpit", "zmagA"]
+>>> maxchars(besede)
+'izpit'
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/most_frequent/common.py b/python/problems/dictionaries/most_frequent/common.py
new file mode 100644
index 0000000..a945f1d
--- /dev/null
+++ b/python/problems/dictionaries/most_frequent/common.py
@@ -0,0 +1,82 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20604
+number = 3
+visible = True
+
+solution = '''\
+# Count number of elements in list xs.
+def freq(xs):
+ hist = {}
+ for x in xs:
+ if x not in hist:
+ hist[x] = 0
+ hist[x] += 1
+ return hist
+
+# Find element with maximal frequency
+def max_freq(f):
+ max_freq = 0
+ max_item = None
+ for item, item_freq in f.items():
+ if item_freq > max_freq:
+ max_freq = item_freq
+ max_item = item
+ return max_item
+
+def most_frequent(s):
+ return max_freq(freq(s.split())), max_freq(freq(s))
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'most_frequent'
+ 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 = [
+ ('a', ('a', 'a')),
+ ('aa bb aa', ('aa', 'a')),
+ ('in to in ono in to smo mi', ('in', ' ')),
+ ('abc abc abc abacbca', ('abc', 'a')),
+ ('abc abc abc abacbcb', ('abc', 'b')),
+ ('abc abc abc abacbcc', ('abc', 'c')),
+ ]
+
+ 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=code, inputs=test_in, timeout=1.0)
+ n_correct = 0
+ tin, tout = None, None
+ for i, (ans, to) in enumerate(zip(answers, test_out)):
+ n_correct += ans[0] == to
+ if ans[0] != to:
+ 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/most_frequent/en.py b/python/problems/dictionaries/most_frequent/en.py
new file mode 100644
index 0000000..1ef9394
--- /dev/null
+++ b/python/problems/dictionaries/most_frequent/en.py
@@ -0,0 +1,13 @@
+id = 20604
+name = 'Most frequent'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/most_frequent/sl.py b/python/problems/dictionaries/most_frequent/sl.py
new file mode 100644
index 0000000..c877e20
--- /dev/null
+++ b/python/problems/dictionaries/most_frequent/sl.py
@@ -0,0 +1,30 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20604
+name = 'Najpogostejše'
+
+description = '''\
+<p>
+Napišite funkcijo <code>most_frequent(s)</code>, ki vrne besedo in znak,
+ki se v podanem nizu največkrat pojavita. V nizu
+<code>'in to in ono in to smo mi'</code> se največkrat pojavita beseda
+<code>'in'</code> in znak <code>' '</code> (presledek).
+<pre>
+>>> most_frequent('aa bb aa')
+('aa', 'a')
+>>> most_frequent('in to in ono in to smo mi')
+('in', ' ')
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/show_letters/common.py b/python/problems/dictionaries/show_letters/common.py
new file mode 100644
index 0000000..f69565a
--- /dev/null
+++ b/python/problems/dictionaries/show_letters/common.py
@@ -0,0 +1,67 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20602
+number = 1
+visible = True
+
+solution = '''\
+def show_letters(word, letters):
+ bes = ""
+ for c in word:
+ bes += c if c in letters else "."
+ return bes
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'show_letters'
+ 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 = [
+ (('PONUDNIK', set(['O', 'N'])), '.ON..N..'),
+ (('PONUDNIK', set(['O', 'I', 'K'])), '.O....IK'),
+ (('PONUDNIK', set()), '........'),
+ (('PONUDNIK', set(['P', 'O', 'N', 'I', 'K', 'U'])), 'PONU.NIK'),
+ (('PONUDNIK', set(['P', 'O', 'N', 'I', 'K', 'U', 'D', 'Z'])), 'PONUDNIK'),
+ (('PONUDNIK', set(['A', 'B', 'J', 'L'])), '........'),
+ (('', set(['A', 'B', 'J', 'L'])), '')
+ ]
+
+ 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=code, inputs=test_in, timeout=1.0)
+ n_correct = 0
+ tin, tout = None, None
+ for i, (ans, to) in enumerate(zip(answers, test_out)):
+ n_correct += ans[0] == to
+ if ans[0] != to:
+ 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/show_letters/en.py b/python/problems/dictionaries/show_letters/en.py
new file mode 100644
index 0000000..bf9cc0e
--- /dev/null
+++ b/python/problems/dictionaries/show_letters/en.py
@@ -0,0 +1,13 @@
+id = 20602
+name = 'Show Letters'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/show_letters/sl.py b/python/problems/dictionaries/show_letters/sl.py
new file mode 100644
index 0000000..7bf8a34
--- /dev/null
+++ b/python/problems/dictionaries/show_letters/sl.py
@@ -0,0 +1,33 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20602
+name = 'Pokaži črke'
+
+description = '''\
+<p>
+Napiši funkcijo <code>show_letters(word, letter)</code>, ki kot argument sprejme
+besedo in množico (<code>set</code>) črk. Funkcija mora vrniti besedo, v
+kateri so vse črke, ki ne nastopajo v množici crke, spremenjene v pike. Lahko
+predpostaviš, da bodo vse besede sestavljene le iz velikih črk. </p>
+<pre>
+>>> show_letters("PONUDNIK", set(["O", "N"]))
+'.ON..N..'
+>>> show_letters("PONUDNIK", set(["O", "I", "K"]))
+'.O....IK'
+>>> show_letters("PONUDNIK", set())
+'........'
+>>> show_letters("PONUDNIK", set(["P", "O", "N", "I", "K", "U"]))
+'PONU.NIK'
+</pre>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/sl.py b/python/problems/dictionaries/sl.py
new file mode 100644
index 0000000..416c265
--- /dev/null
+++ b/python/problems/dictionaries/sl.py
@@ -0,0 +1,3 @@
+name = 'Slovarji'
+description = 'Uporaba slovarjev in množic.'
+
diff --git a/python/problems/dictionaries/successors/common.py b/python/problems/dictionaries/successors/common.py
new file mode 100644
index 0000000..5f824f5
--- /dev/null
+++ b/python/problems/dictionaries/successors/common.py
@@ -0,0 +1,82 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20609
+number = 10
+visible = True
+
+solution = '''\
+def children(tree, name):
+ if name in tree:
+ return tree[name]
+ return []
+
+def successors(tree, name):
+ names = []
+ for child in children(tree, name):
+ names.append(child)
+ names.extend(successors(tree, child))
+ return names
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'successors'
+ tokens = get_tokens(code)
+ if not has_token_sequence(tokens, ['def', func_name]):
+ return False, [{'id' : 'no_func_name', 'args' : {'func_name' : func_name}}]
+
+ tree = {
+ 'alice': ['mary', 'tom', 'judy'],
+ 'bob': ['mary', 'tom', 'judy'],
+ 'ken': ['suzan'],
+ 'renee': ['rob', 'bob'],
+ 'rob': ['jim'],
+ 'sid': ['rob', 'bob'],
+ 'tom': ['ken']}
+
+ in_out = [
+ ((tree, 'tom'), ['ken', 'suzan']),
+ ((tree, 'sid'), ['rob', 'bob', 'jim', 'mary',
+ 'tom', 'judy', 'ken', 'suzan']),
+ ((tree, 'suzan'), []),
+ ((tree, 'ken'), ['suzan']),
+ ((tree, 'rob'), ['jim']),
+]
+
+ test_in = [(func_name+'%s'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ corr = set(ans[0]) == set(to) and len(ans[0]) == len(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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/successors/en.py b/python/problems/dictionaries/successors/en.py
new file mode 100644
index 0000000..fb7c662
--- /dev/null
+++ b/python/problems/dictionaries/successors/en.py
@@ -0,0 +1,13 @@
+id = 20609
+name = 'Successors (family tree 4)'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/successors/sl.py b/python/problems/dictionaries/successors/sl.py
new file mode 100644
index 0000000..e92e2d7
--- /dev/null
+++ b/python/problems/dictionaries/successors/sl.py
@@ -0,0 +1,35 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20609
+name = 'Nasledniki (družinsko drevo 4)'
+
+description = '''\
+<p>
+Napišite funkcijo <code>successors(tree, name)</code>,
+ki vrne seznam vseh naslednikov osebe.
+</p>
+
+<p>
+Družinsko drevo <code>tree</code> je slovar, kjer ključi predstavljajo imena
+staršev, vrednosti pa so njihovi otroci. Primer:
+<pre>
+>>> tree = {'renee': ['rob', 'bob'], 'ken': ['suzan'], 'rob': ['jim'],
+ 'sid': ['rob', 'bob'], ... , 'bob': ['mary', 'tom', 'judy']}
+>>> successors(tree, 'tom')
+['ken', 'suzan']
+>>> successors(tree, 'sid')
+['rob', 'bob', 'jim', 'mary', 'tom', 'judy', 'ken', 'suzan']
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/text/common.py b/python/problems/dictionaries/text/common.py
new file mode 100644
index 0000000..134f69b
--- /dev/null
+++ b/python/problems/dictionaries/text/common.py
@@ -0,0 +1,86 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20612
+number = 13
+visible = True
+
+solution = '''\
+import collections
+
+def following_words(txt):
+ words = txt.split()
+ freq = collections.defaultdict(list)
+ for word, next_word in zip(words, words[1:]):
+ freq[word].append(next_word)
+ return freq
+
+def freq_following_word(txt):
+ following = following_words(txt)
+ for f in following:
+ vals = collections.Counter(following[f])
+ s = sorted(vals.most_common(), key = lambda x: (-x[1], x[0]))
+ following[f] = s[0][0]
+ return following
+
+def text(word, full_text, num):
+ freq = freq_following_word(full_text)
+ words = []
+ for i in range(num):
+ words.append(word)
+ word = freq[word]
+ return ' '.join(words)
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'text'
+ 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 = [
+ (('in', 'in in in in', 5), 'in in in in in'),
+ (('in', 'in to in ono in to smo mi', 5), 'in to in to in'),
+ (('danes', 'danes je lep dan danes sije sonce', 5),
+ 'danes je lep dan danes'),
+ (('danes', 'danes je lep dan danes sije sonce danes sije dan ki je sonce', 5),
+ 'danes sije dan danes sije'),
+ ]
+
+ test_in = [(func_name+'%s'%str(l[0]), None) for l in in_out]
+ test_out = [l[1] for l in in_out]
+
+ answers = python(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)):
+ corr = ans[0] == 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/text/en.py b/python/problems/dictionaries/text/en.py
new file mode 100644
index 0000000..4e5f5b3
--- /dev/null
+++ b/python/problems/dictionaries/text/en.py
@@ -0,0 +1,13 @@
+id = 20612
+name = 'Generated text'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+} \ No newline at end of file
diff --git a/python/problems/dictionaries/text/sl.py b/python/problems/dictionaries/text/sl.py
new file mode 100644
index 0000000..3afeec4
--- /dev/null
+++ b/python/problems/dictionaries/text/sl.py
@@ -0,0 +1,45 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20612
+name = 'Generirano besedilo'
+
+description = '''\
+<p>
+Napisati želimo program, ki bo generiral tipičen stavek. Seveda ni dobro,
+da si samo naključno izbiramo besede in jih lepimo skupaj, saj bi tako dobili
+nekaj povsem neberljivega. Naloge se bomo lotili malo pametneje.
+Recimo, da ima program na voljo nek tekst, npr. <code>'in to in ono smo mi'</code>,
+iz katerega se lahko uči. Naš tekst bomo začeli z izbrano besedo.
+Nadaljujemo tako, da se vprašamo katera beseda se v učnem tekstu pojavi
+najpogosteje za izbrano besedo. Če začnemo z besedo <code>to</code>, potem
+bo naslednja beseda <code>in</code>. Postopek nato ponovimo z besedo <code>in</code>.
+</p>
+
+<p>
+Napišite funkcijo <code>text(word, full_text, num)</code>, ki sprejme začetno
+besedo <code>word</code>, celotno besedilo <code>full_text</code>,
+ter generira besedilo dolgo <code>num</code> besed.
+</p>
+
+<p> Da bodo generirani stavki bolj zanimivi, lahko program testiraš na
+kakšnem romanu, npr. Orwellovi noveli 1984. Vendar pa tega ne boš mogel
+izvajati v CodeQ, saj nima dostopa do mreže. Poženi iz kakšnega drugega programa,
+npr. iz pyCharma ali kar iz ukazne vrstice.
+<pre>
+>>> import urllib.request
+>>> txt = urllib.request.urlopen('http://squeeb1134.tripod.com/1984.txt').read().decode('utf8')
+>>> text('Big', txt, 15)
+'Big Brother is not be a few minutes at the Party member of the Party'
+</pre>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/text/tmp.py b/python/problems/dictionaries/text/tmp.py
new file mode 100644
index 0000000..bf56c4f
--- /dev/null
+++ b/python/problems/dictionaries/text/tmp.py
@@ -0,0 +1,29 @@
+import collections
+
+def following_words(txt):
+ words = txt.split()
+ freq = collections.defaultdict(list)
+ for word, next_word in zip(words, words[1:]):
+ freq[word].append(next_word)
+ return freq
+
+def freq_following_word(txt):
+ following = following_words(txt)
+ for f in following:
+ vals = collections.Counter(following[f])
+ s = sorted(vals.most_common(), key = lambda x: (-x[1], x[0]))
+ following[f] = s[0][0]
+ return following
+
+def text(word, freq, num):
+ words = []
+ for i in range(num):
+ words.append(word)
+ word = freq[word]
+ return ' '.join(words)
+
+
+import urllib.request
+txt = 'danes je lep dan danes sije sonce danes sije dan ki je sonce'
+#urllib.request.urlopen('http://squeeb1134.tripod.com/1984.txt').read().decode('utf8')
+print (text('danes', freq_following_word(txt), 5))
diff --git a/python/problems/dictionaries/transactions/common.py b/python/problems/dictionaries/transactions/common.py
new file mode 100644
index 0000000..66d6387
--- /dev/null
+++ b/python/problems/dictionaries/transactions/common.py
@@ -0,0 +1,71 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20605
+number = 4
+visible = True
+
+solution = '''\
+def transactions(start, trans):
+ state = dict(start)
+ for fr, to, amount in trans:
+ state[fr] -= amount
+ state[to] += amount
+ most = None # could use -1, however all can be in debt
+ for who, amount in state.items():
+ if most is None or amount > most:
+ most, richest = amount, who
+ return richest
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def test(python, code):
+ func_name = 'transactions'
+ 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 = [
+ (([("Ana", 0), ("Berta", 1)], [("Berta", "Ana", 1)]), "Ana"),
+ (([("Ana", 0), ("Berta", 1)], []), "Berta"),
+ (([("Ana", 3), ("Berta", 2)], [("Berta", "Berta", 3)]), "Ana"),
+ (([("Ana", 4), ("Berta", 8), ("Cilka", 10)],
+ [("Cilka", "Ana", 3), ("Cilka", "Ana", 2), ("Ana", "Berta", 2)]),
+ "Berta"),
+ ]
+
+ 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=code, inputs=test_in, timeout=1.0)
+ n_correct = 0
+ tin, tout = None, None
+ for i, (ans, to) in enumerate(zip(answers, test_out)):
+ n_correct += ans[0] == to
+ if ans[0] != to:
+ 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/transactions/en.py b/python/problems/dictionaries/transactions/en.py
new file mode 100644
index 0000000..f60bc08
--- /dev/null
+++ b/python/problems/dictionaries/transactions/en.py
@@ -0,0 +1,13 @@
+id = 20605
+name = 'Transactions'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/transactions/sl.py b/python/problems/dictionaries/transactions/sl.py
new file mode 100644
index 0000000..b80a688
--- /dev/null
+++ b/python/problems/dictionaries/transactions/sl.py
@@ -0,0 +1,41 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20605
+name = 'Transakcije'
+
+description = '''\
+<p>
+V začetku je imela Ana štiri zlatnike, Berta 8 in CIlka 10, torej
+<code>[('Ana', 4), ('Berta', 8), ('Cilka', 10)]</code>. Nato je dala Cilka
+Ani 3 zlatnike; potem je dala Cilka Ani še 2; na koncu je dala Ana Berti 2,
+kar zapišemo <code>[('Cilka', 'Ana', 3), ('Cilka', 'Ana', 2), ('Ana', 'Berta', 2)]</code>.
+Kdo ima na koncu največ?
+</p>
+
+<p>
+Napišite funkcijo <code>transactions(start, tr)</code>, ki dobi gornja seznama in
+vrne ime najbogatejše osebe po koncu transakcij. Če je na koncu več enako
+bogatih najbogatejših oseb, naj vrne poljubno izmed njih. Namig: delo
+si boste poenostavili, če bo funkcija takoj pretvorila sezmam v
+primernejšo podatkovno strukturo.
+</p>
+<p>
+Primer
+<pre>
+>>> transakcije([('Ana', 4), ('Berta', 8), ('Cilka', 10)], [('Cilka', 'Ana', 3),
+('Cilka', 'Ana', 2), ('Ana', 'Berta', 2)])
+Berta
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}
diff --git a/python/problems/dictionaries/waiter/common.py b/python/problems/dictionaries/waiter/common.py
new file mode 100644
index 0000000..bcda759
--- /dev/null
+++ b/python/problems/dictionaries/waiter/common.py
@@ -0,0 +1,81 @@
+import re
+from python.util import has_token_sequence, string_almost_equal, \
+ string_contains_number, get_tokens, get_numbers, get_exception_desc
+from server.hints import Hint
+
+id = 20606
+number = 5
+visible = True
+
+solution = '''\
+import collections
+def orders(s):
+ cust = collections.defaultdict(list)
+ for pers, snack in s:
+ if snack[0] == "-":
+ if snack[1:] in cust[pers]:
+ cust[pers].remove(snack[1:])
+ else:
+ cust[pers].append(snack)
+ return dict(cust)
+'''
+
+hint_type = {
+ 'final_hint': Hint('final_hint')
+}
+
+def comp(solution, test):
+ if not any(test.values()) and dict(solution) == {}:
+ return True
+ return dict(solution) == test
+
+def test(python, code):
+ func_name = 'orders'
+ 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 = [
+ ([("Tone", "pivo")], {"Tone": ["pivo"]}),
+ ([("Tone", "pizza"), ("Tone", "sok")], {"Tone": ["pizza", "sok"]}),
+ ([('Ana', 'torta'), ('Berta', 'krof'), ('Cilka', 'kava'),
+ ('Ana', 'kava'), ('Berta', '-krof'), ('Cilka', '-torta'),
+ ('Berta', 'torta')],
+ {'Cilka': ['kava'], 'Berta': ['torta'], 'Ana': ['torta', 'kava']}),
+ ]
+ in_out_empty = [
+ ([('Ana', 'torta'), ('Ana', '-torta')], {'Ana': []}),
+ ([('Ana', '-torta')], {'Ana': []})
+ ]
+
+ test_in = [('{0}({1})'.format(func_name, str(l[0])), None)
+ for l in in_out+in_out_empty]
+ test_out = [l[1] for l in in_out+in_out_empty]
+
+ answers = python(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)):
+ n_correct += comp(ans[0], to)
+ if not comp(ans[0], to):
+ 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):
+ tokens = get_tokens(code)
+
+ # run one test first to see if there are any exceptions
+ answer = python(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/dictionaries/waiter/en.py b/python/problems/dictionaries/waiter/en.py
new file mode 100644
index 0000000..7f8528b
--- /dev/null
+++ b/python/problems/dictionaries/waiter/en.py
@@ -0,0 +1,13 @@
+id = 20606
+name = 'Waiter'
+
+description = '''\
+<p>(translation missing)</p>'''
+
+hint = {
+ 'plan': '''\
+<p>(translation missing)</p>''',
+
+ 'no_input_call': '''\
+<p>(translation missing)</p>''',
+}
diff --git a/python/problems/dictionaries/waiter/sl.py b/python/problems/dictionaries/waiter/sl.py
new file mode 100644
index 0000000..d2bd50b
--- /dev/null
+++ b/python/problems/dictionaries/waiter/sl.py
@@ -0,0 +1,50 @@
+import server
+mod = server.problems.load_language('python', 'sl')
+
+
+id = 20606
+name = 'Natakar'
+
+description = '''\
+<p>
+Ko je prišel natakar, so naročile:
+<ul>
+<li>Ana je naročila torto,</li>
+<li>Berta je naročila krof,</li>
+<li>Cilka je naročila kavo,</li>
+<li>Ana je naročila še kavo,</li>
+<li>Berta je rekla, da ne bo krofa,</li>
+<li>Cilka je rekla, da ne bo torte (no, saj je niti ni naročila;
+to natakar mirno ignorira),</li>
+<li>Berta je naročila torto.</li></ul>
+<p>
+Vse skupaj zapišemo takole: <code>[("Ana", "torta"), ("Berta", "krof"),
+("Cilka", "kava"), ("Ana", "kava"), ("Berta", "-krof"), ("Cilka", "-torta"),
+("Berta", "torta")]</code>. Seznam torej vsebuje pare nizov (oseba, jed),
+pri čemer se jed včasih začne z "-", kar pomeni, da stranka prekliče naročilo te
+jedi oz. pijače.</p>
+
+<p>Napiši funkcijo <code>orders(s)</code>, ki prejme takšen seznam in vrne
+slovar, katerega ključi so imena strank, vrednost pri vsakem ključu pa je
+seznam vsega, kar mora stranka na koncu dobiti.</p>
+<p>Primer
+<pre>
+>>> orders([('Ana', 'torta'), ('Berta', 'krof'), ('Cilka', 'kava'), ('Ana', 'kava'),
+('Berta', '-krof'), ('Cilka', '-torta'), ('Berta', 'torta')])
+{'Cilka': ['kava'], 'Berta': ['torta'], 'Ana': ['torta', 'kava']}
+>>> orders([('Ana', 'torta'), ('Ana', '-torta')])
+{'Ana': []}
+>>> orders([('Ana', '-torta')])
+{'Ana': []} # Tu sme funkcija vrniti tudi prazen slovar, {}
+</pre>
+</p>
+'''
+
+plan = []
+
+hint = {
+ 'final_hint': ['''\
+<p>Program je pravilen! <br>
+</p>
+'''],
+}