From df2e7033ff1a4336d7cc404a845e3c214ee7ddfd Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 15 Sep 2015 15:26:28 +0200 Subject: Improved hints for pythagorean theorem. --- .../introduction/fahrenheit_to_celsius/common.py | 5 +- .../introduction/fahrenheit_to_celsius/sl.py | 7 -- .../introduction/pythagorean_theorem/common.py | 91 +++++++--------------- .../introduction/pythagorean_theorem/sl.py | 52 +++++-------- 4 files changed, 49 insertions(+), 106 deletions(-) (limited to 'python') diff --git a/python/problems/introduction/fahrenheit_to_celsius/common.py b/python/problems/introduction/fahrenheit_to_celsius/common.py index 79cdff3..0bb6468 100644 --- a/python/problems/introduction/fahrenheit_to_celsius/common.py +++ b/python/problems/introduction/fahrenheit_to_celsius/common.py @@ -22,7 +22,6 @@ hint_type = { 'name_error': HintSequence('name_error', 4), 'unsupported_operand': HintSequence('unsupported_operand', 4), 'not_callable': HintSequence('not_callable', 4), - 'indentation_error': HintSequence('indentation_error', 3), } def test(python, code): @@ -66,14 +65,12 @@ def hint(python, code): return [{'id':'unsupported_operand', 'args': {'message': exc}}] elif 'TypeError' in exc: return [{'id':'unsupported_operand', 'args': {'message': exc}}] - elif 'IndentationError' in exc: - return [{'id':'indentation_error', 'args': {'message': exc}}] # 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 + if len(code.strip()) < 5 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']))): diff --git a/python/problems/introduction/fahrenheit_to_celsius/sl.py b/python/problems/introduction/fahrenheit_to_celsius/sl.py index 41aab7a..1c73cce 100644 --- a/python/problems/introduction/fahrenheit_to_celsius/sl.py +++ b/python/problems/introduction/fahrenheit_to_celsius/sl.py @@ -128,11 +128,4 @@ C = 5/9 * (F – 32).

Python ne zna izpuščati znaka za množenje, kot to delamo pri matematiki.

'''], - 'syntax_error' : [general_exception['error_head'], general_exception['general'], - general_exception['type_error'], ''' -

Ste mogoče pozabili na kakšen zaklepaj?

'''], - - '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 index 5f59588..800107e 100644 --- a/python/problems/introduction/pythagorean_theorem/common.py +++ b/python/problems/introduction/pythagorean_theorem/common.py @@ -1,73 +1,50 @@ # coding=utf-8 -from python.util import has_token_sequence +from python.util import has_token_sequence, string_almost_equal from server.hints import Hint, HintSequence -id = 1000 +id = 188 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.") +a = float(input("Prva kateta: ")) +b = float(input("Druga kateta: ")) +c = sqrt(a ** 2 + b ** 2) +print("Hipotenuza trikotnika s stranicama", a, "in", b, "je", c) ''' hint_type = { 'plan': Hint('plan'), - 'name_error': HintSequence('name_error'), - 'unsupported_operand': HintSequence('unsupported_operand'), - 'syntax_error' : HintSequence('syntax_error'), - 'indentation_error': HintSequence('indentation_error'), + 'name_error': HintSequence('name_error', 4), + 'unsupported_operand': HintSequence('unsupported_operand', 4), 'no_input_call' : Hint('no_input_call'), - 'radians': HintSequence('radians'), 'printing': Hint('printing'), 'math_functions': Hint('math_functions') } - -def almostEqual(a, b, prec=1): - """ Compares values a and b using at most prec decimal values. """ - return int(a*10**prec) == int(b*10**prec) - -def stringAlmostEqual(s, a): - """ Searches string s for a value that is almost equal to a. - - Args: - s (str): string to search - a (float): value to find in string - - Returns: - bool: True if successful, else False - """ - for v in s.split(): - try: - if almostEqual(float(v), a): - return True - return False - 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, '3\n4\n'), + (None, '4\n3\n'), + (None, '12\n5\n'), + (None, '5\n12\n'), + (None, '5\n0\n'), + (None, '0\n5\n'), + (None, '1\n1\n'), ] + test_out = [ - '1000', - '999.39', - '999.39', - '0.0', - '0.0', - '50153.5' + 5, + 5, + 13, + 13, + 5, + 5, + 1.414 ] # List of outputs: (expression result, stdout, stderr, exception). @@ -76,32 +53,24 @@ def test(python, code): n_correct = 0 for output, correct in zip(outputs, test_out): - if stringAlmostEqual(output, correct): + if string_almost_equal(output, float(correct)): 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, '45\n')] + test_in = [(None, '3\n4\n')] answer = python(code=code, inputs=test_in, timeout=1.0) exc = answer[0][3] # if have an exception! if exc: if 'NameError' in exc: - return [{'id':'name_error'}] - 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'}] - - # if result if 893.996, angle is not converted to radians - if stringAlmostEqual(answer[0][1], 893.996): - return [{'id': 'radians'}] + return [{'id':'name_error', 'args': {'exception': exc}}] + if 'unsupported operand' in exc or 'TypeError' in exc: + return [{'id':'unsupported_operand', 'args': {'exception': exc}}] # show plan if student is lost - if not code or (not has_token_sequence(code, ['input']) and + if len(code.strip()) < 5 or (not has_token_sequence(code, ['input']) and (has_token_sequence(code, ['pi']) or has_token_sequence(code, ['sin']) or has_token_sequence(code, ['print']))): @@ -116,7 +85,7 @@ def hint(python, code): # if tokens sqrt or ** are not in code, we have to teach them how to # use math functions. if (not has_token_sequence(code, ['sqrt']) or - not has_token_sequence(code, ['**']): + not has_token_sequence(code, ['**'])): return [{'id' : 'math_functions'}] # student is not using print function diff --git a/python/problems/introduction/pythagorean_theorem/sl.py b/python/problems/introduction/pythagorean_theorem/sl.py index ffbf6a1..806db27 100644 --- a/python/problems/introduction/pythagorean_theorem/sl.py +++ b/python/problems/introduction/pythagorean_theorem/sl.py @@ -1,6 +1,6 @@ # coding=utf-8 -id = 1000 +id = 188 name = 'Pitagorov izrek' slug = 'Pitagorov izrek' @@ -9,11 +9,16 @@ description = '''\ izpiše dolžino hipotenuze. ''' general_exception = { - 'error_head' : '

