我花时间正确翻译了
四个人在你面前:一个男魔术师,一个女魔术师,一个巫师和一个女巫。每个人都有一个或多个硬币的袋子。
硬币由青铜,铜,黄铜或锡制成。
哪个袋子包含最少的硬币?
鉴于:
1 - 没有两个相同内容的袋子
2 - 在一个袋子里,不能有两个相同的硬币
3 - 一个袋子可以包含一个,两个或四个硬币
4 - 巫师和男魔术师各有一枚硬币,其他三只都没有
5 - 所有没有黄铜硬币的袋子都含有青铜币
6 - 所有没有锡币的袋子也不含青铜币
使用深度优先搜索创建Prolog程序以找到解决此问题的解决方案
我不知道从哪里开始
coin(bronze).
coin(copper).
coin(brass).
coin(tin).
% 5: All bags without a brass coin contain a bronze coin.
hint_1(B) :- \+ \+ ( memberchk(brass, B) ; memberchk(bronze, B) ).
% 6: All bags without tin coins do not contain a bronze coin either.
hint_2(B) :- \+ ( \+ memberchk(tin, B), memberchk(bronze, B) ).
unique_coin(Us, Bags) :-
member(U, Us),
\+ (member(Bag, Bags), memberchk(U, Bag)).
bag(Cs) :-
% 3: A bag can contain either one, two or four coins
member(L, [1,2,4]), length(Cs, L),
% 2: In a bag, there cannot be two of the same coins.
foldl(ascending_coin, Cs, _, _).
ascending_coin(C, Prev, C) :-
coin(C),
Prev @< C..
%All bags are different
all_dif([]).
all_dif([L|Ls]) :-
maplist(dif(L), Ls),
all_dif(Ls).
bags(Bs) :-
Bs = [MM,FM,Wizard,Witch],
maplist(bag, Bs),
% 1: There are no two bags of identical content
all_dif(Bs),
% 4: The Wizard and the male magician each have a unique coin.
unique_coin(Wizard, [MM,FM,Witch]),
unique_coin(MM, [FM,Wizard,Witch]),
maplist(hint_1, Bs),
maplist(hint_2, Bs).
答案 0 :(得分:1)
这是我尝试解决方案。它似乎有用,但我对这些谜题的练习并不是很好。使用#n
的评论表明该行上的代码旨在解决您拼图中的规则n。
编辑:我已经更新了我的代码,以便从您的代码中加入两个更好的创意:
not_member/2
,因此我可以maplist
检查其他列表中的唯一项目。这是普遍性和unique_coin/2
之间的折衷。虽然您的unique_coin/2
可能只是更好的选择。bag_with_fewest_coins(Answers) :-
Bags = [A, B, C, D], % there are four bags...
maplist(coin_bag, Bags), % ... of coins
is_set(Bags), % #1
member(MemA, A), maplist(not_member(MemA), [B,C,D]), % #4
member(MemB, B), maplist(not_member(MemB), [A,C,D]), % #4
predsort(compare_lengths, Bags, [Answer|_]). % Answer is shortest list.
not_member(X, Ys) :-
\+ member(X, Ys).
%% To be used with predsort/3:
compare_lengths(Comp, A, B) :-
length(A, LenA), length(B, LenB),
compare(Comp, LenA, LenB). % Per @mat's suggestion in comments.
coin_bag(Bag) :-
Coins = [bronze, copper, brass, tin], % types of coins
member(Len, [1,2,4]), length(Bag, Len), % #3
set_subset(Coins, Bag), % #2
(member(brass, Bag) ; member(bronze, Bag)), % #5
(member(tin, Bag) ; \+ member(bronze, Bag)). % #6
% Taken form gusbro's SO answer: http://stackoverflow.com/a/4917016/1187277
% For the purposes of this predicate, each element of Set is thought of as
% distinct, qua differentiable entity, regardless of whether it would unify,
% equate with, or otherwise match another element in Set.
set_subset([], []).
set_subset([X|Set], [X|Subset]) :-
set_subset(Set, Subset).
set_subset([_|Set], Subset) :-
set_subset(Set, Subset).
然后,根据@ mat在评论中的建议,我们可以使用set_of/3
来确保我们收集所有不同的答案:
?- setof(B, bag_with_fewest_coins(B), Answers).
Answers = [[brass]].
这表明只有一个独特的答案。
这些提示与之前版本的问题有关。我离开了他们以防将来对某人有帮助:
对规则和事实使用非常具有描述性的名称会很有帮助。 rule
没有帮助,因为它告诉我们什么样的规则我们没有描述。在Prolog中,<head> :- <body>.
形式的任何内容都是规则,因此我们知道某些内容是基于其语法的规则。这使我们能够将我们的规则命名为描述性内容,例如bag_contents
。
你的一些规则对我来说没有多大意义,我认为这是因为你有点误解了Prolog中的表达方式。所以这里有一些关于你的规则的指示:
我希望你的意思是说这个规则是“M2是列表的第一个元素,它是一个长度为2的列表,或者是一个长度为4的列表”:
rule(M2,[M2|_]):- length(M2,X), X=2; X = 4.
但它实际上说“M2的长度为X,X = 2,或者X = 4”,这是因为;/2
运算符的优先级大于,/2
运算符的优先级。因此,您需要使用括号以正确的方式对表达式进行分组,如:length(M2,X), (X=2; X = 4)
。
这条规则的第二个分支永远不会成功:
rule([A|B]):- length(A,Y), Y= 1; Y = 2, Y=4, rule(B).
因为第二部分(在;
之后)读取“Y = 2且Y = 4且规则(B)”,但如果Y = 2
则为\+ Y = 4
,那么它将永远失败。
因此,我对进一步进展的建议是为您的规则提供描述性的,不同的名称,纠正某些条款中的错误逻辑,并尝试设置可以在最高级别测试规则的情况。
答案 1 :(得分:-1)
尝试http://swish.swi-prolog.org/这会有效..可能有一些问题SWI-Prolog桌面版。桌面veriosn无法检查memberchek和foldl函数的构建。希望这有帮助