inserting an integer into a sorted list - list

So my problem is this i have a predicate called insere_ordenado(El,Lst1,Lst2) in which El is a random integer, Lst1 is a list and Lst2 is the resulting list of adding El to Lst1.
The thing is i did this recursively but now i have to do this iteratively and the problem is when i want to add a number that is bigger or equal than the biggest number of the list it doesnt add anything.
Example:
?- insere_ordenado_ite(2,[1,2,3,6,9],L2).
L2 = [1, 2, 2, 3, 6, 9].
?- insere_ordenado_ite(5,[1,2,3,6,9],L2).
L2 = [1, 2, 3, 5, 6, 9].
?- insere_ordenado_ite(0,[1,2,3,6,9],L2).
L2 = [0, 1, 2, 3, 6, 9].
?- insere_ordenado_ite(9,[1,2,3,6,9],L2).
L2 = [1, 2, 3, 6, 9] .
?- insere_ordenado_ite(10,[1,2,3,6,9],L2).
L2 = [1, 2, 3, 6, 9] .
As you can see in the example that i want to add 9 or 10 its supposed to add 9 or 10 (depending on the example) at the end.
Program:
insere_ordenado_ite(El,L1,L2) :- insere_ordenado_ite(El,L1,L2,[]).
insere_ordenado_ite(El,[],L2,L2).
insere_ordenado_ite(El,[P|R],L2,AC) :- El >= P,
append(AC,[P],NAC),
insere_ordenado_ite(El,R,L2,NAC).
insere_ordenado_ite(El,[P|R],L2,AC) :- El < P,
append(AC,[El,P],NAC),
append(NAC,R,NNAC),
insere_ordenado_ite(El,[],L2,NNAC).
I think the problem is that something is missing from the stop condition, but I'm not sure what it is or how to do it exactly, honestly any help would be appreciated.

How about this, which I happen to have on hand.
It's as iterative as possible, there is nothing which happens after an insert_help/3, call. The tail of the difflist is constrained to a valid list eventually, and as variables are really global, this fact is immediately visible to whoever shares the variable, in this case insert/3.
insert(P,List,T) :-
DiffList=[-1|T]-T, % -1 is a guard, smaller than anything, removed later
insert_help(P,List,DiffList).
insert_help(P,[Px|R],H-T) :-
P>Px,!,
format("go right at ~q into ~q, difflist: ~q\n",[P,[Px|R],H-T]),
T=[Px|TT],
insert_help(P,R,H-TT).
insert_help(P,[P|R],H-T) :-
!,
format("~q exists in ~q, difflist: ~q\n",[P,[P|R],H-T]),
T=[P|R].
insert_help(P,[Px|R],H-T) :-
P<Px,!,
format("insert-before at ~q into ~q, difflist: ~q\n",[P,[Px|R],H-T]),
T=[P,Px|R].
insert_help(P,[],H-T) :-
!,
format("insert ~q at end, difflist: ~q\n",[P,H-T]),
T=[P].
:-begin_tests(inserting).
test(1) :- insert(10,[],R),R=[10].
test(2) :- insert(11,[2,3,5,7],R),R=[2,3,5,7,11].
test(3) :- insert(2,[3,5,7,11],R),R=[2,3,5,7,11].
test(4) :- insert(3,[2,3,5,7,11],R),R=[2,3,5,7,11].
test(5) :- insert(3,[2,5,7,11],R),R=[2,3,5,7,11].
test(6) :- insert(7,[2,3,5,11],R),R=[2,3,5,7,11].
test(7) :- insert(2,[],R),R=[2].
:-end_tests(inserting).
rt :- run_tests(inserting).
Addendum: Solving it with append/{2,3}
If you have append/3 (and append/2), you can just do:
insert_with_append(El,List,Out) :-
search(El,List,0,Result),
((Result >= 0) % -1 means entry exists
->
(length(Front,Result), % create list of fresh variables of length Result
append(Front,Back,List), % rip list apart into Front, Back
append([Front,[El],Back],Out)) % build result
;
Out = List % already exists in list
).
% search/4 looks for the insert position, counting the number of
% items in List that come before Element, and setting CounterOut
% to that value, once known. CounterOut is set to -1 if Element
% is already in the list.
% search(Element,List,CounterCur,CounterOut)
search(_,[],Counter,Counter) :- !.
search(E,[L|Ls],CounterCur,CounterOut) :-
L<E,!,
succ(CounterCur,CounterNext),
search(E,Ls,CounterNext,CounterOut).
search(E,[L|_],CounterCur,CounterCur) :-
E<L,!.
search(E,[E|_],_,-1).
:-begin_tests(insert_with_append).
test(1) :- insert_with_append(10,[],R),R=[10].
test(2) :- insert_with_append(11,[2,3,5,7],R),R=[2,3,5,7,11].
test(3) :- insert_with_append(2,[3,5,7,11],R),R=[2,3,5,7,11].
test(4) :- insert_with_append(3,[2,3,5,7,11],R),R=[2,3,5,7,11].
test(5) :- insert_with_append(3,[2,5,7,11],R),R=[2,3,5,7,11].
test(6) :- insert_with_append(7,[2,3,5,11],R),R=[2,3,5,7,11].
test(7) :- insert_with_append(2,[],R),R=[2].
:-end_tests(insert_with_append).
rt :- run_tests(insert_with_append).