Napaka:

', + 'error_head' : '''\ +

Napaka:

+
+[%=message%]
+
+''', 'general': ''' -

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.

+

Pri razumevanju napake sta pomembni dve vrstici. V predzadnji vrstici je napisana lokacija + napake (line ...), v zadnji vrstici pa izvemo za kakšno napako gre.

''', 'name_error' : ''' @@ -29,30 +34,22 @@ general_exception = { ''', 'type_error': ''' -

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. .

- ''', - - 'syntax_error': ''' -

Napaka v sintaksi programa. Napisali ste nekaj, kar Python ne zna prebrati.

''', - - 'indentation_error': ''' -

Pomeni, da imate napačno število presledkov na začetku vrstice. Poskrbite, da so vse vrstice pravilno -poravnane.

''' - +

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. .

+ ''' } hint = { - 'plan': ['''\ + 'plan': '''\

Program razdelimo na tri dele kot pri Fahrenheitih:

  1. Preberi vrednosti katet (a,b = ?)
  2. Izračunaj dolžino hipotenuze c (c = …)
  3. Izpis dolžine hipotenuze (print … )
-'''], +''', - 'no_input_call': ['''\ + 'no_input_call': '''\

Tako kot pri prejšnji nalogi uporabimo funkcijo input, le da tokrat preberemo dve vrednosti in jih shranimo v dve spremenljivki:

@@ -65,7 +62,7 @@ potrebovali kasneje v programu. Imena spremenljivk so lahko poljubno
  dolga, v našem primeru bi jim lahko rekli tudi kateta_a in kateta_b. 
  Pri programiranju velja, da izbiramo taka imena spremenljivk, 
  ki bodo naredila program berljiv. 

- '''] + ''', 'math_functions': [''' @@ -91,12 +88,6 @@ ki vsebuje naše ime, potem lahko napišemo: print("Ime mi je", ime, ".")
'''], - 'radians': [''' -

Vse triginometrične funkcije sprejemajo kot v radianih in ne v stopinjah.

''', -'''

V stopinjah ima cel krog 360°, v radianih pa 2*pi. Zato je 360° ekvivalentno 2*pi.

''', -'''

Formula za pretvorbo med stopinjami in radiani je:

-kot_rad = kot * 2 * pi / 360'''] - 'name_error' : [general_exception['error_head'], general_exception['general'], general_exception['name_error'], '''

Verjetno uporabljate spremenljivko, ki nima vrednosti. Ali v izrazu za izračun @@ -110,13 +101,6 @@ ki jo moramo najprej pretvoriti v tip float, če želimo z njo rač

 v = float(input(" ...
 
-'''], - - 'syntax_error' : [general_exception['error_head'], general_exception['general'], - general_exception['type_error'], ''' -

Ste mogoče pozabili na kakšen zaklepaj ali pa narekovaje?

'''], - - 'indentation_error' : [general_exception['error_head'], general_exception['general'], - general_exception['indentation_error']], +'''] -} +} \ No newline at end of file -- cgit v1.2.1