Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prolog With Lists

Tags:

list

prolog

I received this problem and I can't get it done, I don't know what I've done wrong, can someone help me ?

Write a predicate to add a value v after 1-st, 2-nd, 4-th, 8-th, … element in a list.

% add(L:list, E:Number, P:Number, C:number, H:List)
% add(i,i,i,i,o)

add([],_,_,_,[]).
add([_|T],E,P,C,[HR|TR]) :-
   P =:= C,
   HR is E,
   C is C+1,
   P is P*2,
   add(T,E,P,C,TR).
add([H|T],E,P,C,[H|TR]) :-
   P =\= C,
   C is C+1,
   add(T,E,P,C,TR).
like image 958
Oscar Gal Avatar asked May 16 '26 01:05

Oscar Gal


1 Answers

Here's another possibility to define such a predicate. Whenever you are describing lists it is worthwhile to consider using DCGs since they yield easily readable code. First let's observe that there's only need for three arguments, namely the list, the element to be inserted and the list with the element already inserted at the desired positions. The arguments P and C are only needed for bookkeeping purposes so it's opportune to hide them inside the predicate. And since we're already about to redesign the predicates interface let's also give it a more descriptive name that reflects its relational nature, say list_e_inserted/3:

list_e_inserted(L,E,I) :-
   phrase(inserted(L,E,1,1),I).  % the DCG inserted//4 describes the list I

inserted([],_E,_P,_C) -->        % if the list L is empty  
   [].                           % the list I is empty as well
inserted([H|T],E,P,P) -->        % if P and C are equal
   {P1 is P*2, C1 is P+1},       % P is doubled and C is increased
   [H,E],                        % H is in the list I, followed by E
   inserted(T,E,P1,C1).          % the same holds for T,E,P1,C1
inserted([H|T],E,P,C) -->        % if P and C are
   {dif(P,C), C1 is C+1},        % different C is increased
   [H],                          % H is in the list I
   inserted(T,E,P,C1).           % the same holds for T,E,P,C1

Now let's see the predicate at work:

?- list_e_inserted([],10,I).
I = [].

?- list_e_inserted([1],10,I).
I = [1, 10] ;
false.

?- list_e_inserted([1,2],10,I).
I = [1, 10, 2, 10] ;
false.

?- list_e_inserted([1,2,3],10,I).
I = [1, 10, 2, 10, 3] ;
false.

?- list_e_inserted([1,2,3,4],10,I).
I = [1, 10, 2, 10, 3, 4, 10] ;
false.

The predicate also works in the other direction:

?- list_e_inserted(L,E,[1,10,2,10,3,4,10,5]).
L = [1, 2, 3, 4, 5],
E = 10 ;
false.

And the most general query also yields the desired solutions:

?- list_e_inserted(L,E,I).
L = I, I = [] ;
L = [_G23],
I = [_G23, E] ;
L = [_G23, _G35],
I = [_G23, E, _G35, E] ;
L = [_G23, _G35, _G47],
I = [_G23, E, _G35, E, _G47] ;
L = [_G23, _G35, _G47, _G53],
I = [_G23, E, _G35, E, _G47, _G53, E] ;
.
.
.
like image 137
tas Avatar answered May 18 '26 16:05

tas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!