Related

Prolog prefix sum of a list

I want to implement the prolog predicate prefixSum(L, R) that calculates the prefix sum of a list i.e:
?- prefixSum([1,2,3,4],R).
R=[1,3,6,10].
Here is my solution so far:
prefixSum([],[]).
prefixSum([X], [X])
prefixSum([X|Xs], [R, Rs|T]):-
Rs is X + R, prefixSum(Xs, T).
What can I try next?
Your original code,
prefixSum( [] , [] ) .
prefixSum( [X] , [X] )
prefixSum( [X|Xs] , [R,Rs|T] ) :- Rs is X+R, prefixSum(Xs,T) .
Has these problems:
The code is syntactically incorrect, as the 2nd clause is not terminated by ..
In the 3rd clause, the variable R will always be unbound unless you've provided a bound list as the 2nd argument to prefixSum/3, meaning Rs is X+R will fail.
The key to what you are trying to accomplish is that as you traverse the list, you need to track the sum previously computed as you go.
That leads to an implementation like this:
prefix_sum( [] , [] ) . % the empty list is a special case
prefix_sum( [X|Xs] , [X|Ys] ) :- % for a non-empty list, we add the first item to the result , and
prefix_sum(Xs,X,Ys) . % invoke our helper, seeding the previous sum with the first element.
prefix_sum( [] , _ , [] ) . % once the source list is exhausted, we're done.
prefix_sum( [X|Xs] , P , [Y|Ys] ) :- % otherwise...
Y is P+X, % compute the sum of the current element and the previous sum
prefix_sum(Xs,Y,Ys) . % and recurse down on the tails.
prefix_sum(L, Ps) :-
prefix_sum_(L, 0, Ps).
prefix_sum_([], _, []).
prefix_sum_([H|T], S, [P|Ps]) :-
P is H + S,
prefix_sum_(T, P, Ps).
Result in swi-prolog:
?- prefix_sum([1,2,3,4], Ps).
Ps = [1, 3, 6, 10].
This is an operation on lists knows as a "scan" which, unlike a "fold", keeps a list of intermediate results. For your particular case you could use the built-in plus/3 but you might also need to define a helper predicate like add/3:
add(X, Y, Z) :- Z is X + Y.
Now you can do:
?- foldl(add, [1,2,3,4], 0, Sum).
Sum = 10.
?- scanl(add, [1,2,3,4], 0, [0|Sums]).
Sums = [1, 3, 6, 10].
If you don't like the useless addition of the zero you can split off the first element in advance, so:
?- [1,2,3,4] = [V0|Vs], scanl(add, Vs, V0, Result).
V0 = 1,
Vs = [2, 3, 4],
Result = [1, 3, 6, 10].
"Scan left" and "fold left" are available in library(apply) in SWI-Prolog and your exact question is solved in the examples on the docs for scanl. You can also look at the implementation of scanl.
Yes, this answer is perfectly good. When I look at the solution and compare it to the library definition of scanl/4 I just see a generic algorithm that has been specialized to solve one particular instance by binding the Goal.

