diff options
author | Martin <martin@leo.fri1.uni-lj.si> | 2015-09-14 10:24:22 +0200 |
---|---|---|
committer | Martin <martin@leo.fri1.uni-lj.si> | 2015-09-14 10:24:22 +0200 |
commit | c80a5ba87d3dd8cc4a67a2d23c087448a702d7fe (patch) | |
tree | 425156fdd66a960237ce1fe3508bef11c1ff9485 /python | |
parent | 40275283e213082992b69cfe48f84d3cd4d6f13a (diff) |
Completed description of Fahrenheit.
Added new exercises Pythagorean theorem.
Diffstat (limited to 'python')
5 files changed, 417 insertions, 10 deletions
diff --git a/python/problems/introduction/fahrenheit_to_celsius/common.py b/python/problems/introduction/fahrenheit_to_celsius/common.py index 34f2832..076d322 100644 --- a/python/problems/introduction/fahrenheit_to_celsius/common.py +++ b/python/problems/introduction/fahrenheit_to_celsius/common.py @@ -22,18 +22,26 @@ hint_type = { def test(python, code): # List of inputs: (expression to eval, stdin). test_in = [ - (None, '0\n'), - (None, '100\n'), + (None, '32\n'), + (None, '212\n'), + (None, '-459.4\n'), + (None, '98.6\n'), + (None, '1832\n'), ] test_out = [ - '-17.7', - '37.7', + '0', + '100', + '-273', + '37', + '1000' ] # List of outputs: (expression result, stdout, stderr, exception). answers = python(code=code, inputs=test_in, timeout=1.0) outputs = [ans[1] for ans in answers] + print (answers) + n_correct = 0 for output, correct in zip(outputs, test_out): if correct in output: @@ -41,8 +49,46 @@ def test(python, code): return n_correct, len(test_in) def hint(python, code): - if not code: + # run one test first to see if there are any exceptions + test_in = [(None, '212\n')] + exc = python(code=code, inputs=test_in, timeout=1.0)[0][3] + # have an exception! + if exc: + if 'NameError' in exc: + return [{'id':'name_error'}] + if 'not callable' in exc: + return [{'id':'not_callable'}] + if 'unsupported operand' in exc: + return [{'id':'unsupported_operand'}] + if 'SyntaxError' in exc: + return [{'id':'syntax_error'}] + if 'IndentationError' in exc: + return [{'id':'indentation_error'}] + + + # the trick is to decide when to show the plan and when the first hint. + # I implemented a simple idea: show plan, when code contains something from the + # solution, but not input. + if not code or (not has_token_sequence(code, ['input']) and + (has_token_sequence(code, ['32']) or + has_token_sequence(code, ['=', '5']) or + has_token_sequence(code, ['print']))): return [{'id': 'plan'}] + + + # if input is not present in code, student needs to learn about input if not has_token_sequence(code, ['input']): return [{'id': 'no_input_call'}] + + # if tokens * or / or = are not in code, we have to teach them how to + # evaluate expressions. + if (not has_token_sequence(code, ['/']) or + not has_token_sequence(code, ['*']) or + not has_token_sequence(code, ['='])): + return [{'id' : 'expressions_python'}] + + # student is not using print function + if not has_token_sequence(code, ['print']): + return [{'id' : 'printing'}] + return None diff --git a/python/problems/introduction/fahrenheit_to_celsius/sl.py b/python/problems/introduction/fahrenheit_to_celsius/sl.py index e1f5ce3..d5cef06 100644 --- a/python/problems/introduction/fahrenheit_to_celsius/sl.py +++ b/python/problems/introduction/fahrenheit_to_celsius/sl.py @@ -9,16 +9,50 @@ description = '''\ stopinjah, program pa jo izpiše v Celzijevih. Med temperaturama pretvarjamo po formuli C = 5/9 (F – 32).</p>''' +general_exception = { + 'error_head' : '<p>Napaka:</p>', + + 'general': ''' + <p>Pri razumevanju napake sta pomembni dve vrstici. V drugi vrstici je specificirana lokacija + napake (line XY), v zadnji vrstici pa izvemo za kakšno napako gre.</p> + ''', + + 'name_error' : ''' + <p>Napaka tipa NameError označuje, da uporabljate nedefinirano vrednost:</p> + <ul> + <li>Če je v napaki omenjena spremenljivka, potem vrednost te spremenljivke ni določena, + a vi jo poskušate uporabiti.</li> + <li>Če napaka omenja ime funkcije, potem ste verjetno pozabili uvoziti ustrezni modul. + Npr. če gre za matematično funkcijo, je potrebno uvoziti modul <code>math</code>: + <pre> + from math import * + </pre> + ''', + + 'type_error': ''' + <p>TypeError napaka pomeni, da želite izvesti operacijo na nedovoljenih tipih. Npr., če želite sešteti niz in +število ali klicati funkcijo, čeprav tisto ni funkcija, itd. .</p> + ''', + + 'syntax_error': ''' + <p>Napaka v sintaksi programa. Napisali ste nekaj, kar Python ne zna prebrati.</p> ''', + + 'indentation_error': ''' + <p> Pomeni, da imate napačno število presledkov na začetku vrstice. Poskrbite, da so vse vrstice pravilno +poravnane. </p>''' + +} + hint = { - 'plan': '''\ -<p>Za začetek lahko razdelimo program na 3 dele:</p> + 'plan': ['''\ +<p>Program izvedemo v treh korakih:</p> <ol> <li>Vprašanje za temperaturo v Fahrenheitih (F = ?).</li> <li>Izračun temperature v Celzijih: C = 5/9 (F – 32)</li> <li>Izpis temperature v Celzijih (izpiši C).</li> -</ol>''', +</ol>'''], - 'no_input_call': '''\ + 'no_input_call': ['''\ <p>Uporabnika lahko nekaj vprašamo s funkcijo <code>input</code>. Funkcija <code>input</code> sprejme kot argument niz (<em>angl.</em> string), ki se prikaže uporabniku kot vprašanje in vrne niz, ki ga je uporabnik napisal. Nize @@ -28,5 +62,75 @@ vrstica:</p> ime = input("Kako ti je ime?") </pre> <p>pokliče funkcijo <code>input</code>, ki povpraša uporabnika po imenu in si -shrani uporabnikov odgovor v spremenljivko <code>ime</code>.</p>''', +shrani uporabnikov odgovor v spremenljivko <code>ime</code>.</p>'''], + + + 'expressions_python': [''' +<p>Računanje: če v Pythonu napišemo izraz, se bo ta izračunal. Npr., če napišemo</p> +<pre> +3 + 6 +<pre> +bo Python seštel vrednosti 3 in 6 in ... rezultat pozabil. Kadar pa želimo +rezultat shraniti, za to uporabimo <em>prireditveni stavek</em>, kjer na levo +napišemo ime spremenljivke, na desno pa izraz:</p> +<pre> +c = 2 * a * (3 + b) +</pre> +<p> Kot vidite, izraz lahko uporablja tudi spremenljivke. </p>'''], + + 'printing': [''' +<p> V Pythonu izpisujemo s funkcijo <code>print. Če želimo izpisati več elementov, +jih ločimo z vejico. Recimo, da imamo spremenljivko <code>ime</code>, +ki vsebuje naše ime, potem lahko napišemo: +<pre> +print("Ime mi je", ime, ".") +</pre>'''], + + 'name_error' : [general_exception['error_head'], general_exception['general'], + general_exception['name_error'], ''' + <p>Verjetno uporabljate spremenljivko, ki nima vrednosti. Ali v izrazu za izračun + uporabljate napačno spremenljivko? Ali pri izpisu morda poskušate + izpisati napačno spremenljivko?</p>'''], + + 'unsupported_operand' : [general_exception['error_head'], general_exception['general'], + general_exception['type_error'], ''' +<p>Verjetni razlog: funkcija <code>input</code> vrača vrednost tipa niz, +ki jo moramo najprej pretvoriti v tip <code>float</code>, če želimo z njo računati:</p> +<pre> +v = float(input(" ... +</pre> +<p>Zakaj je tako, boste razumeli kasneje, zaenkrat je dovolj, da to poznate.</p> +<p>Na primeru pretvarjanja temperatur:</p> +<pre> +fniz = input("Temperatura [F]: ") +f = float(fniz) +</pre> +<p>ali krajše, združeno v eno vrstico:</p> +<pre> +f = float(input("Temperatura [F]: ")) +</pre> +<p>Funkcijo <code>float</code> lahko kličemo le, če je v nizu zapisano število, +npr. "10". Če imamo v nizu tudi kakšno črko, bo Python javil napako.</p> '''], + + + 'not_callable' : [general_exception['error_head'], general_exception['general'], + general_exception['type_error'], ''' +<p>V programu poskušate uporabiti število kot funkcijo, a to ne gre. +Verjetni razlog: Ali ste v izrazu pozabili na znak *. Pri pretvorbi temperatur bi namesto:</p> +<pre> +C = 5/9(F – 32) +</pre> +<p>morali napisati: </p> +<pre> +C = 5/9 * (F – 32). +</pre> +<p> Python ne zna izpuščati znaka za množenje, kot to delamo pri matematiki.</p> '''], + + 'syntax_error' : [general_exception['error_head'], general_exception['general'], + general_exception['type_error'], ''' +<p> Ste mogoče pozabili na kakšen zaklepaj? </p>'''], + + 'indentation_error' : [general_exception['error_head'], general_exception['general'], + general_exception['indentation_error']], + } diff --git a/python/problems/introduction/pythagorean_theorem/common.py b/python/problems/introduction/pythagorean_theorem/common.py new file mode 100644 index 0000000..b2ae10c --- /dev/null +++ b/python/problems/introduction/pythagorean_theorem/common.py @@ -0,0 +1,105 @@ +# coding=utf-8 + +from python.util import has_token_sequence +from server.hints import Hint, HintSequence + +id = 1000 +group = 'introduction' +number = 2 +visible = True + +solution = '''\ +from math import * +g = 10 +kot = float(input("Vnesi kot (v stopinjah): ")) +v = float(input("Vnesi hitrost (v m/s): ")) +kot_rad = kot * 2 * pi / 360 +razdalja = v ** 2 * sin(2 * kot_rad) / g +print("Kroglo bo odneslo", razdalja, "metrov.") +''' + +#hint_type = { +# 'plan': Hint('plan'), +# 'no_input_call': Hint('no_input_call'), +#} + +def test(python, code): + # List of inputs: (expression to eval, stdin). + test_in = [ + (None, '45\n100\n'), + (None, '44\n100\n'), + (None, '46\n100\n'), + (None, '0\n100\n'), + (None, '90\n100\n'), + (None, '32\n747\n'), + #(None, '212\n'), + #(None, '-459.4\n'), + #(None, '98.6\n'), + #(None, '1832\n'), + ] + test_out = [ + '1000', + '999.39' + '999.39' + #'100', + #'-273', + #'37', + #'1000' + ] + + # List of outputs: (expression result, stdout, stderr, exception). + answers = python(code=code, inputs=test_in, timeout=1.0) + outputs = [ans[1] for ans in answers] + + print (answers) + + n_correct = 0 + for output, correct in zip(outputs, test_out): + if correct in output: + n_correct += 1 + return n_correct, len(test_in) + +def hint(python, code): + # run one test first to see if there are any exceptions + test_in = [(None, '212\n')] + exc = python(code=code, inputs=test_in, timeout=1.0)[0][3] + # have an exception! + if exc: + if 'NameError' in exc: + return [{'id':'name_error'}] + if 'not callable' in exc: + return [{'id':'not_callable'}] + if 'unsupported operand' in exc: + return [{'id':'unsupported_operand'}] + if 'SyntaxError' in exc: + return [{'id':'syntax_error'}] + if 'IndentationError' in exc: + return [{'id':'indentation_error'}] + + + # the trick is to decide when to show the plan and when the first hint. + # I implemented a simple idea: show plan, when code contains something from the + # solution, but not input. + if not code or (not has_token_sequence(code, ['input']) and + (has_token_sequence(code, ['32']) or + has_token_sequence(code, ['=', '5']) or + has_token_sequence(code, ['print']))): + return [{'id': 'plan'}] + + + # if input is not present in code, student needs to learn about input + if not has_token_sequence(code, ['input']): + return [{'id': 'no_input_call'}] + + # if tokens * or / or = are not in code, we have to teach them how to + # evaluate expressions. + if (not has_token_sequence(code, ['/']) or + not has_token_sequence(code, ['*']) or + not has_token_sequence(code, ['='])): + return [{'id' : 'expressions_python'}] + + # student is not using print function + if not has_token_sequence(code, ['print']): + return [{'id' : 'printing'}] + + return None diff --git a/python/problems/introduction/pythagorean_theorem/en.py b/python/problems/introduction/pythagorean_theorem/en.py new file mode 100644 index 0000000..72e83aa --- /dev/null +++ b/python/problems/introduction/pythagorean_theorem/en.py @@ -0,0 +1,16 @@ +# coding=utf-8 + +id = 1000 +name = 'Pythagorean theorem' +slug = 'Pythagorean theorem' + +description = '''\ +<p>(translation missing)''' + +hint = { + 'plan': '''\ +<p>(translation missing)</p>''', + + 'no_input_call': '''\ +<p>(translation missing)</p>''', +} diff --git a/python/problems/introduction/pythagorean_theorem/sl.py b/python/problems/introduction/pythagorean_theorem/sl.py new file mode 100644 index 0000000..ae88d1b --- /dev/null +++ b/python/problems/introduction/pythagorean_theorem/sl.py @@ -0,0 +1,136 @@ +# coding=utf-8 + +id = 1000 +name = 'Pitagorov izrek' +slug = 'Pitagorov izrek' + +description = '''\ +<p>Napiši program, ki mu uporabnik vpiše temperaturo v Fahrenheitovih +stopinjah, program pa jo izpiše v Celzijevih. Med temperaturama pretvarjamo po +formuli C = 5/9 (F – 32).</p>''' + +general_exception = { + 'error_head' : '<p>Napaka:</p>', + + 'general': ''' + <p>Pri razumevanju napake sta pomembni dve vrstici. V drugi vrstici je specificirana lokacija + napake (line XY), v zadnji vrstici pa izvemo za kakšno napako gre.</p> + ''', + + 'name_error' : ''' + <p>Napaka tipa NameError označuje, da uporabljate nedefinirano vrednost:</p> + <ul> + <li>Če je v napaki omenjena spremenljivka, potem vrednost te spremenljivke ni določena, + a vi jo poskušate uporabiti.</li> + <li>Če napaka omenja ime funkcije, potem ste verjetno pozabili uvoziti ustrezni modul. + Npr. če gre za matematično funkcijo, je potrebno uvoziti modul <code>math</code>: + <pre> + from math import * + </pre> + ''', + + 'type_error': ''' + <p>TypeError napaka pomeni, da želite izvesti operacijo na nedovoljenih tipih. Npr., če želite sešteti niz in +število ali klicati funkcijo, čeprav tisto ni funkcija, itd. .</p> + ''', + + 'syntax_error': ''' + <p>Napaka v sintaksi programa. Napisali ste nekaj, kar Python ne zna prebrati.</p> ''', + + 'indentation_error': ''' + <p> Pomeni, da imate napačno število presledkov na začetku vrstice. Poskrbite, da so vse vrstice pravilno +poravnane. </p>''' + +} + +hint = { + 'plan': ['''\ +<p>Program izvedemo v treh korakih:</p> +<ol> + <li>Vprašanje za temperaturo v Fahrenheitih (F = ?).</li> + <li>Izračun temperature v Celzijih: C = 5/9 (F – 32)</li> + <li>Izpis temperature v Celzijih (izpiši C).</li> +</ol>'''], + + 'no_input_call': ['''\ +<p>Uporabnika lahko nekaj vprašamo s funkcijo <code>input</code>. Funkcija +<code>input</code> sprejme kot argument niz (<em>angl.</em> string), ki se +prikaže uporabniku kot vprašanje in vrne niz, ki ga je uporabnik napisal. Nize +zapisujemo v narekovaje (lahko so enojni ali dvojni). Npr., naslednja +vrstica:</p> +<pre> +ime = input("Kako ti je ime?") +</pre> +<p>pokliče funkcijo <code>input</code>, ki povpraša uporabnika po imenu in si +shrani uporabnikov odgovor v spremenljivko <code>ime</code>.</p>'''], + + + 'expressions_python': [''' +<p>Računanje: če v Pythonu napišemo izraz, se bo ta izračunal. Npr., če napišemo</p> +<pre> +3 + 6 +<pre> +bo Python seštel vrednosti 3 in 6 in ... rezultat pozabil. Kadar pa želimo +rezultat shraniti, za to uporabimo <em>prireditveni stavek</em>, kjer na levo +napišemo ime spremenljivke, na desno pa izraz:</p> +<pre> +c = 2 * a * (3 + b) +</pre> +<p> Kot vidite, izraz lahko uporablja tudi spremenljivke. </p>'''], + + 'printing': [''' +<p> V Pythonu izpisujemo s funkcijo <code>print. Če želimo izpisati več elementov, +jih ločimo z vejico. Recimo, da imamo spremenljivko <code>ime</code>, +ki vsebuje naše ime, potem lahko napišemo: +<pre> +print("Ime mi je", ime, ".") +</pre>'''], + + 'name_error' : [general_exception['error_head'], general_exception['general'], + general_exception['name_error'], ''' + <p>Verjetno uporabljate spremenljivko, ki nima vrednosti. Ali v izrazu za izračun + uporabljate napačno spremenljivko? Ali pri izpisu morda poskušate + izpisati napačno spremenljivko?</p>'''], + + 'unsupported_operand' : [general_exception['error_head'], general_exception['general'], + general_exception['type_error'], ''' +<p>Verjetni razlog: funkcija <code>input</code> vrača vrednost tipa niz, +ki jo moramo najprej pretvoriti v tip <code>float</code>, če želimo z njo računati:</p> +<pre> +v = float(input(" ... +</pre> +<p>Zakaj je tako, boste razumeli kasneje, zaenkrat je dovolj, da to poznate.</p> +<p>Na primeru pretvarjanja temperatur:</p> +<pre> +fniz = input("Temperatura [F]: ") +f = float(fniz) +</pre> +<p>ali krajše, združeno v eno vrstico:</p> +<pre> +f = float(input("Temperatura [F]: ")) +</pre> +<p>Funkcijo <code>float</code> lahko kličemo le, če je v nizu zapisano število, +npr. "10". Če imamo v nizu tudi kakšno črko, bo Python javil napako.</p> '''], + + + 'not_callable' : [general_exception['error_head'], general_exception['general'], + general_exception['type_error'], ''' +<p>V programu poskušate uporabiti število kot funkcijo, a to ne gre. +Verjetni razlog: Ali ste v izrazu pozabili na znak *. Pri pretvorbi temperatur bi namesto:</p> +<pre> +C = 5/9(F – 32) +</pre> +<p>morali napisati: </p> +<pre> +C = 5/9 * (F – 32). +</pre> +<p> Python ne zna izpuščati znaka za množenje, kot to delamo pri matematiki.</p> '''], + + 'syntax_error' : [general_exception['error_head'], general_exception['general'], + general_exception['type_error'], ''' +<p> Ste mogoče pozabili na kakšen zaklepaj? </p>'''], + + 'indentation_error' : [general_exception['error_head'], general_exception['general'], + general_exception['indentation_error']], + +} |