Пролог: найти все числа уникальных цифр, которые могут быть сформированы из списка цифр - PullRequest
1 голос
/ 27 мая 2010

Лучшее, что я мог придумать, это функция:

 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 голосов
/ 27 мая 2010

Вот один способ, используя встроенные модули SWI-PROLOG для atomic_list_concat/2, atom_number/2 и select/3. Во-первых, точка входа относится к реализации, использующей изначально пустой аккумулятор:

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 (с пустым аккумулятором в первом предложении numberFromList/2) в findall/3 вызов.

0 голосов
/ 27 мая 2010

Вы пропускаете случай, когда пропускаете цифру из списка.

 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)

0 голосов
/ 27 мая 2010

Предикат 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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...