Пролог: Найти все номера уникальных цифр, которые могут быть сформированы из списка цифр

StackOverflow https://stackoverflow.com/questions/2917182

  •  04-10-2019
  •  | 
  •  

Вопрос

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

 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) В какой-то момент для получения списков меньшей длины.

Я был бы признателен за любой вклад.

Это было полезно?

Решение

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

 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)

Другие советы

Предикат 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.

Вот один из способов, используя 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 вызов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top