我有一个序言功课要做:有5人坐在不同国籍(法语,英语,波兰语,意大利语,土耳其语)的圆桌会议。 他们每个人只知道一个自己以外的其他语言。 他们以这样的方式,每个人可以有自己的邻居2交谈(与他们自己的母语,并与其他在他们知道单一外语交谈一个邻居)坐在圆桌。 在英语的人都知道意大利,波兰人都知道法国,土耳其的人不知道英语。 现在的问题是外语没有土耳其人知道吗?
我已经做了一些仅使用条款和谓词,但我走入了死胡同,老师建议最简单的方法是使用列表。
什么该列表将包含或根本有什么想法的任何代码的想法?
UPDATE(弱逻辑代码):
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).
更新 - 编程环境:涡轮序言2.0 '86,'88由Borland,也是我在序言中一个完整的beginer,所以...我想apreciate至少程序和代码体之外的解释的全部草图。 我处理事情慢:d
您可以使用循环列表,可尝试此代码来了解。
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, _).
通常情况下,我会解决这样使用约束一个谜,不过那可能会是你的功课太先进。 因此,而不是使用约束来限制搜索空间,我们不得不使用测试,以检验其是否可行。
您将需要两个列表来上班,说People
和Languages
。 列表的每个元素对应于在该表一个座椅。 两个列表可具有相同的结构域, [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
。 这是为了排除symmterical解决方案,否则将被退回,因为该表是圆的。 如果没有此限制,每个解决方案将有另外四个对称的解决方案。
试着拿出自己的解决方案阅读之前... :-)
该列表People
第一次实例。 我们需要的是每个元素只出现一次的照顾:
people([], []) :- !.
people([P|RestP], Domain) :-
delete(P, Domain, RestD),
people(RestP, RestD).
您的Prolog的方言可能有select/3
,而不是delete/3
。
当实例列表中Languages
,我们也检查拼图约束不违反:
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)
一般来说,造型的问题时,找出一个紧凑表示,消除不相关的细节是非常重要的。 这里有,比如, 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
始终限制为单个值...