1

我有一个序幕作业要做:有 5 个人坐在一张来自不同国籍(法语、英语、波兰语、意大利语、土耳其语)的圆桌旁。除了自己的语言,他们每个人都只知道另一种语言。他们坐在圆桌旁,每个人都可以与他们的 2 个邻居交谈(一个邻居用他们的母语交谈,另一个用他们知道的单一外语交谈)。英国人会意大利语,波兰人会法语,土耳其人不会英语。问题是土耳其人懂什么外语?

我只使用子句和谓词做了一些事情,但我走到了死胡同,老师建议最简单的方法是使用列表。

关于该列表将包含什么或任何代码想法的任何想法?

更新(弱逻辑代码):

    predicates
knowTheLanguage(symbol,symbol)  
knowNotTheLanguage(symbol,symbol)
isNeighbor(symbol,symbol,symbol,symbol)

aTheory(symbol,symbol,symbol,symbol) 
anotherTheory(symbol,symbol,symbol,symbol)

    clauses
knowTheLanguage(englishman,italian).
knowTheLanguage(polishman,franch).

%native tongues
knowTheLanguage(englishman,english).
knowTheLanguage(frenchman,franch).
knowTheLanguage(polishman,polish).
knowTheLanguage(italianman,italian).
knowTheLanguage(turk,turkish).


knowNotTheLanguage(turk,english).

aTheory(centralPerson, languageCntrlPers, personOnOneSide,languagePrsnOnOneSide) if knowTheLanguage(personOnOneSide,languageCntrlPers)
                                                                            and not( knowTheLanguage(centralPerson,languagePrsnOnOneSide))
                                                                            and not(knowNotTheLanguage(centralPerson,languagePrsnOnOneSide)).
anotherTheory(centralPerson, languageCntrlPers, personOnOneSide,languagePrsnOnOneSide) if knowTheLanguage(centralPerson,languagePrsnOnOneSide) 
                                                                            and  not( knowTheLanguage(personOnOneSide,languageCntrlPers))
                                                                            and not(knowNotTheLanguage(centralPerson,languagePrsnOnOneSide)).

isNeighbor(centralPerson, languageCntrlPers, personOnOneSide,languagePrsnOnOneSide) if aTheory(centralPerson, languageCntrlPers, personOnOneSide,languagePrsnOnOneSide)
                                                                        or
                                                                        anotherTheory(centralPerson, languageCntrlPers, personOnOneSide,languagePrsnOnOneSide).

更新 - 编程环境:Borland 的 turbo prolog 2.0 '86,'88,我也是 prolog 的完整初学者,所以......我至少要了解代码体之外的程序和解释的完整草图。我处理事情很慢:D

4

3 回答 3

1

你可以使用循环列表,试试这个代码来理解。

t :-
    L = [1,2,3 | L],
    my_write(5, L).

my_write(0, _).
my_write(N, [H | T]) :-
    write(H), nl,
    N1 is N - 1,
    my_write(N1, T).

循环列表可能对您非常有用。

描述列表的元素是什么,然后语言的约束是什么

编辑:这是我的解决方案,适用于 SWI-Prolog:

% @arg1 : list of nationalities around the table
% @arg2 : list of persons
dinner(Languages, Table) :-
    length(Languages, Len),
    length(Table, Len),

    % set Natianalities and languages
    init_1(Table, Languages, Languages),

    % create cyclic list
    % works with SWI-Prolog
    append(Table, L, L),

    % set languages constraint
    init_2(Len, L).

init_1([], [], []).

init_1([person(N, L) | T], Nations, Languages):-
    select(N, Nations, New_Nations),

    % problem specific
    (   N = english
    ->  L = italian
    ;   N = polish
    ->  L = french
    ;   true),

    select(L, Languages, New_Languages),

    % problem specific
    (   N = turkish
    ->  L \=  english
    ;   true),

    init_1(T, New_Nations, New_Languages).

