Prolog:查找可以从数字列表中形成的所有唯一数字

时间:2010-05-26 22:08:43

标签: list numbers prolog digits

到目前为止,我能想出的最好的事情就是这个功能:

 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)这样的东西来获得更短的列表。

我很感激任何贡献。

3 个答案:

答案 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/2atom_number/2select/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)