How can I delete every occurrence of a sublist from a list in prolog?

This is the code for deleting or removing an element from a given list:
remove_elem(X,[],[]).
remove_elem(X,L1,L2) :-
L1 = [H|T],
X == H,
remove_elem(X,T,Temp),
L2 = Temp.
remove_elem(X,L1,L2) :-
L1 = [H|T],
X \== H,
remove_elem(X,T,Temp),
L2 = [H|Temp].
How can I modify it, so that I can delete every occurrence of a sub list from a list?
When I tried to put a list in an element, it only deletes the element and only once.
It should be this:
?- remove([1,2],[1,2,3,4,1,2,5,6,1,2,1],L).
L = [3,4,5,6,1]. % expected result
Inspired by #CapelliC's implementation I wrote the following code based on
and_t/3:
append_t([] ,Ys,Ys, true).
append_t([X|Xs],Ys,Zs,Truth) :-
append_aux_t(Zs,Ys,Xs,X,Truth).
append_aux_t([] ,_ ,_ ,_,false). % aux pred for using 1st argument indexing
append_aux_t([Z|Zs],Ys,Xs,X,Truth) :-
and_t(X=Z, append_t(Xs,Ys,Zs), Truth).
One append_t/4 goal can replace two prefix_of_t/3 and append/3 goals.
Because of that, the implementation of list_sublist_removed/3 gets a bit simpler than before:
list_sublist_removed([] ,[_|_] ,[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(append_t([L|Ls],Xs0,[X|Xs]),
(Zs = Zs0 , Xs1 = Xs0),
(Zs = [X|Zs0], Xs1 = Xs)),
list_sublist_removed(Xs1,[L|Ls],Zs0).
Still deterministic?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1].
Yes! What about the following?
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3,4,5,6,1]).
X = [1,2] ; % succeeds with useless choice-point
false.
Nope. So there is still room for potential improvement...
This logically pure implementation is based on the predicates if_/3 and (=)/3.
First, we build a reified version of prefix_of/2:
prefix_of_t([],_,true).
prefix_of_t([X|Xs],Zs,T) :-
prefix_of_t__aux(Zs,X,Xs,T).
prefix_of_t__aux([],_,_,false).
prefix_of_t__aux([Z|Zs],X,Xs,T) :-
if_(X=Z, prefix_of_t(Xs,Zs,T), T=false).
Then, on to the main predicate list_sublist_removed/3:
list_sublist_removed([],[_|_],[]).
list_sublist_removed([X|Xs],[L|Ls],Zs) :-
if_(prefix_of_t([L|Ls],[X|Xs]), % test
(Zs = Zs0, append([L|Ls],Xs0,[X|Xs])), % case 1
(Zs = [X|Zs0], Xs0 = Xs)), % case 2
list_sublist_removed(Xs0,[L|Ls],Zs0).
A few operational notes on the recursive clause of list_sublist_removed/3:
First (test), we check if [L|Ls] is a prefix of [X|Xs].
If it is present (case 1), we strip it off [X|Xs] yielding Xs0 and add nothing to Zs.
If it is absent (case 2), we strip X off [X|Xs] and add X to Zs.
We recurse on the rest of [X|Xs] until no more items are left to process.
Onwards to some queries!
The use case you gave in your question:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3,4,5,6,1]. % succeeds deterministically
Two queries that try to find the sublist that was removed:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[ 3,4,5,6,1]).
Sub = [1,2] ? ;
no
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],Sub,[1,3,4,5,6,1]).
no
Next, let's find a suitable Ls in this query:
?- list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
% a lot of time passes ... and nothing happens!
Non-termination! This is unfortunate, but within expectations, as the solution set is infinite. However, by a-priori constraining the length of Ls, we can get all expected results:
?- length(Ls,_), list_sublist_removed(Ls,[1,2],[3,4,5,6,1]).
Ls = [ 3,4,5,6,1] ?
; Ls = [1,2, 3,4,5,6,1] ?
; Ls = [3, 1,2, 4,5,6,1] ?
; Ls = [3,4, 1,2, 5,6,1] ?
; Ls = [3,4,5, 1,2, 6,1] ?
; Ls = [3,4,5,6, 1,2, 1] ?
; Ls = [3,4,5,6,1, 1,2 ] ?
; Ls = [1,2, 1,2, 3,4,5,6,1] ? ...
<rant>
So many years I study Prolog, still it deserves some surprises... your problem it's quite simple to solve, when you know the list library, and you have a specific mode (like the one you posted as example). But can also be also quite complex to generalize, and it's unclear to me if the approach proposed by #repeat, based on #false suggestion (if_/3 and friends) can be 'ported' to plain, old Prolog (a-la Clocksin-Mellish, just to say).
</rant>
A solution, that has been not so easy to find, based on old-school Prolog
list_sublist_removed(L, S, R) :-
append([A, S, B], L),
S \= [],
list_sublist_removed(B, S, T),
append(A, T, R),
!
; L = R.
some test:
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],[1,2],L).
L = [3, 4, 5, 6, 1].
?- list_sublist_removed([1,2,3,4,1,2,5,6,1,2,1],X,[3, 4, 5, 6, 1]).
X = [1, 2].
?- length(X,_), list_sublist_removed(X,[1,2],[3, 4, 5, 6, 1]).
X = [3, 4, 5, 6, 1] ;
X = [3, 4, 5, 6, 1, 2, 1] ...

