James
James

Reputation: 13

switch between 1 and 0 in a list

There is an initial list always consists of '1' (e.g.: [1,1,1], [1,1,1,1]), and the initial list will be given in the question. Then there are some people want to switch the list. The first person will switch every '1' to '0'. The second person follow the first one, and he want to switch the every second number to another(if he meets '0', he switch it to '1';if he meets '1', he switch it to '0'). The third person follow the first one, and he want to switch the every third number to another. Of course, the number of people will be given in the question. Please give the result of final statement of the list.

Write a program 'switch(1,N,Initial,Final). N is the count of people.

For example :

switch(1,2,[1,1],Final).       Final=[0,1].

switch(1,3,[1,1,1],Final).     Final=[0,1,1].

Upvotes: 0

Views: 121

Answers (2)

Kintalken
Kintalken

Reputation: 773

:- [library(plunit)] .

switch(_one_,_two_,_source_,_target_) :-
    switch('induce',_one_,_two_,_source_,_target_,1) .

switch('swap',false,0,0) .
switch('swap',false,1,1) .
switch('swap',true,0,1) .
switch('swap',true,1,0) .

switch('induce',_one_,_two_,_source_,_target_,_nth_) :-
    _source_ = [] ,
    _target_ = [] ;
    _source_ = [_car_|_cdr_] ,
    _target_ = [_CAR_|_CDR_] ,
    _NTH_ is _nth_ + 1 ,
    switch('induce',_one_,_two_,_cdr_,_CDR_,_NTH_) ,
    switch('deduce',_one_,_two_,_car_,_CAR_,_nth_) .

switch('deduce',_one_,_two_,_car_,_CAR_,_nth_) :-
    _one_ = _nth_ ,
    switch('swap',true,_car_,_CAR_) ;
    _one_ \= _nth_ ,
    _two_ = _nth_ ,
    switch('swap',true,_car_,_CAR_) ;
    _one_ \= _nth_ ,
    _two_ \= _nth_ ,
    switch('swap',false,_car_,_CAR_) .

%

:- begin_tests(switch).

test(switch,[nondet,true(Final == [0,0])])       :- switch(1,2,[1,1],Final) .
test(switch,[nondet,true(Final == [0,1,0])])     :- switch(1,3,[1,1,1],Final) .
test(switch,[nondet,true(Final == [0,1,1,0])])   :- switch(1,4,[1,1,1,1],Final) .
test(switch,[nondet,true(Final == [0,1,1,1,0])]) :- switch(1,5,[1,1,1,1,1],Final) .
test(switch,[nondet,true(Final == [1,1,1,1,1])]) :- switch(1,5,[0,1,1,1,0],Final) .

:- end_tests(switch).

%

/*
$ yap -f stackoverflow_switch_list.prolog -g 'run_tests' ;
YAP 6.2.2 (i686-linux): Sat Aug 17 14:01:16 UTC 2019
% PL-Unit: switch ..... done
% All 5 tests passed
yes
   ?- 
*/

Upvotes: 0

Paul Brown
Paul Brown

Reputation: 2403

So we've got a bunch of people who, with nothing better to do in their lives, want to sequentially switch some numbers in a list. Someone needs to introduce them to Prolog, they could make better use of their time. But this is our initial recursion and base case:

switch(N, N, In, Out) :-
    person_switch(N, 1, In, Out), !.
switch(P, N, In, Out) :-
    person_switch(P, 1, In, Done),
    succ(P, Q),
    switch(Q, N, Done, Out).

So we can make our people do their switch sequentially via the first argument, which we increment until we reach the base case.

Next up, we'd better teach these people how to do their jobs of switching 0's and 1's.

person_switch(_, _, [], []). % Base case
person_switch(P, P, [1|In], [0|Out]) :- % switch 1 to a 0 on their turn
    person_switch(P, 1, In, Out). % Recurse
person_switch(P, P, [0|In], [1|Out]) :- % switch 0 to a 1 on their turn
    person_switch(P, 1, In, Out). % Recurse
person_switch(P, C, [H|In], [H|Out]) :- % don't switch, unify
    C < P, % don't not switch when they should, C is a counter along the list
    succ(C, D), % increment
    person_switch(P, D, In, Out). % Recurse

Good luck learning Prolog.

Upvotes: 1

Related Questions