2. Island of Logic


Submit solution

Points: 10
Time limit: 60.0s
Memory limit: 64M

Author:
Problem type
Allowed languages
Prolog

有一座邏輯之島,島上有五個生物(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).


注意事項


  1. 繳交期限:2021-05-28 Fri. 23:59
  2. 輸入範例無法直接執行,還有其它地方需要寫


參考答案


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

There are no comments at the moment.