在课堂上,我们讲解了我的老师给出的subset_of/2谓词,如下所示:
subset_of([],[]).
subset_of([X|Xs],Zs):-subset_of(Xs,Ys),maybe_add(X,Ys,Zs).
maybe_add(_,Ys,Ys).
maybe_add(X,Ys,[X|Ys]).
subsets_of(Xs,Xss):-findall(Ys,subset_of(Xs,Ys),Xss).
他随后要求我们将其更改为仅提供某个长度为K的子集(但不使用长度/2,而是通过直接找到递归定义来实现)。我的第一次尝试是将subset_of调用分成一个添加额外元素的函数和一个不添加的函数(而不是使用maybe_add调用),并跟踪传递的列表的长度,并在最后进行检查,但这根本没有按计划工作。
subset_of(K, 0, [],[]).
subset_of(K, Len, [X|Xs],Zs):-
L1 is Len - 1,
subset_of(K, L1, Xs, Zs),
L1 == K.
subset_of(K, Len, [X|Xs],Zs):-
L1 is Len - 1,
subset_of(K, L1, Xs,Ys),
do_add(X, Ys, Zs),
Len == K.
subsets_of(K,Xs,Xss):-
length(Xs, Len),
findall(Ys,subset_of(K, Len, Xs,Ys),Xss).
我并不是要求正确的代码来解决这个问题,只是希望得到正确方向的指引,以便继续尝试解决它。这是我第一次接触声明式语言,感到非常困惑。
ksubset_of(0, _, []). ksubset_of(K, [X|Xs], Zs) :- K1 is K - 1, ksubset_of(K1, Xs, Ys), Zs = [X|Ys].
但这只生成了第一个,所以我不知道该怎么做。 - StuartZs = [X | Ys]
。你应该将所有的Zs
替换为它的实际值。这不仅更清晰,而且更有效率。 - julxksubset_of(0, [], [])。 ksubset_of(K, [X|Xs], [X|Ys]) :- K1 is K - 1, ksubset_of(K1, Xs, Ys)。 ksubset_of(K, [X|Xs], Ys) :- ksubset_of(K, Xs, Ys)
看起来正好按照预期工作。你说的第一条规则也会导致重复,所以我不得不进行了更改。感谢您的帮助,julkiewicz,我非常感激。 - Stuart