我是 Prolog 的新手,我对一段代码有一些可能很简单的问题。这是上周五出现的现实世界问题,相信我这不是 CS 作业。

我们想打印名片,而这些名片只能打印 900 张卡片(100 张,每张 9 张)。任何人的卡片都不应该分布在几个块上。人们订购了不同数量的卡片,例如:

% "braucht" is german and means "needs"
braucht(anton,400).
braucht(berta,200).
braucht(claudia,400).
braucht(dorothee,100).
braucht(edgar,200).
braucht(frank,400).
braucht(georg,100).

我将以下定义放在一起以找到合适的 900 张名片块:
block(0,[]).
block(N,[H|T]) :-
    braucht(H,Nh),
%   \+(member(H,T)),
    D is N - Nh,
    D >= 0,
    block(D,T).

这会生成一个很好的人块列表,这些人的卡片可以放在 900 张卡片块上。但是如果我激活注释行“\+member....”并且只给我一个“false”,它就会停止工作。但我需要确保没有人在那个街区得到超过一次。我在这里做错了什么?

最佳答案

看来你要实现的是设置一个约束,使得H不会出现在列表的尾部T中。但是,当您调用 T 时, member/2 仍然未绑定(bind),因此 member(H, T) 将成功,因此 \+ member(H,T) 将失败。

如果您不想使用约束编程,而是使用纯 Prolog,您应该使用另一个方向的检查,并检查 H 是否已经存在于已聚合到该点的人员列表中。就像是:

block(0, List, List).
block(N, Rest, List) :-
  braucht(H, Nh),
  \+(memberchk(H, Rest)), % will fail when H is already in Rest
  D is N-Nh,
  D >= 0,
  block(D, [H|Rest], List).

谓词 block/3 可以从谓词 block/2 调用:
block(N, List) :-
  block(N, [], List).

关于prolog - 打印名片 - 一种背包任务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8779115/

10-11 18:12