到目前为止,我能想出的最好的事情就是这个功能:
numberFromList([X], X) :- digit(X), !. numberFromList(List, N) :- member(X, List), delete(List, X, LX), numberFromList(LX, NX), N is NX * 10 + X.
其中digit/1
是验证原子是否为十进制数的函数。
numberFromList(List, N)
找到可以使用List
中所有数字形成的所有数字。
例如。 [2, 3] -> 23, 32
。
但我想得到这个结果:[2, 3] -> 2, 3, 23, 32
我花了很多时间考虑这个问题,我怀疑你可能会在某些时候使用像append(L, _, List)
这样的东西来获得更短的列表。
我很感激任何贡献。
答案 0 :(得分:0)
谓词unique/3
生成长度最多为MaxLen
的所有列表,其中包含来自Symbols
的符号。生成的列表一次只存储在L
中。
unique(MaxLen, Symbols, L) :-
between(0, MaxLen, Len),
length(L, Len),
unique(Symbols, L).
用于生成列表的辅助谓词。
unique(_, []).
unique(Set, [H|R]) :-
select(H, Set, ReducedSet),
unique(ReducedSet, R).
用于演示上述谓词的简单程序:
main :-
unique(5, [2,3], L),
write(L), nl, fail.
答案 1 :(得分:0)
这是一种方法,使用适用于atomic_list_concat/2
,atom_number/2
和select/3
的SWI-PROLOG内置插件。首先,入口点是指使用最初为空的累加器的实现:
numberFromList(L, N) :-
numberFromList(L, [], N).
谓词numberFromList/3
要么从列表中累积数字(未选中),要么没有,留下选择点:
numberFromList([_|Cs], Acc, N) :-
numberFromList(Cs, Acc, N).
numberFromList([C|Cs], Acc, N) :-
numberFromList(Cs, [C|Acc], N).
numberFromList/3
的最后一个句子置换累积的数字列表并将它们连接成一个原子,然后根据需要将其转换为数字:
numberFromList([], [C|Cs], N) :-
permute([C|Cs], PermutedAcc),
atomic_list_concat(PermutedAcc, AN),
atom_number(AN, N).
有时permute/2
(如下面手动定义的)可以作为内置版本使用,例如permutation/2
。以下是使用select/3
的手动定义:
permute([], []).
permute([E|Es], [E0|PL]) :-
select(E0, [E|Es], Rem),
permute(Rem, PL).
如果你想要一个包含所有结果的列表并且不希望numberFromList/2
回溯自己,你可以将调用包装到numberFromList/3
({{1}的第一个子句中的空累加器在findall/3
电话中。} /)
答案 2 :(得分:0)
当您从列表中跳过数字时,您将丢失案例。
numberFromList([X], X) :-
digit(X), !.
numberFromList(List, N) :-
member(X, List),
delete(List, X, LX),
numberFromList(LX, NX),
( % use X
N is NX * 10 + X
; % skip X
N = NX
).
顺便说一句,正如@Roland Illig所提到的,有select(X, List, LX)
替换member(X, List), delete(List, X, LX)