Taking a tree and making a list

I have written a program that can take a list and change it into a tree.
build_tree([X,Y],'Tree'(X,Y)) :- !.
build_tree([X|Y],'Tree'(X,Z)) :- build_tree(Y, Z).
If I want to reverse the process and take the tree and change it back into a list, how would I do this?
Note that your tree->list conversion isn't a function since trees may correspond to multiple lists:
?- build_tree([1, 2, 3], T).
T = 'Tree'(1, 'Tree'(2, 3)).
?- build_tree([1, 'Tree'(2, 3)], T).
T = 'Tree'(1, 'Tree'(2, 3)).
If you want a predicate that can generate all lists from a tree, remove the cut from build_tree and apply it with a variable first argument. If you want a deterministic conversion, write a new predicate tree_to_list.
Just curious, how would that deterministic version play out? Assuming there was only one possible list, from the tree, for example:
('Tree'('Tree'(nil, 2, nil), 5, 'Tree'(nil, 6, nil)).
Which gives: L = [5, 2, 6]
If you remove the cut from the first rule, your code it's ready to work in 'backward' mode:
?- build_tree([1,2,3,4],T).
T = 'Tree'(1, 'Tree'(2, 'Tree'(3, 4))) ;
false.
?- build_tree(X,$T).
X = [1, 'Tree'(2, 'Tree'(3, 4))] ;
X = [1, 2, 'Tree'(3, 4)] ;
X = [1, 2, 3, 4] ;
false.
flatten(leaf, []).
flatten(node(L, E, R), Ls) :-
flatten(L, Ls1),
append(Ls1, [E], Ls2),
flatten(R, Ls3),
append(Ls2, Ls3, Ls).
if you consider tree ass node(leaf,Element,leaf) for example
flatten(node(node(leaf,2,leaf),3,node(leaf,5,leaf)),X).
gives X=[2,3,5].
and if you wanna have bst
List to Tree.
insert(E,leaf,node(leaf,E,leaf)).
insert(E,node(L,N,R),T) :-
E >= N,
T=node(L,N,R1),
insert(E,R,R1).
insert(E,node(L,N,R),T) :-
E < N,
T=node(L1,N,R),
insert(E,L,L1).
list_to_tree(List,Tree) :-
list_to_tree(List,leaf,Trea2),
Tree=Trea2.
list_to_tree([],Tree,Tree).
list_to_tree([H|T],Tree,St):-
insert(H,Tree,R),
list_to_tree(T,R,St).

Prolog: How to remove every second element of a list

I need to write a program in Prolog that should remove every second element of a list. Should work this: [1,2,3,4,5,6,7] -> [1,3,5,7]
so far I have this, but it just returns "false".
r([], []).
r([H|[T1|T]], R) :- del(T1,[H[T1|T]], R), r(R).
del(X,[X|L],L).
del(X,[Y|L],[Y|L1]):- del(X,L,L1).
This is pretty much Landei's answer in specific Prolog syntax:
r([], []).
r([X], [X]).
r([X,_|Xs], [X|Ys]) :- r(Xs, Ys).
The second predicate is not required.
Alternative solution using foldl/4:
fold_step(Item, true:[Item|Tail], false:Tail).
fold_step(_Item, false:Tail, true:Tail).
odd(List, Odd) :-
foldl(fold_step, List, true:Odd, _:[]).
Usage:
?- odd([1, 2, 3, 4, 5, 6, 7], Odd).
Odd = [1, 3, 5, 7]
The idea is to go through the list, while keeping "odd/even" flag and flipping its value (false -> true, true -> false) on each element. We also gradually construct the list, by appending those elements which have "odd/even" flag equal to true, and skipping others.
This fine answer by #code_x386 utilizes difference-lists and foldl/4.
Let's use only one fold_step/3 clause and make the relation more general, like so:
fold_step(X, [X|Xs]+Ys, Ys+Xs).
list_odds_evens(List, Odds, Evens) :-
foldl(fold_step, List, Odds+Evens, []+[]).
Sample queries:
?– list_odds_evens([a,b,c,d,e,f], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e]
?– list_odds_evens([a,b,c,d,e,f,g], Odds, Evens).
Evens = [b,d,f], Odds = [a,c,e,g]
Edit
Why not use one clause less and do away with predicate fold_step/3?
lambda to the rescue!
:- use_module(library(lambda)).
list_odds_evens(List, Odds, Evens) :-
foldl(\X^([X|Xs]+Ys)^(Ys+Xs)^true, List, Odds+Evens, []+[]).
Another possibility is to use DCGs, they are usually a worthwhile consideration when describing lists:
list_oddindices(L,O) :-
phrase(oddindices(L),O). % the list O is described by oddindices//1
oddindices([]) --> % if L is empty
[]. % O is empty as well
oddindices([X]) --> % if L has just one element
[X]. % it's in O
oddindices([O,_E|OEs]) --> % if L's head consists of at least two elements
[O], % the first is in O
oddindices(OEs). % the same holds for the tail
This is certainly less elegant than the solutions using foldl/4 but the code is very easily readable, yet it solves the task described by the OP and works both ways as well:
?- list_oddindices([1,2,3,4,5,6,7],O).
O = [1, 3, 5, 7] ;
false.
?- list_oddindices(L,[1,3,5,7]).
L = [1, _G4412, 3, _G4418, 5, _G4424, 7] ;
L = [1, _G4412, 3, _G4418, 5, _G4424, 7, _G4430] ;
false.
I have no Prolog here to try it out, and I got a little bit rusty, but it should be along the lines of
r([]) :- [].
r([X]) :- [X].
r([X,Y|Z]) :- R=r(Z),[X|R].
[Edit]
Of course pad is right. My solution would work in functional languages like Haskell or Erlang:
--Haskell
r [] = []
r [x] = [x]
r (x:_:xs) = x : (r xs)
In Prolog you have to "pull" the right sides into the argument list in order to trigger unification.
I just needed a function like this and took a more "mathematical" approach:
odds(Xs, Ys) :- findall(X, (nth1(I,Xs,X), I mod 2 =:= 1), Ys).
It doesn't work both ways like some of the other fine answers here, but it's short and sweet.

How do I find the longest list in a list of lists?

I have a list of lists, and I need to find the longest one of them. If there are more than one with the same length it's the same which it returns. Thanks.
Here is a general predicate that scans a list to find a single member defined by a given goal.
select_element(Goal, [Head | Tail], Selected) :-
select_element(Goal, Tail, Head, Selected).
select_element(_Goal, [], Selected, Selected).
select_element(Goal, [Head | Tail], Current, FinalSelected) :-
call(Goal, Head, Current, Selected),
select_element(Goal, Tail, Selected, FinalSelected).
Lets say you define a predicate
get_bigger_number(N1, N2, N) :-
N is max(N1, N2).
Now you can execute:
?- select_element(get_bigger_number, [5, 1, -2, 10, 3.2, 0], Selected).
Selected = 10
So all you need to do now is define a predicate get_longer_list(L1, L2, L),
and use it instead of get_bigger_number/3.
Of course, using a general predicate like select_element/3 might not be very efficient. For example, you should try to avoid calculating the length of the same list several times, because this calculation is slow in Prolog (at least if implemented in Prolog in the standard way).
Please consider my aproach.
longest([L], L) :-
!.
longest([H|T], H) :-
length(H, N),
longest(T, X),
length(X, M),
N > M,
!.
longest([H|T], X) :-
longest(T, X),
!.
Then you can consult it:
?- longest([[1]], N).
N = [1] ;
?- longest([[1],[2]], N).
N = [2] .
?- longest([[1],[2], [3,3,3], [2]], N).
N = [3, 3, 3] ;
?- longest([[1],[2], [3,3,3], [2]], N).
N = [3, 3, 3].
?- longest([[1],[2], [3,3,3], [2], [4,4,4,4]], N).
N = [4, 4, 4, 4] .
?- longest([[1],[2], [3,3,3], [2], [4,4,4,4]], N).
N = [4, 4, 4, 4] ;
Greets!
We define longest/2 based on meta-predicate max_of_by/3 used in tandem with length/2:
longest(Xss,Ys) :-
max_of_by(Ys,Xss,length).
Sample queries:
?- longest([[1],[2]],Xs). % we expect multiple solutions
Xs = [1]
; Xs = [2]. % we _get_ multiple solutions
?- longest([[2,1,3],[7,5],[1,8,2,3,1],[2,7,1,4]],Xs).
Xs = [1,8,2,3,1]. % succeeds deterministically
Here is another approach that is efficient and easy to understand. The idea is to find the lengths of all lists in the list, use max_list to get the length of the longest list, and then find a list that is that long. This has the benefit that it will return all lists of the longest length.
lengths([],[]).
lengths([H|T], [LH|LengthsT]) :-
length(H, LH),
lengths(T, LengthsT).
lengthLongest(ListOfLists, Max) :-
lengths(ListOfLists, Lengths),
max_list(Lengths, Max).
longestList(ListOfLists, Longest) :-
lengthLongest(ListOfLists, Len),
member(Longest, ListOfLists),
length(Longest, Len).
% Correct again.
longest(LL,LX) :-
findmax(Len,(append(_,[L|_],LL),length(L,Len)),MaxLen),
append(_,[LX|_],LL),
length(LX,MaxLen).
findmax(V,P,Max) :-
findall(V,P,L),
max(L,Max).
max([N],N) :- !.
max([N|R],Max) :-
max(R,Max2),
max3(N,Max2,Max).
max3(N,Max2,N) :- N > Max2,!.
max3(N,Max2,Max2).
To have the length of longest list:
%sample: longest([[2,1,3],[7,5],[1,8,2,3,1],[2,7,1,4]],L,LEN).
longest([L], L, _) :-
!.
longest([H|T], H, _) :-
length(H, N),
longest(T, X, N),
length(X, M),
N > M,
!.
longest([_|T], X, LEN) :-
length(X, LEN),
longest(T, X, LEN),
!.