简体   繁体   中英

How can I convert a list of binary 0 to 1 numbers PROLOG

How can I convert a list of binary 0 to 1 numbers in Prolog to give me the following results:

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

Simple, it's

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

But of course it's too specific. More cases should probably be added, like

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]          ).

right? But how many concrete cases is enough? Is it ever going to be, enough?

To deal with the infinite number of structured cases, we can write down a structured code, using recursion. The last two clauses seem minimal, and why should they be enclosed in lists like that?

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

What is the recursive case?

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

What is the base case?

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

Finishing the last clause's definition is particularly easy.


We could arrive at this "recursive" solution by the same way of playing with the given example, simplifying it, and then generalizing it.

Let's see. Going in another direction, it is

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

So, let's write this down!

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

and now, we can generalize by simply removing that specific case definition. Surely the same scheme must hold with any other specific data at all!

Of course not every list can be matched up with a non-empty list [_ | _] [_ | _] pattern, just because not all lists are non-empty. Some lists are actually empty, [] , and this gives rise to the base case.

Lastly, the recursive step is preferred to be specified last, in so called tail position, for the overall predicate to be tail recursive. It is much more efficient this way.

one to one correspondence in lists is easily done with maplist:

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

You should install library(lambda) for this to work, in SWI-Prolog for instance

?- pack_install(lambda).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM