2. Island of Logic
Submit solution
Prolog
Points:
10
Time limit:
60.0s
Memory limit:
64M
Author:
Problem type
Allowed languages
有一座邏輯之島,島上有五個生物(a, b, c, d, e),他們可能是有三種物種,分別為,神(divine)、惡魔(evil)、人類(human)。神永遠說實話、惡魔終年說謊,人類早上說實話晚上說謊。
到這座島上的邏輯學家透過他們之間的對話能夠得到一些推論,請透過推論回答問題。
Input
一段對話和一段問題,之間使用一個「-」分隔
有幾種可能的 predicate:
- say(X, Y, Z).: X 說 Y 為 Z 物種
- say(X, Y, \+Z).: X 說 Y 不為 Z 物種
- say(X, Y, lying).: X 說 Y 說謊
- say(X, Y, \+lying).: X 說 Y 沒有說謊
- say(X, day).: X 說現在為白天
- say(X, night).: X 說現在為晚上
-
而可能的 query 為:
- divine(X).: X 為神
- evil(X).: X 為惡魔
- human(X).: X 為人類
- day.: 現在是白天
- night.: 現在是晚上
Output
Qurey 的回答(yes/no)
Sample Input1
say(a, b, human).
say(a, b, evil).
say(b, a, human).
say(c, a, \+lying).
say(b, c, \+human).
say(d, e, \+lying).
-
human(a).
evil(a).
evil(b).
divine(b).
day.
Sample Output1
yes
no
no
yes
no
Sample Input2
say(a, a, human).
say(b, b, human).
say(a, b, lying).
-
human(a).
human(b).
day.
evil(b).
divine(a).
Sample Output2
no
no
yes
no
no
Sample Input3
say(a, a, lying).
-
day.
Sample Output3
no
Sample Input4
say(a, b, lying).
say(b, a, human).
-
human(d).
Sample Output4
no
輸入範例
:- initialization main, halt.
:- dynamic say/3.
:- dynamic say/2.
:- dynamic divine/1.
:- dynamic evil/1.
:- dynamic human/1.
:- dynamic day/0.
:- dynamic night/0.
read_predicates([H|T]) :-
read_line_to_codes(user_input, H),
string_codes(Input, H),
( Input = "-"
-> process,
read_queries(T)
; term_string(Term, Input),
assert(Term), % 將 Term assert 進 KB
read_predicates(T)).
read_predicates([]).
read_queries([H|T]) :-
read_line_to_codes(user_input, H),
H \= end_of_file,
string_codes(Input, H),
term_string(Query, Input),
query(Query),
read_queries(T).
read_queries([]).
query(Q) :-
(Q -> writeln(yes) ; writeln(no)).
process:-
forall((member(A, [divine, evil, human]), member(B, [divine, evil, human]), member(C, [divine, evil, human]), member(D, [divine, evil, human]), member(E, [divine, evil, human]), member(Day, [day, night])),
( Creatures = [a, b, c, d, e], Species = [A, B, C, D, E],
test(a, A, Day, Creatures, Species), test(b, B, Day, Creatures, Species),
test(c, C, Day, Creatures, Species), test(d, D, Day, Creatures, Species),
test(e, E, Day, Creatures, Species)
-> insert(Creatures, Species), assert(Day)
; true)),
% 這裡還需要寫
test(Creature, Species, Day, CreatureList, SpeciesList) :-
% 這裡還需要寫
insert([], []).
insert([HofC|TofC], [HofS|TofS]) :-
atomic_list_concat([HofS, "(", HofC, ")"], Fact),
term_to_atom(Term, Fact),
assert(Term),
insert(TofC, TofS).
main :-
read_predicates(X).
注意事項
- 繳交期限:2021-05-28 Fri. 23:59
- 輸入範例無法直接執行,還有其它地方需要寫
參考答案
:- initialization main.%, halt.
:- dynamic say/2.
:- dynamic say/3.
:- dynamic divine/1.
:- dynamic evil/1.
:- dynamic human/1.
:- dynamic day/0.
:- dynamic night/0.
read_predicates([H|T]) :-
read_line_to_codes(user_input, H),
string_codes(Input, H),
% writeln(Input),
( Input = "-"
-> process,
read_queries(T)
; term_string(Term, Input),
assert(Term),
read_predicates(T)).
read_predicates([]).
read_queries([H|T]) :-
read_line_to_codes(user_input, H),
H \= end_of_file,
string_codes(Input, H),
term_string(Term, Input),
query(Term),
read_queries(T).
read_queries([]).
query(Q) :-
(Q -> writeln(yes) ; writeln(no)).
process:-
forall((member(A, [divine, evil, human]), member(B, [divine, evil, human]), member(C, [divine, evil, human]), member(D, [divine, evil, human]), member(E, [divine, evil, human]), member(Day, [day, night])),
( Creatures = [a, b, c, d, e], Species = [A, B, C, D, E], % writeln(Species),
test(a, A, Day, Creatures, Species), test(b, B, Day, Creatures, Species),
test(c, C, Day, Creatures, Species), test(d, D, Day, Creatures, Species),
test(e, E, Day, Creatures, Species)
-> insert(Creatures, Species), assert(Day) % , writeln(Species|Day)
; true)),
forall(member(Creature, [a, b, c, d, e]),
( \+check(Creature)
-> retractall(divine(Creature)), retractall(evil(Creature)), retractall(human(Creature))
; true)),
( \+(day xor night)
-> retractall(day), retractall(night)
; true).
test(Creature, Species, Day, CreatureList, SpeciesList) :-
Species = divine,
( Day = day
-> \+say(Creature, \+day), \+say(Creature, night)
; \+say(Creature, day), \+say(Creature, \+night)),
fact(Creature, Day, CreatureList, SpeciesList).
test(Creature, Species, Day, CreatureList, SpeciesList) :-
Species = evil,
( Day = day
-> \+say(Creature, day), \+say(Creature, \+night)
; \+say(Creature, \+day), \+say(Creature, night)),
lie(Creature, Day, CreatureList, SpeciesList).
test(Creature, Species, Day, CreatureList, SpeciesList) :-
Species = human, \+say(Creature, \+day), \+say(Creature, night),
( Day = day
-> fact(Creature, Day, CreatureList, SpeciesList)
; lie(Creature, Day, CreatureList, SpeciesList)).
% Speaker will not lie.
fact(S, D, [], []).
fact(Speaker, Day, [HofC|TofC], [HofS|TofS]) :-
( HofS = divine
-> \+say(Speaker, HofC, \+divine), \+say(Speaker, HofC, evil), \+say(Speaker, HofC, human), \+say(Speaker, HofC, lying)
; true),
( HofS = evil
-> \+say(Speaker, HofC, divine), \+say(Speaker, HofC, \+evil), \+say(Speaker, HofC, human), \+say(Speaker, HofC, \+lying)
; true),
( HofS = human, Day = day
-> \+say(Speaker, HofC, divine), \+say(Speaker, HofC, evil), \+say(Speaker, HofC, \+human), \+say(Speaker, HofC, lying)
; true),
( HofS = human, Day = night
-> \+say(Speaker, HofC, divine), \+say(Speaker, HofC, evil), \+say(Speaker, HofC, \+human), \+say(Speaker, HofC, \+lying)
; true),
fact(Speaker, Day, TofC, TofS).
% Speaker will not tell truth.
lie(S, D, [], []).
lie(Speaker, Day, [HofC|TofC], [HofS|TofS]) :-
( HofS = divine
-> \+say(Speaker, HofC, divine), \+say(Speaker, HofC, \+evil), \+say(Speaker, HofC, \+human), \+say(Speaker, HofC, \+lying)
; true),
( HofS = evil
-> \+say(Speaker, HofC, \+divine), \+say(Speaker, HofC, evil), \+say(Speaker, HofC, \+human), \+say(Speaker, HofC, lying)
; true),
( HofS = human, Day = day
-> \+say(Speaker, HofC, \+divine), \+say(Speaker, HofC, \+evil), \+say(Speaker, HofC, human), \+say(Speaker, HofC, \+lying)
; true),
( HofS = human, Day = night
-> \+say(Speaker, HofC, \+divine), \+say(Speaker, HofC, \+evil), \+say(Speaker, HofC, human), \+say(Speaker, HofC, lying)
; true),
lie(Speaker, Day, TofC, TofS).
insert([], []).
insert([HofC|TofC], [HofS|TofS]) :-
atomic_list_concat([HofS, "(", HofC, ")"], Fact),
% writeln(Fact),
term_to_atom(Term, Fact),
assert(Term),
insert(TofC, TofS).
and(A, B) :- A, B.
and(A, B, C) :- A, B, C.
or(A, B) :- A.
or(A, B) :- B.
xor(A, B) :-
or(A, B), \+and(A, B).
check(Creature) :-
divine(Creature), \+evil(Creature), \+human(Creature).
check(Creature) :-
\+divine(Creature), evil(Creature), \+human(Creature).
check(Creature) :-
\+divine(Creature), \+evil(Creature), human(Creature).
main :-
read_predicates(X).
Comments