From 86bfc55d2ddc19b79127f2c788609635b702dbfd Mon Sep 17 00:00:00 2001
From: Aleksander Sadikov
Date: Sat, 17 Oct 2015 20:04:54 +0200
Subject: Family relations section fully hint-ready (just a few minor things
missing).
---
.../ancestor_2/Prolog_ancestor_01.svg | 356 +++++++
.../ancestor_2/Prolog_ancestor_02.svg | 292 ++++++
.../ancestor_2/Prolog_ancestor_03.svg | 766 ++++++++++++++
.../ancestor_2/Prolog_ancestor_04.svg | 940 +++++++++++++++++
.../problems/family_relations/ancestor_2/common.py | 37 +-
prolog/problems/family_relations/ancestor_2/sl.py | 25 +-
.../family_relations/aunt_2/Prolog_aunt_01.svg | 425 ++++++++
.../family_relations/aunt_2/Prolog_aunt_02.svg | 402 ++++++++
.../family_relations/aunt_2/Prolog_aunt_03.svg | 639 ++++++++++++
.../family_relations/aunt_2/Prolog_aunt_04.svg | 560 ++++++++++
.../family_relations/aunt_2/Prolog_aunt_05.svg | 576 +++++++++++
.../family_relations/aunt_2/Prolog_aunt_06.svg | 425 ++++++++
.../family_relations/aunt_2/Prolog_aunt_07.svg | 463 +++++++++
prolog/problems/family_relations/aunt_2/common.py | 28 +-
prolog/problems/family_relations/aunt_2/sl.py | 21 +-
.../problems/family_relations/brother_2/common.py | 12 +-
prolog/problems/family_relations/brother_2/sl.py | 19 +-
.../family_relations/connected_3/common.py | 35 +
.../family_relations/cousin_2/Prolog_cousin_01.svg | 448 ++++++++
.../family_relations/cousin_2/Prolog_cousin_02.svg | 582 +++++++++++
.../family_relations/cousin_2/Prolog_cousin_03.svg | 825 +++++++++++++++
.../family_relations/cousin_2/Prolog_cousin_04.svg | 609 +++++++++++
.../problems/family_relations/cousin_2/common.py | 24 +-
prolog/problems/family_relations/cousin_2/sl.py | 19 +-
.../descendant_2/Prolog_descendant_01.svg | 374 +++++++
.../descendant_2/Prolog_descendant_02.svg | 283 +++++
.../descendant_2/Prolog_descendant_03.svg | 899 ++++++++++++++++
.../descendant_2/Prolog_descendant_04.svg | 1090 ++++++++++++++++++++
.../family_relations/descendant_2/common.py | 33 +-
.../problems/family_relations/descendant_2/sl.py | 24 +-
.../family_relations/father_2/Prolog_father_01.svg | 310 ++++++
.../family_relations/father_2/Prolog_father_02.svg | 352 +++++++
.../family_relations/father_2/Prolog_father_03.svg | 312 ++++++
.../family_relations/father_2/Prolog_father_04.svg | 325 ++++++
.../grandparent_2/Prolog_grandparent_01.svg | 439 ++++++++
.../grandparent_2/Prolog_grandparent_02.svg | 517 ++++++++++
.../grandparent_2/Prolog_grandparent_03.svg | 516 +++++++++
.../grandparent_2/Prolog_grandparent_04.svg | 463 +++++++++
.../problems/family_relations/grandparent_2/sl.py | 4 +-
.../problems/family_relations/sister_2/common.py | 12 +-
prolog/problems/family_relations/sister_2/sl.py | 19 +-
41 files changed, 14410 insertions(+), 90 deletions(-)
create mode 100644 prolog/problems/family_relations/ancestor_2/Prolog_ancestor_01.svg
create mode 100644 prolog/problems/family_relations/ancestor_2/Prolog_ancestor_02.svg
create mode 100644 prolog/problems/family_relations/ancestor_2/Prolog_ancestor_03.svg
create mode 100644 prolog/problems/family_relations/ancestor_2/Prolog_ancestor_04.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_01.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_02.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_03.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_04.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_05.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_06.svg
create mode 100644 prolog/problems/family_relations/aunt_2/Prolog_aunt_07.svg
create mode 100644 prolog/problems/family_relations/cousin_2/Prolog_cousin_01.svg
create mode 100644 prolog/problems/family_relations/cousin_2/Prolog_cousin_02.svg
create mode 100644 prolog/problems/family_relations/cousin_2/Prolog_cousin_03.svg
create mode 100644 prolog/problems/family_relations/cousin_2/Prolog_cousin_04.svg
create mode 100644 prolog/problems/family_relations/descendant_2/Prolog_descendant_01.svg
create mode 100644 prolog/problems/family_relations/descendant_2/Prolog_descendant_02.svg
create mode 100644 prolog/problems/family_relations/descendant_2/Prolog_descendant_03.svg
create mode 100644 prolog/problems/family_relations/descendant_2/Prolog_descendant_04.svg
create mode 100644 prolog/problems/family_relations/father_2/Prolog_father_01.svg
create mode 100644 prolog/problems/family_relations/father_2/Prolog_father_02.svg
create mode 100644 prolog/problems/family_relations/father_2/Prolog_father_03.svg
create mode 100644 prolog/problems/family_relations/father_2/Prolog_father_04.svg
create mode 100644 prolog/problems/family_relations/grandparent_2/Prolog_grandparent_01.svg
create mode 100644 prolog/problems/family_relations/grandparent_2/Prolog_grandparent_02.svg
create mode 100644 prolog/problems/family_relations/grandparent_2/Prolog_grandparent_03.svg
create mode 100644 prolog/problems/family_relations/grandparent_2/Prolog_grandparent_04.svg
diff --git a/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_01.svg b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_01.svg
new file mode 100644
index 0000000..2478b13
--- /dev/null
+++ b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_01.svg
@@ -0,0 +1,356 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_02.svg b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_02.svg
new file mode 100644
index 0000000..8d911be
--- /dev/null
+++ b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_02.svg
@@ -0,0 +1,292 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_03.svg b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_03.svg
new file mode 100644
index 0000000..08bb4c7
--- /dev/null
+++ b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_03.svg
@@ -0,0 +1,766 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_04.svg b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_04.svg
new file mode 100644
index 0000000..8118e75
--- /dev/null
+++ b/prolog/problems/family_relations/ancestor_2/Prolog_ancestor_04.svg
@@ -0,0 +1,940 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/ancestor_2/common.py b/prolog/problems/family_relations/ancestor_2/common.py
index 7249ed8..94b7e68 100644
--- a/prolog/problems/family_relations/ancestor_2/common.py
+++ b/prolog/problems/family_relations/ancestor_2/common.py
@@ -4,7 +4,7 @@ from operator import itemgetter
import socket
import prolog.engine
import prolog.util
-from server.hints import Hint, HintSequence
+from server.hints import Hint, HintPopup
import server.problems
id = 100
@@ -21,8 +21,10 @@ ancestor(X, Y) :-
'''
hint_type = {
+ 'gender_is_irrelevant_markup': HintPopup('gender_is_irrelevant_markup'),
'gender_is_irrelevant': Hint('gender_is_irrelevant'),
'grandparent_used': Hint('grandparent_used'),
+ 'grandparent_used_markup': HintPopup('grandparent_used_markup'),
'base_case': Hint('base_case'),
'ancestor_to_oneself': Hint('ancestor_to_oneself'),
'descendant_need_not_be_parent': Hint('descendant_need_not_be_parent'),
@@ -30,7 +32,12 @@ hint_type = {
}
test_cases = [
- # TODO
+ ('ancestor(ana, X)',
+ [{'X': 'aleksander'}, {'X': 'luana'}, {'X': 'daniela'}]),
+ ('ancestor(morty, X)',
+ [{'X': 'jerry'}, {'X': 'anna'}]),
+ ('ancestor(X, susan)',
+ [{'X': 'vanessa'}, {'X': 'patrick'}, {'X': 'tina'}, {'X': 'thomas'}, {'X': 'william'}]),
]
def test(program, solved_problems):
@@ -75,29 +82,29 @@ def hint(program, solved_problems):
# gender testing is redundant
# this is not necessarily wrong, but worth mentioning anyway
targets = [prolog.util.Token('NAME', 'male'), prolog.util.Token('NAME', 'female')]
- pos = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
- if pos:
- # TODO: resolve how highlighting info is communicated
- return [{'id': 'gender_is_irrelevant', 'highlight': pos}]
+ marks = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
+ if marks:
+ return [{'id': 'gender_is_irrelevant_markup', 'start': m[0], 'end': m[1]} for m in marks] + \
+ [{'id': 'gender_is_irrelevant'}]
# grandparent is a sign of complications
# it's likely used instead of recursion
targets = [prolog.util.Token('NAME', 'grandparent')]
- pos = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
- if pos:
- # TODO: resolve how highlighting info is communicated
- return [{'id': 'grandparent_used', 'highlight': pos}]
+ marks = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
+ if marks:
+ return [{'id': 'grandparent_used_markup', 'start': m[0], 'end': m[1]} for m in marks] + \
+ [{'id': 'grandparent_used'}]
# missing/failed base case
# TODO: how will ask_truth handle/return timeouts...
# TODO: timeout is the same as fail in this particular case
if prolog.engine.ask_truth(engine_id,
'parent(X, Y), \+ ancestor(X, Y)'):
- return [{'id', 'base_case'}]
+ return [{'id': 'base_case'}]
# ancestor to oneself
if prolog.engine.ask_truth(engine_id, 'ancestor(X, X)'):
- return [{'id', 'ancestor_to_oneself'}]
+ return [{'id': 'ancestor_to_oneself'}]
# Y does not necessarily need to be a parent
if prolog.engine.ask_one(engine_id,
@@ -109,14 +116,14 @@ def hint(program, solved_problems):
if prolog.engine.ask_truth(engine_id,
'findall(_, ancestor(william, X), L1), length(L1, 2), \
findall(_, ancestor(X, william), L2), length(L2, 6)'):
- return [{'id', 'wrong_direction'}]
+ return [{'id': 'wrong_direction'}]
except socket.timeout as ex:
- pass
+ return [{'id': 'base_case'}]
finally:
if engine_id:
prolog.engine.destroy(engine_id)
- return None
+ return []
diff --git a/prolog/problems/family_relations/ancestor_2/sl.py b/prolog/problems/family_relations/ancestor_2/sl.py
index d74ccc5..b0fae7c 100644
--- a/prolog/problems/family_relations/ancestor_2/sl.py
+++ b/prolog/problems/family_relations/ancestor_2/sl.py
@@ -14,31 +14,38 @@ description = '''\
plan = ['''\
Sedaj pa bo potrebna rekurzija... kako lahko problem prevedem na (en korak) manjši problem?
-
-
Loni naj zbriše imena relacij (parent, ancestor) s te slike!
-''', '''\
-
+
''', '''\
Če je X starš od nekega Z in je
ta Z prednik od Y,
potem je X tudi prednik od Y.
+''', '''\
+
''']
hint = {
'gender_is_irrelevant': '''\
Je spol res pomemben?
+''',
+
+ 'gender_is_irrelevant_markup': '''\
+
Je to res potrebno?
''',
'grandparent_used': '''\
Rešitev z "grandparent" bo premalo splošna, poskusi nadomestiti to z rekurzijo.
Skratka, poskusi prevesti na "manjši" problem, npr. prednik v enem koraku manj
(en korak bližji prednik)...
+''',
+
+ 'grandparent_used_markup': '''\
+
Bi se dalo rešiti brez tega?
''',
'base_case': '''\
Si pomislil na robni pogoj? Kaj je najbolj enostaven par (prednik, potomec)?
-
-''',
+
+''', # TODO: morda ta hint naredim z "more": najprej tekst, ob kliku pa še slika... (sicer je preveč očitno)
'ancestor_to_oneself': '''\
Kako je lahko nekdo prednik samemu sebi?
@@ -51,11 +58,7 @@ Skratka, poskusi prevesti na "manjši" problem, npr. prednik v enem koraku manj
'wrong_direction': '''\
Si morda sprogramiral ravno obratno in zamenjal prednika s potomcem?
X naj bo prednik od Y in ne obratno!
+
''',
-
-# 'interesting_tidbit': '''\
-#
Zanimivost: nalogo bi lahko rešil tudi z uporabo rešitve za relacijo "sister".
-# Teta je namreč sestra od starša od Y.
-# ''',
}
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_01.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_01.svg
new file mode 100644
index 0000000..7b55826
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_01.svg
@@ -0,0 +1,425 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_02.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_02.svg
new file mode 100644
index 0000000..1c994f5
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_02.svg
@@ -0,0 +1,402 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_03.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_03.svg
new file mode 100644
index 0000000..8442518
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_03.svg
@@ -0,0 +1,639 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_04.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_04.svg
new file mode 100644
index 0000000..83b6685
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_04.svg
@@ -0,0 +1,560 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_05.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_05.svg
new file mode 100644
index 0000000..4083a57
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_05.svg
@@ -0,0 +1,576 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_06.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_06.svg
new file mode 100644
index 0000000..4042814
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_06.svg
@@ -0,0 +1,425 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/Prolog_aunt_07.svg b/prolog/problems/family_relations/aunt_2/Prolog_aunt_07.svg
new file mode 100644
index 0000000..c9f3d5c
--- /dev/null
+++ b/prolog/problems/family_relations/aunt_2/Prolog_aunt_07.svg
@@ -0,0 +1,463 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/aunt_2/common.py b/prolog/problems/family_relations/aunt_2/common.py
index 51bc99a..df1a272 100644
--- a/prolog/problems/family_relations/aunt_2/common.py
+++ b/prolog/problems/family_relations/aunt_2/common.py
@@ -27,14 +27,21 @@ aunt(X, Y) :-
hint_type = {
'x_and_y_mixed_up': Hint('x_and_y_mixed_up'),
'precedence_fail': Hint('precedence_fail'),
+ 'x_must_have_sibling': Hint('x_must_have_sibling'),
'x_must_be_female': Hint('x_must_be_female'),
+ 'y_must_have_parent': Hint('y_must_have_parent'),
'aunt_vs_mother': Hint('aunt_vs_mother'),
'x_need_not_be_parent': Hint('x_need_not_be_parent'),
'y_need_not_be_parent': Hint('y_need_not_be_parent'),
}
test_cases = [
- # TODO
+ ('aunt(X, _)',
+ [{'X': 'sally'}, {'X': 'melanie'}, {'X': 'vanessa'}, {'X': 'patricia'}]),
+ ('aunt(_, X)',
+ [{'X': 'vanessa'}, {'X': 'patricia'}, {'X': 'joanne'}, {'X': 'john'}, {'X': 'susan'}]),
+ ('aunt(sally, X)',
+ [{'X': 'vanessa'}, {'X': 'patricia'}]),
]
def test(program, solved_problems):
@@ -82,25 +89,36 @@ def hint(program, solved_problems):
if prolog.engine.ask_truth(engine_id,
'findall(X/Y, aunt(X, Y), \
[vanessa/sally, patricia/sally, joanne/melanie, john/vanessa, susan/patricia])'):
- return [{'id', 'x_and_y_mixed_up'}]
+ return [{'id': 'x_and_y_mixed_up'}]
# precedence fail (AND block vs OR block)
# case in point: female(X), parent(P, Y), brother(P, X) ; sister(P, X)
# warning: knowledge base dependent
if prolog.util.Token('SEMI', ';') in tokens and prolog.engine.ask_truth(engine_id,
'findall(_, aunt(X, Y), L), length(L, 15)'):
- return [{'id', 'precedence_fail'}]
+ return [{'id': 'precedence_fail'}]
# X must be female
if prolog.engine.ask_truth(engine_id,
'aunt(X, _), male(X)'):
- return [{'id', 'x_must_be_female'}]
+ return [{'id': 'x_must_be_female'}]
+
+ # Y must have a parent
+ # perhaps risky as only one such nephew exists in DB (susan)
+ if prolog.engine.ask_truth(engine_id,
+ 'aunt(_, Y), \+ parent(_, Y)'):
+ return [{'id': 'y_must_have_parent'}]
# X and P can be the same person
# this can occur if the problem is not solved using sister/2
if prolog.engine.ask_truth(engine_id,
'aunt(X, Y), mother(X, Y)'):
- return [{'id', 'aunt_vs_mother'}]
+ return [{'id': 'aunt_vs_mother'}]
+
+ # X must have sibling
+ if prolog.engine.ask_truth(engine_id,
+ 'aunt(X, _), \+ (sister(X, _) ; brother(X, _))'): # TODO: Tim, can I use sister/brother predicates here? Or sister98?
+ return [{'id': 'x_must_have_sibling'}]
# X does not necessarily need to be a parent
# perhaps risky as only one aunt that is not a parent exists in DB (melanie)
diff --git a/prolog/problems/family_relations/aunt_2/sl.py b/prolog/problems/family_relations/aunt_2/sl.py
index 2bf0ef6..e5c3bb9 100644
--- a/prolog/problems/family_relations/aunt_2/sl.py
+++ b/prolog/problems/family_relations/aunt_2/sl.py
@@ -13,13 +13,12 @@ description = '''\
plan = ['''\
Morda lahko uporabiš rešitev kakšne prejšnje naloge?
-
-
Loni naj zbriše imena relacij (parent, sister) s te slike!
-''', '''\
-
+
''', '''\
Če je X sestra od starša od Y,
potem je X teta od Y.
+''', '''\
+
''']
hint = {
@@ -31,16 +30,27 @@ hint = {
Si morda narobe upošteval prioriteto operatorjev IN ter ALI?
Operator IN veže močneje od ALI, če želiš spremeniti prioriteto,
lahko uporabiš oklepaje.
+''',
+
+ 'x_must_have_sibling': '''\
+
Teta ima navadno brata ali sestro...
+
''',
'x_must_be_female': '''\
Teta je navadno ženskega spola.
+
''', # TODO: Loni should mark female gender on some aunt hints!
+ 'y_must_have_parent': '''\
+
Verjetno bi bilo smiselno, da ima nečak kakšnega starša?
+
+''',
+
'aunt_vs_mother': '''\
Kako je teta lahko hkrati še mama od Y?
Si morda pozabil, da teta in starš od Y ne smeta biti ista oseba?
-
+
''',
'x_need_not_be_parent': '''\
@@ -54,6 +64,7 @@ Si morda pozabil, da teta in starš od Y ne smeta biti ista oseba?<
'interesting_tidbit': '''\
Zanimivost: nalogo bi lahko rešil tudi z uporabo rešitve za relacijo "sister".
Teta je namreč sestra od starša od Y.
+
''', # TODO: only trigger if sister is not part of correct solution
}
diff --git a/prolog/problems/family_relations/brother_2/common.py b/prolog/problems/family_relations/brother_2/common.py
index 48b89fe..654825e 100644
--- a/prolog/problems/family_relations/brother_2/common.py
+++ b/prolog/problems/family_relations/brother_2/common.py
@@ -23,8 +23,9 @@ brother(X, Y) :-
hint_type = {
'x_must_be_male': Hint('x_must_be_male'),
'common_parent_needed': Hint('common_parent_needed'),
- 'y_can_be_of_any_gender': Hint('Y_can_be_of_any_gender'),
+ 'y_can_be_of_any_gender': Hint('y_can_be_of_any_gender'),
'x_y_must_be_different': Hint('x_y_must_be_different'),
+ 'neq_used_too_early': Hint('neq_used_too_early'),
}
test_cases = [
@@ -64,7 +65,7 @@ def test(program, solved_problems):
return passed, hints
def hint(program, solved_problems):
- # tokens = prolog.util.tokenize(program)
+ tokens = prolog.util.tokenize(program)
code = (program + '\n' +
server.problems.solutions_for_problems('prolog', solved_problems) + '\n' +
@@ -91,10 +92,15 @@ def hint(program, solved_problems):
return [{'id': 'y_can_be_of_any_gender'}]
# X and Y must be different
- if prolog.engine.ask_truth(engine_id,
+ if prolog.util.Token('NEQ', '\==') not in tokens and prolog.engine.ask_truth(engine_id,
'setof(X, (member(X, [william, alessandro, andrew]), brother(X, X)), L), length(L, 3)'):
return [{'id': 'x_y_must_be_different'}]
+ # X and Y must be different, but \== was used
+ if prolog.util.Token('NEQ', '\==') in tokens and prolog.engine.ask_truth(engine_id,
+ 'setof(X/Y, brother(X, Y), L), member(alessandro/alessandro, L), member(andrew/andrew, L), member(william/william, L)'):
+ return [{'id': 'neq_used_too_early'}]
+
except socket.timeout as ex:
pass
diff --git a/prolog/problems/family_relations/brother_2/sl.py b/prolog/problems/family_relations/brother_2/sl.py
index 96c6126..29703a1 100644
--- a/prolog/problems/family_relations/brother_2/sl.py
+++ b/prolog/problems/family_relations/brother_2/sl.py
@@ -22,14 +22,16 @@ potem je X brat od Y.
Si pomislil, da sta X in Y lahko ista oseba? Poskusi naslednjo poizvedbo:
?- brother(william, Y).
-
-
VEČ... Kako naredim, da sta X in Y različna?
-''',
+''', 'linkText': 'Kako lahko preverim, da sta X in Y različna?'},
+'''\
+
S pomočjo operatorja \== lahko preverim, da sta X in Y med seboj različna.
+Na primer: X \== Y
+'''],
'x_must_be_male': '''\
@@ -44,4 +46,13 @@ hint = {
Dobro bi bilo, da imata X in Y vsaj enega skupnega starša.
''',
+
+ 'neq_used_too_early': '''\
+
Si morda uporabil operator \== prezgodaj?
+
Poskusi ga pomakniti bolj proti koncu. Razlog za probleme je verjetno,
+da spremenljivki, ki ju primerjaš, še nimata določene vrednosti in sta zato različni.
+Prolog ne preverja, če kasneje morda postaneta enaki, ampak samo kakšni sta v trenutku,
+ko naleti na primerjavo.
+''',
+
}
diff --git a/prolog/problems/family_relations/connected_3/common.py b/prolog/problems/family_relations/connected_3/common.py
index 9c0bef7..e6aa6dc 100644
--- a/prolog/problems/family_relations/connected_3/common.py
+++ b/prolog/problems/family_relations/connected_3/common.py
@@ -15,3 +15,38 @@ connected(X, Y, N) :-
parent(Z, X) ),
connected(Z, Y, N1).
'''
+
+test_cases = [
+# ('descendant(anna, X)',
+# [{'X': 'jerry'}, {'X': 'elaine'}, {'X': 'morty'}, {'X': 'helen'}]),
+# ('descendant(daniela, X)',
+# [{'X': 'nevia'}, {'X': 'aleksander'}, {'X': 'margaret'}, {'X': 'ana'}, {'X': 'aleksandr'}]),
+# ('descendant(X, william)',
+# [{'X': 'vanessa'}, {'X': 'patricia'}, {'X': 'susan'}, {'X': 'john'}, {'X': 'michael'}, {'X': 'michelle'}]),
+]
+
+def test(program, solved_problems):
+ code = (program + '\n' +
+ server.problems.solutions_for_problems('prolog', solved_problems) + '\n' +
+ server.problems.load_facts('prolog', facts).facts)
+
+ engine_id = None
+ try:
+ engine_id, output = prolog.engine.create(code=code, timeout=1.0)
+ if not engine_id or 'error' in map(itemgetter(0), output):
+ # Engine creation failed, or syntax error in code.
+ return 0, len(test_cases)
+
+ n_correct = 0
+ for query, answers in test_cases:
+ # Limit inferences for each solution to curb unbounded recursion.
+ limited = 'call_with_inference_limit(({}), 100000, _)'.format(query)
+ if prolog.engine.check_answers(engine_id, query=limited, answers=answers, timeout=1.0):
+ n_correct += 1
+ finally:
+ if engine_id:
+ prolog.engine.destroy(engine_id)
+
+ passed = n_correct == len(test_cases)
+ hints = [{'id': 'test_results', 'args': {'passed': n_correct, 'total': len(test_cases)}}]
+ return passed, hints
diff --git a/prolog/problems/family_relations/cousin_2/Prolog_cousin_01.svg b/prolog/problems/family_relations/cousin_2/Prolog_cousin_01.svg
new file mode 100644
index 0000000..2e7cf55
--- /dev/null
+++ b/prolog/problems/family_relations/cousin_2/Prolog_cousin_01.svg
@@ -0,0 +1,448 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/cousin_2/Prolog_cousin_02.svg b/prolog/problems/family_relations/cousin_2/Prolog_cousin_02.svg
new file mode 100644
index 0000000..3844a83
--- /dev/null
+++ b/prolog/problems/family_relations/cousin_2/Prolog_cousin_02.svg
@@ -0,0 +1,582 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/cousin_2/Prolog_cousin_03.svg b/prolog/problems/family_relations/cousin_2/Prolog_cousin_03.svg
new file mode 100644
index 0000000..8829022
--- /dev/null
+++ b/prolog/problems/family_relations/cousin_2/Prolog_cousin_03.svg
@@ -0,0 +1,825 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/cousin_2/Prolog_cousin_04.svg b/prolog/problems/family_relations/cousin_2/Prolog_cousin_04.svg
new file mode 100644
index 0000000..d49256c
--- /dev/null
+++ b/prolog/problems/family_relations/cousin_2/Prolog_cousin_04.svg
@@ -0,0 +1,609 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/cousin_2/common.py b/prolog/problems/family_relations/cousin_2/common.py
index 8dc33b8..c556ffd 100644
--- a/prolog/problems/family_relations/cousin_2/common.py
+++ b/prolog/problems/family_relations/cousin_2/common.py
@@ -4,7 +4,7 @@ from operator import itemgetter
import socket
import prolog.engine
import prolog.util
-from server.hints import Hint, HintSequence
+from server.hints import Hint, HintPopup
import server.problems
id = 99
@@ -34,6 +34,7 @@ cousin(X, Y) :-
'''
hint_type = {
+ 'gender_is_irrelevant_markup': HintPopup('gender_is_irrelevant_markup'),
'gender_is_irrelevant': Hint('gender_is_irrelevant'),
'precedence_fail': Hint('precedence_fail'),
'cousin_vs_sibling': Hint('cousin_vs_sibling'),
@@ -42,7 +43,12 @@ hint_type = {
}
test_cases = [
- # TODO
+ ('cousin(X, _)',
+ [{'X': 'vanessa'}, {'X': 'patricia'}, {'X': 'melanie'}, {'X': 'andrew'}, {'X': 'john'}, {'X': 'susan'}]),
+ ('cousin(X, john)',
+ [{'X': 'susan'}]),
+ ('cousin(patricia, X)',
+ [{'X': 'andrew'}, {'X': 'melanie'}]),
]
def test(program, solved_problems):
@@ -87,10 +93,10 @@ def hint(program, solved_problems):
# gender testing is redundant
# this is not necessarily wrong, but worth mentioning anyway
targets = [prolog.util.Token('NAME', 'male'), prolog.util.Token('NAME', 'female')]
- pos = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
- if pos:
- # TODO: resolve how highlighting info is communicated
- return [{'id': 'gender_is_irrelevant', 'highlight': pos}]
+ marks = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
+ if marks:
+ return [{'id': 'gender_is_irrelevant_markup', 'start': m[0], 'end': m[1]} for m in marks] + \
+ [{'id': 'gender_is_irrelevant'}]
# precedence fail (AND block vs OR block)
# case in point: parent(PX, X), parent(PY, Y), brother(PX, PY) ; sister(PX, PY)
@@ -98,18 +104,18 @@ def hint(program, solved_problems):
# warning: knowledge base dependent
if prolog.util.Token('SEMI', ';') in tokens and prolog.engine.ask_truth(engine_id,
'findall(_, cousin(X, Y), L), (length(L, 14) ; length(L, 16))'):
- return [{'id', 'precedence_fail'}]
+ return [{'id': 'precedence_fail'}]
# cousin should not be brother or sister
# common parent, probably solved via grandparent
if prolog.engine.ask_truth(engine_id,
'cousin(X, Y), (brother(X, Y) ; sister(X, Y))'):
- return [{'id', 'cousin_vs_sibling'}]
+ return [{'id': 'cousin_vs_sibling'}]
# cousin to him/herself
# just common grandparent is not enough
if prolog.engine.ask_truth(engine_id, 'cousin(X, X)'):
- return [{'id', 'cousin_to_oneself'}]
+ return [{'id': 'cousin_to_oneself'}]
# X (or Y) does not necessarily need to be a parent
diff --git a/prolog/problems/family_relations/cousin_2/sl.py b/prolog/problems/family_relations/cousin_2/sl.py
index 7e3e7f0..7bd819a 100644
--- a/prolog/problems/family_relations/cousin_2/sl.py
+++ b/prolog/problems/family_relations/cousin_2/sl.py
@@ -13,23 +13,24 @@ description = '''\
plan = ['''\
Verjetno bi se sedaj splačalo uporabiti rešitev kakšne prejšnje naloge?
-
-
Loni naj zbriše imena relacij (parent, sister) s te slike!
-
Seveda se da rešiti tudi brez prejšnjih rešitev... MORE
-
-
Loni naj zbriše imena relacij (parent, sister) s te slike!
-''', '''\
-
+
+
Seveda se da rešiti tudi brez prejšnjih rešitev...
''', '''\
Če je PX starš od X in je
PY starš od Y ter sta
PX in PY brat ali sestra,
potem je X bratranec/sestrična od Y.
+''', '''\
+
''']
hint = {
'gender_is_irrelevant': '''\
Kako je lahko bratranec/sestrična hkrati tudi brat/sestra od Y?
Si morda pozabil, da starša od X in Y ne smeta biti ista oseba?
-
+
''',
'cousin_to_oneself': '''\
Kako je lahko nekdo bratranec/sestrična samemu sebi?
Imata morda X in Y istega starša?
-
+
''',
'cousin_need_not_be_parent': '''\
diff --git a/prolog/problems/family_relations/descendant_2/Prolog_descendant_01.svg b/prolog/problems/family_relations/descendant_2/Prolog_descendant_01.svg
new file mode 100644
index 0000000..a81be29
--- /dev/null
+++ b/prolog/problems/family_relations/descendant_2/Prolog_descendant_01.svg
@@ -0,0 +1,374 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/descendant_2/Prolog_descendant_02.svg b/prolog/problems/family_relations/descendant_2/Prolog_descendant_02.svg
new file mode 100644
index 0000000..210b4bc
--- /dev/null
+++ b/prolog/problems/family_relations/descendant_2/Prolog_descendant_02.svg
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/descendant_2/Prolog_descendant_03.svg b/prolog/problems/family_relations/descendant_2/Prolog_descendant_03.svg
new file mode 100644
index 0000000..ad5ed94
--- /dev/null
+++ b/prolog/problems/family_relations/descendant_2/Prolog_descendant_03.svg
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/descendant_2/Prolog_descendant_04.svg b/prolog/problems/family_relations/descendant_2/Prolog_descendant_04.svg
new file mode 100644
index 0000000..19f5b26
--- /dev/null
+++ b/prolog/problems/family_relations/descendant_2/Prolog_descendant_04.svg
@@ -0,0 +1,1090 @@
+
+
+
+
+
+
+
+
+
+
+]>
+
diff --git a/prolog/problems/family_relations/descendant_2/common.py b/prolog/problems/family_relations/descendant_2/common.py
index cfa1d37..49e7e5c 100644
--- a/prolog/problems/family_relations/descendant_2/common.py
+++ b/prolog/problems/family_relations/descendant_2/common.py
@@ -4,7 +4,7 @@ from operator import itemgetter
import socket
import prolog.engine
import prolog.util
-from server.hints import Hint, HintSequence
+from server.hints import Hint, HintPopup
import server.problems
id = 101
@@ -21,8 +21,10 @@ descendant(X, Y) :-
'''
hint_type = {
+ 'gender_is_irrelevant_markup': HintPopup('gender_is_irrelevant_markup'),
'gender_is_irrelevant': Hint('gender_is_irrelevant'),
'grandparent_used': Hint('grandparent_used'),
+ 'grandparent_used_markup': HintPopup('grandparent_used_markup'),
'base_case': Hint('base_case'),
'descendant_of_oneself': Hint('ancestor_to_oneself'),
'descendant_need_not_be_parent': Hint('descendant_need_not_be_parent'),
@@ -30,7 +32,12 @@ hint_type = {
}
test_cases = [
- # TODO
+ ('descendant(anna, X)',
+ [{'X': 'jerry'}, {'X': 'elaine'}, {'X': 'morty'}, {'X': 'helen'}]),
+ ('descendant(daniela, X)',
+ [{'X': 'nevia'}, {'X': 'aleksander'}, {'X': 'margaret'}, {'X': 'ana'}, {'X': 'aleksandr'}]),
+ ('descendant(X, william)',
+ [{'X': 'vanessa'}, {'X': 'patricia'}, {'X': 'susan'}, {'X': 'john'}, {'X': 'michael'}, {'X': 'michelle'}]),
]
def test(program, solved_problems):
@@ -75,29 +82,29 @@ def hint(program, solved_problems):
# gender testing is redundant
# this is not necessarily wrong, but worth mentioning anyway
targets = [prolog.util.Token('NAME', 'male'), prolog.util.Token('NAME', 'female')]
- pos = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
- if pos:
- # TODO: resolve how highlighting info is communicated
- return [{'id': 'gender_is_irrelevant', 'highlight': pos}]
+ marks = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
+ if marks:
+ return [{'id': 'gender_is_irrelevant_markup', 'start': m[0], 'end': m[1]} for m in marks] + \
+ [{'id': 'gender_is_irrelevant'}]
# grandparent is a sign of complications
# it's likely used instead of recursion
targets = [prolog.util.Token('NAME', 'grandparent')]
- pos = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
- if pos:
- # TODO: resolve how highlighting info is communicated
- return [{'id': 'grandparent_used', 'highlight': pos}]
+ marks = [(t.pos, t.pos + len(t.val)) for t in tokens if t in targets]
+ if marks:
+ return [{'id': 'grandparent_used_markup', 'start': m[0], 'end': m[1]} for m in marks] + \
+ [{'id': 'grandparent_used'}]
# missing/failed base case
# TODO: how will ask_truth handle/return timeouts...
# TODO: timeout is the same as fail in this particular case
if prolog.engine.ask_truth(engine_id,
'parent(Y, X), \+ descendant(X, Y)'):
- return [{'id', 'base_case'}]
+ return [{'id': 'base_case'}]
# descendant of oneself
if prolog.engine.ask_truth(engine_id, 'descendant(X, X)'):
- return [{'id', 'descendant_of_oneself'}]
+ return [{'id': 'descendant_of_oneself'}]
# X does not necessarily need to be a parent
if prolog.engine.ask_one(engine_id,
@@ -109,7 +116,7 @@ def hint(program, solved_problems):
if prolog.engine.ask_truth(engine_id,
'findall(_, descendant(william, X), L1), length(L1, 6), \
findall(_, descendant(X, william), L2), length(L2, 2)'):
- return [{'id', 'wrong_direction'}]
+ return [{'id': 'wrong_direction'}]
except socket.timeout as ex:
pass
diff --git a/prolog/problems/family_relations/descendant_2/sl.py b/prolog/problems/family_relations/descendant_2/sl.py
index 5e81d26..5f4a3ca 100644
--- a/prolog/problems/family_relations/descendant_2/sl.py
+++ b/prolog/problems/family_relations/descendant_2/sl.py
@@ -14,31 +14,38 @@ description = '''\
plan = ['''\
Brez rekurzije ne bo šlo... kako lahko problem prevedem na (en korak) manjši problem?
-
-
Loni naj zbriše imena relacij (parent, ancestor) s te slike!
-''', '''\
-
+
''', '''\
Če je nek Z starš od X in je
ta Z hkrati potomec od Y,
potem je tudi X potomec od Y.
+''', '''\
+
''']
hint = {
'gender_is_irrelevant': '''\
Je spol res pomemben?
+''',
+
+ 'gender_is_irrelevant_markup': '''\
+
Je to res potrebno?
''',
'grandparent_used': '''\
Rešitev z "grandparent" bo premalo splošna, poskusi nadomestiti to z rekurzijo.
Skratka, poskusi prevesti na "manjši" problem, npr. potomec v enem koraku manj
(en korak bližji potomec)...
+''',
+
+ 'grandparent_used_markup': '''\
+
Bi se dalo rešiti brez tega?
''',
'base_case': '''\
Si pomislil na robni pogoj? Kaj je najbolj enostaven par (potomec, prednik)?
-
-''',
+
+''', # TODO: morda ta hint naredim z "more": najprej tekst, ob kliku pa še slika... (sicer je preveč očitno)
'descendant_of_oneself': '''\
Kako je lahko nekdo potomec samega sebe?
@@ -51,12 +58,13 @@ Skratka, poskusi prevesti na "manjši" problem, npr. potomec v enem koraku manj
'wrong_direction': '''\
Si morda sprogramiral ravno obratno in zamenjal prednika s potomcem?
X naj bo potomec od Y in ne obratno!
-''',
+
+''', # TODO: Tim, kako bi lahko še query poslali med parametri v Hint dict? Je to predvideno? Tukaj bi recimo pasalo...
'interesting_tidbit': '''\
Zanimivost: nalogo bi lahko rešil tudi z uporabo rešitve za relacijo "ancestor".
Samo obrni spremenljivki X in Y;
če je X potomec od Y, potem je Y prednik od X.
Če je X starš od starša od Y,
potem je X stari starš od Y.
+''', '''\
+
''']
hint = {
diff --git a/prolog/problems/family_relations/sister_2/common.py b/prolog/problems/family_relations/sister_2/common.py
index 627648c..c112a9c 100644
--- a/prolog/problems/family_relations/sister_2/common.py
+++ b/prolog/problems/family_relations/sister_2/common.py
@@ -23,8 +23,9 @@ sister(X, Y) :-
hint_type = {
'x_must_be_female': Hint('x_must_be_female'),
'common_parent_needed': Hint('common_parent_needed'),
- 'y_can_be_of_any_gender': Hint('Y_can_be_of_any_gender'),
+ 'y_can_be_of_any_gender': Hint('y_can_be_of_any_gender'),
'x_y_must_be_different': Hint('x_y_must_be_different'),
+ 'neq_used_too_early': Hint('neq_used_too_early'),
}
test_cases = [
@@ -121,10 +122,17 @@ def hint(program, solved_problems):
# X and Y must be different
# this is the last code-specific hint (when everything else doesn't trigger anymore)
- if prolog.engine.ask_truth(engine_id,
+ if prolog.util.Token('NEQ', '\==') not in tokens and prolog.engine.ask_truth(engine_id,
'setof(X, (member(X, [sally, nevia, vanessa]), sister(X, X)), L), length(L, 3)'):
return [{'id': 'x_y_must_be_different'}]
+ # X and Y must be different, but the user used '\=='
+ # most likely this means that \== was used before X and Y are known
+ # this is the last code-specific hint (when everything else doesn't trigger anymore)
+ if prolog.util.Token('NEQ', '\==') in tokens and prolog.engine.ask_truth(engine_id,
+ 'setof(X/Y, sister(X, Y), L), member(nevia/nevia, L), member(sally/sally, L), member(vanessa/vanessa, L)'):
+ return [{'id': 'neq_used_too_early'}]
+
# last hints are connected with programming style
# here, this means detecting such code:
# parent(P1, X), parent(P2, Y), P1 == P2 (or P1 = P2)
diff --git a/prolog/problems/family_relations/sister_2/sl.py b/prolog/problems/family_relations/sister_2/sl.py
index d69b56c..cb51592 100644
--- a/prolog/problems/family_relations/sister_2/sl.py
+++ b/prolog/problems/family_relations/sister_2/sl.py
@@ -21,14 +21,16 @@ potem je X sestra od Y.''',
]
hint = {
- 'x_y_must_be_different': '''\
+ 'x_y_must_be_different': [{'message': '''\
Si pomislil, da sta X in Y lahko ista oseba? Poskusi naslednjo poizvedbo:
?- sister(sally, Y).
-
-
VEČ... Kako naredim, da sta X in Y različna?
-''',
+''', 'linkText': 'Kako lahko preverim, da sta X in Y različna?'},
+'''\
+
S pomočjo operatorja \== lahko preverim, da sta X in Y med seboj različna.
+Na primer: X \== Y
+'''],
'x_must_be_female': '''\
@@ -43,4 +45,13 @@ hint = {
Dobro bi bilo, da imata X in Y vsaj enega skupnega starša.
''',
+
+ 'neq_used_too_early': '''\
+
Si morda uporabil operator \== prezgodaj?
+
Poskusi ga pomakniti bolj proti koncu. Razlog za probleme je verjetno,
+da spremenljivki, ki ju primerjaš, še nimata določene vrednosti in sta zato različni.
+Prolog ne preverja, če kasneje morda postaneta enaki, ampak samo kakšni sta v trenutku,
+ko naleti na primerjavo.