Как преобразовать список двоичных чисел 0 в 1 PROLOG - PullRequest
0 голосов

Как мне преобразовать список двоичных чисел 0 в 1 в Прологе, чтобы получить следующие результаты:

?- cryptoA( [1,1,0,1,0,0,0,1], L2).
L2 = [0,0,1,0,1,1,1,0]

Ответы [ 2 ]

3 голосов
/ 11 июля 2020

Просто, это

cryptoA([1,1,0,1,0,0,0,1], [0,0,1,0,1,1,1,0]).

Но, конечно, слишком конкретно c. Вероятно, следует добавить больше случаев, например,

cryptoA([1,1,0,1,0,0,0],   [0,0,1,0,1,1,1]  ).
cryptoA([1,1,0,1,0,0],     [0,0,1,0,1,1]    ).
cryptoA([1,1,0,1,0],       [0,0,1,0,1]      ).
.....
cryptoA([1,1,0],           [0,0,1]          ).
.....
cryptoA([  1  ],           [  0  ]          ).
cryptoA([    0],           [    1]          ).

, верно? Но сколько конкретных случаев достаточно? Будет ли этого когда-нибудь достаточно?

Чтобы иметь дело с бесконечным количеством структурированных кейсов, мы можем написать структурированный код, используя рекурсию. Последние два предложения кажутся минимальными, и почему они должны быть заключены в такие списки?

cryptoB(   1 ,                0             ).
cryptoB(     ,                              ).         
                               % fill the blanks

Что такое рекурсивный регистр?

cryptoA( [A | B], [C | D] ) :-
  cryptoB(  ,  ),              % fill the blanks
  cryptoA( B, D).

Каков базовый случай?

cryptoA( [    ], [    ] ).     % fill the blanks

Завершить определение последнего предложения особенно легко.

Мы могли бы прийти к этому «рекурсивному» решению, поиграв с данным примером, упростив его, а затем обобщив его.

Посмотрим. Если пойти в другом направлении, это

cryptoA(  [1,1,0,1,0,0,0],   [0,0,1,0,1,1,1]  ).   % which means this must hold:
cryptoA(  [  1,0,1,0,0,0],   [  0,1,0,1,1,1]  ).   % and also this must hold:
cryptoA(  [1            ],   [0            ]  ).   % which is to say,
cryptoB(   1             ,    0               ).   % this must hold

Итак, давайте запишем это!

cryptoA(  [1,1,0,1,0,0,0],   [0,0,1,0,1,1,1]  ) :-
  cryptoA([  1,0,1,0,0,0],   [  0,1,0,1,1,1]  ),
  cryptoB( 1             ,    0               ).

%% or, equivalently,
cryptoA( X,   Y  ) :- 
  X =     [1,1,0,1,0,0,0],  Y = [0,0,1,0,1,1,1],   % specific case
  X =     [A | B        ],  Y = [C | D        ],   % general structure
  cryptoA(     B,                    D        ),   %  recursive step
  cryptoB( A             ,       C            ).   %  single-step processing

, и теперь мы можем обобщить, просто удалив это определение c case. Конечно, та же самая схема должна выполняться с любыми другими спецификациями c данных вообще!

Конечно, не каждый список может быть сопоставлен с шаблоном непустого списка [_ | _], просто потому что не все списки непустые. Некоторые списки на самом деле пусты, [], и это приводит к базовому случаю.

Наконец, рекурсивный шаг предпочтительно указывать последним, в так называемой хвостовой позиции, для общий предикат должен быть хвостом рекурсивным. Так намного эффективнее.

2 голосов
/ 11 июля 2020

однозначное соответствие в списках легко выполняется с помощью maplist:

cryptoA(A,B) :- maplist(\X^Y^(X=1,Y=0;X=0,Y=1),A,B).

Чтобы это работало, вы должны установить библиотеку (лямбда), например, в SWI-Prolog

?- pack_install(lambda).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...