我正在尝试编写一个函数,它将生成通过删除1或2个元素形成的列表元素的组合,包括拆分列表。
例如:
[b,b,b]
可能会成为
[b,b]
[b]
[[b],[b]]
我可以使用以下谓词生成前两个:
permute([_|T],T).
permute([_|[_|T]],T).
但第三个证明更难。我可以使用append
将列表分成两部分,但我不知道如何将其与我已有的部分相结合。
我正在使用SWI-Prolog。
(虽然标记为家庭作业,但这是较大任务的一部分,而且我现在处于困境中)
答案 0 :(得分:2)
以Kayles的游戏作为我们的应用程序表明,状态的经济表示将是正整数的有序列表,每个数字代表连续的瓶子串。
我说有序,因为游戏的状态在这些值的任何排列下都是等价的。
因此,可能的移动包括选择一个条目并将其减少一个或两个为零,一个或两个较小的条目。然后,这些较小的条目(如果有的话)应插入游戏状态列表的新“尾部”中的适当位置。
用于游戏移动的更大表示的构建块是决定连续X串瓶子的减少方式。所以我们可以从这个要求开始:
bowls(X,[ ]) :-
( 0 is X - 1 ; 0 is X-2 ).
bowls(X,[W]) :-
( W is X - 1 ; W is X-2 ),
W > 0.
bowls(X,[Y,Z]) :-
( W is X - 1 ; W is X-2 ),
W > 1,
bowlsplits(W,Y,Z).
由读者实施 bowlsplits / 3 ,以便Y + Z = W
与Y >= Z > 0
产生所有可能性。
请注意,通过这样的表示,我们应该通过跳过与列表中的以下条目相等的任何条目来避免重复结果,因为两个相等的条目会产生相同的可能结果。
kayles([X],R) :- bowls(X,R).
kayles([X,Y|T],R) :-
X > Y,
bowls(X,L),
inSort(L,[Y|T],R).
kayles([X,X|T],[X|L]) :-
kayles([X|T],L).
还可以让读者按照插入排序的方式实现 inSort / 3 ,该排序将前两个参数中的有序列表合并为有序列表以绑定第三个参数。 / p>
请注意, kayles / 2 是尾递归的,但不确定。
答案 1 :(得分:1)
谓词
permute([_|T],T).
permute([_|[_|T]],T).
更恰当地命名为tail_or_tail_of_tail
。您是否注意到它只能删除第一个或前两个元素?如果你想取出任何两个元素,请使用类似
take_out_one_or_two(L, R) :- select(_, L, R).
take_out_one_or_two(L, R) :- select(_, L, L1), select(_, L1, R).
您可以使用append/3
进行拆分。
strange_predicate(L, R) :- take_out_one_or_two(L, R).
strange_predicate(L, [X,Y]) :- take_out_one_or_two(L, L1), append(X, Y, L1).
如果您不希望结果中出现空列表,请将第二个句子替换为
strange_predicate(L, [X,Y]) :-
take_out_one_or_two(L, L1),
X = [_|_],
Y = [_|_],
append(X, Y, L1).
(如果没有用例,我真的想不出这个谓词的名称。)