% persons speaks with theirs two neighbors
init_2(Tr, [person(_N1, L1), person(N2, L2), person(N3, L3) | T]) :-
    Tr > 0,
    member(N2, [L1, L3]),
    Tr1 is Tr - 1,
    init_2(Tr1, [person(N2, L2), person(N3, L3) | T]).

init_2(0, _).
于 2012-11-09T11:10:36.883 回答
0

通常,在对问题建模时,重要的是要确定一个紧凑的表示,消除不相关的细节。例如,这里有,polishman并且polish是无用的。我们可以同意,它polish代表人语言。

我草拟解决方案,请填写省略号,添加约束:

puzzle(L) :-
    L = [P1,P2,P3,P4,P5],
    cadj(P5,P1,P2),
    ...
    member(p(english, italian), L),
    member(p(french,  _ ),      L),
    ...
    \+ member(p(turk, english), L).

% constrain adjacents
cadj(p(Pl, Ll), p(P, K), p(Pr, Lr)) :-
    P = Ll, K = Pr ; P = Lr, K = Pl.

p/2 代表他知道的人和语言。cadj/3 说如果左边的人知道我的语言,我必须知道右边的人的语言,反之亦然。

要获得所需的语言,请尝试

puzzle :-
    puzzle(L),
    memberchk(p(turk, T), L),
    writeln(T:L).

有更多的解决方案,但语言T始终被限制在一个单一的价值......

于 2012-11-09T18:13:56.017 回答
0

通常,我会使用约束来解决这样的难题,但这对于您的作业来说可能太高级了。因此,我们必须使用测试来检查解决方案是否可行,而不是使用约束来限制搜索空间。

您将需要使用两个列表,例如PeopleLanguages。列表中的每个元素对应于餐桌上的一个座位。两个列表可以具有相同的域,[f,e,p,i,t]. 域的语义应该是清晰的。

要生成解决方案,首先设置列表,然后实例化列表并检查实例化是否满足您的约束:

puzzle(People, Languages) :-
    Domain = [f,e,p,i,t],
    length(People, 5),
    length(Languages, 5),
    % symmetry break:
    People = [f|_],
    % instantiate People
    people(People, Domain),
    % instantiate languages and check constraints
    languages(Languages, People, Domain).

请注意,列表的第一个元素People设置为f。这是为了排除对称解决方案,否则将返回,因为桌子是圆形的。如果没有这个限制,每个解决方案将有四个额外的对称解决方案。

在继续阅读之前尝试提出自己的解决方案...... :-)

该列表People首先被实例化。我们需要注意每个元素只出现一次:

people([], []) :- !.
people([P|RestP], Domain) :-
    delete(P, Domain, RestD),
    people(RestP, RestD).

你的 Prolog 方言可能有select/3而不是delete/3.

实例化 listLanguages时,我们还检查是否违反了拼图约束:

languages(Languages, People, Domain) :-
    Term =.. [[]|People],
    languages0(Languages, People, Term, 1, Domain).
languages0([], _, _, _, _) :- !.
languages0([L|RestL], [P|RestP], Term, I, Domain) :-
    delete(L, Domain, RestD),
    L \= P, % language needs to be foreign
    check_l(P, L),
    check_n(L, I, Term),
    I1 is I+1,
    languages0(RestL, RestP, Term, I1, RestD).

同样,每个元素只能出现一次。

check_l检查有关外语的限制:

check_l(e, i).
check_l(p, f).
check_l(t, L) :- L \= e.
check_l(f, _).
check_l(i, _).

check_n确保左邻或右邻的语言和国籍匹配:

check_n(L, I, Term) :-
    ( I == 1 -> NL = 5 ; NL is I-1 ),
    ( I == 5 -> NR = 1 ; NR is I+1 ),
    ( arg(NL, Term, L) ; arg(NR, Term, L) ).

有两种解决方案:

?- puzzle(P, L).
P = [f, e, i, t, p]
L = [e, i, t, p, f]
Yes (0.00s cpu, solution 1, maybe more)
P = [f, p, t, i, e]
L = [e, f, p, t, i]
Yes (0.01s cpu, solution 2, maybe more)
No (0.01s cpu)
于 2012-11-09T15:02:33.557 回答