I have a sort algorithm and I am trying to call a list but i seems only garbage variable. What is the right way?
This is what I got:
?- sort(list(K),Sorted).
K = Sorted, Sorted = [[_3796]]
This is the code:
list([[a,b,c,10],[e,f,g,2],[h,i,j,6]]).
sort([],[]):- !.
sort([X], [X]).
sort(list([Head|Tail]),Sorted):- %code to sort, split sort, sort and append
I don't have to do this:
?- sort( [ [a,b,c,10], [e,f,g,2], [h,i,j,6] ] , Sorted).
The normal way to do this would be:
?- list(K),sort(K,Sorted).
list([[a,b,c,10],[e,f,g,2],[h,i,j,6]]).
sort([],[]):- !.
sort([X], [X]).
sort([Head|Tail],Sorted):- %code to sort, split sort, sort and append
You could call it the way that you were doing it, but you'd have to do this messy approach:
sort(list([Head|Tail]),Sorted):- list([Head|Tail]), %code to sort, split sort, sort and append
Related
I'm trying to modify a list by search and replace, was wondering how do I search through a list with the search term as a list as well?
Lets say I have a list [1,2,3,4] I want to single out the 2 and 3 and replace it with 5,6
so ideally I could have a predicate:
search_and_replace(Search_Term, Replace_Term, Target_List, Result_List).
eg.
search_and_replace([2,3], [5,6], [1,2,3,4], Result_List), write(Result_List).
Let me assume that you want to replace a subsequence substring within a list by another list.
Here is a general way how to do this. You might want to insert
further conditions into the program.
replacement(A, B, Ag, Bg) :-
phrase((seq(S1),seq(A),seq(S2)), Ag),
phrase((seq(S1),seq(B),seq(S2)), Bg).
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
And, yes this can be optimized a bit - even its termination property
would profit. But conceptual clarity is a quite precious value...
Edit: Your example query:
?- replacement([2,3], [5,6], [1,2,3,4], Xs).
Xs = [1,5,6,4]
; false.
You can use append/2 as follows :
replace(ToReplace, ToInsert, List, Result) :-
once(append([Left, ToReplace, Right], List)),
append([Left, ToInsert, Right], Result).
With or without use of once/1 depending on if you want all the possibilies or not.
To replace all the occurences I'd go with something like :
replace(ToReplace, ToInsert, List, Result) :-
replace(ToReplace, ToInsert, List, [], Result).
replace(ToReplace, ToInsert, List, Acc, Result) :-
append([Left, ToReplace, Right], List),
append([Acc, Left, ToInsert], NewAcc),
!,
replace(ToReplace, ToInsert, Right, NewAcc, Result).
replace(_ToReplace, _ToInsert, [], Acc, Acc).
How can I sort/display all different outputs that make a predicate true according to their list size?
for example, if the output before is:
X = [1,2,3,5,5,2,1,4,1]
X = [1,2,3,1]
X = [1,2,1,3,1,3]
What can I do so that it outputs like this:
X = [1,2,3,1]
X = [1,2,1,3,1,3]
X = [1,2,3,5,5,2,1,4,1]
If your procedure always returns a list, you can collect all solutions, sort them according to the list length and then iterate over the sorted list.
E.g., assume you have a procedure something(L) which returns a list, you can do this:
sorted_something(L):-
findall(Len-L, (something(L), length(L, Len)), AllL),
keysort(AllL, SortedAllL),
member(_-L, SortedAllL).
The call to findall/3 will collect all solutions and their lengths, keysort/2 will sort the solutions according to their length, and member/2 obtains each list from the sorted list of solutions.
sort and duplicates removal can be performed by setof/3:
:- meta_predicate(sorted_lists(1,?)).
sorted_lists(Generate_a_list, SortedByLenght):-
setof(Len-L, (call(Generate_a_list, L), length(L, Len)), All),
member(_-SortedByLenght, All).
I need some help with three prolog predicates for checking and manipulating lists. I'm new to prolog and any help would be much appreciated.
The three predicates are:
double_up(+List1, -List2) is true when List2 has each element of List1 twice. The query double_up([a,b,c],X) should give X=[a,a,b,b,c,c]. The order of the elements in the output list does not matter.
pivot(+List1, +Pivot, -Smaller, -GreaterEq) is true when Smaller is the list of numbers in List1 smaller than Pivot, and GreaterEq is the list of numbers in List1 bigger than or equal to Pivot.
fancy_replace(+List, +Takeout,+Putin, -NewList, -Count) is true when NewList is the same list as the input List, but where each Takeout element in the list is replaced with the Putin element. Count should be the number of Takeouts that got replaced. For example, the query fancy_replace([9,10,1,9,2],9,0, X, C) should give X = [0,10,1,0,2] and C = 2. The order of the elements in the output list does not matter.
The simpler pattern to process lists in Prolog imposes a recursive predicate with 2 arguments, matching - conventionally - input and output data, and a base case, stopping the recursion, matching the empty list. Then
double_up([X|Xs], [X,X|Ys]) :- double_up(Xs, Ys).
double_up([], []).
This predicate it's a bit more general than what's required, because it works also in mode double_up(-List1, +List2). For instance
?- double_up(L,[1,1,2,2]).
L = [1, 2].
To restrict its mode as required, I think it's necessary to uselessly complicate the code, moving that clean loop in a service predicate, and leaving double_up just to test the arguments:
double_up(I, O) :- is_list(I), var(O), double_up_(I, O).
double_up_([X|Xs], [X,X|Ys]) :- double_up_(Xs, Ys).
double_up_([], []).
pivot/4 could be 'one-liner' in SWI-Prolog:
pivot(List1, Pivot, Smaller, GreaterEq) :-
partition(>(Pivot), List1, Smaller, GreaterEq).
like partition, foldl from library(apply) it's an easy inplementation of the last required predicate:
fancy_replace(List, Takeout, Putin, NewList, Count) :-
foldl(swap_n_count(Takeout, Putin), List, NewList, 0, Count).
swap_n_count(Takeout, Putin, L, N, C0, C) :-
( L == Takeout
-> N = Putin, C is C0 + 1
; N = L, C = C0
).
to be honest, i hate prolog... even though it is fun and easy after you learn it
i think this is a good reference as I was having trouble understanding how prolog works couple weeks ago.
what does the follow prolog codes do?
anyway.. this is the answer for your first problem; Hopefully you could solve the rest yourself :D
double([]).
double([H|[]], [H,H|[]]).
double([H|T],[H,H|T1]):- double(T, T1).
btw, this might not the only solution...but it works
i have a problem
i take in input a list, and i want append it's element to another that i want in output
this is my code :
run([],L).
run([X|Y],Lista) :- X =..Total, append(Total,Lista,ListaR), run(Y,ListaR), stamp(ListaR).
stamp([]).
stamp([X|Y]) :- nl, write(X), stamp(Y).
if I run it with:
run([p(X,Y,Z),h(Z,P,Q)],[]).
it will print out:
h
_G238
_G244
_G245
p
_G236
_G237
_G238
p
_G236
_G237
_G238
true.
why it contain 2 time the p ? what is wrong?
_GXXX are variables...
It prints p twice, because you print the result at each level of recursion. If you want to print it only once at the end, do so:
run([],L) :- stamp(L).
run([X|Y],Lista) :- X =..Total, append(Total,Lista,ListaR), run(Y,ListaR).
For appending lists you don't need to write this recursive function append/3 do that for you.
?- append([a,b],[k,l],NewList).
NewList = [a, b, k, l].
But i tried your code in swi-prolog it doesn't give your output but it produces wrong result because you are printing the list more than one in recursion part. You can try something like that
run(List1,List2) :- append(List1,List2,ListResult), stamp(ListResult).
Hope it helps.
a List of Lists like
Lists=[ [1,2,3],
[4,5,6],
[7,8,3] ]
and i want to get in this case all vertical lists like
[1,4,7], [2,5,8], [3,6,3]
how to do that? i thought about 2 counters witch work together like two "for to do" repeats.
i need to check with "is_set" if [1,4,7] is a set or [3,6,3] witch of course is not.
like this:
el_at(Llist,Gl,1),
el_at(EList, Llist,1),
globalListVertikalCheck(ListVertikal),
addlist(Elist,ListVertikal,NewListVertikal),
el_at(Llist,Gl,2),
el_at(EList, Llist,2),
globalListVertikalCheck(ListVertikal),
addlist(Elist,ListVertikal,NewListVertikal),
thanks
A list of all vertical lists is known as a transposed matrix.
SWI's library(clpfd) contains such code.
I didn't fully understand the solution you propose, but I have another one. I will try to describe how it works and maybe than you can see what was wrong with your solution and why it didn't work.
Let's consider an example of [[1,2], [3,4]]. The idea is to go through the first sub-list [1,2] and create an incomplete result [[1],[2]], then go through the next one [3,4] and prepend (which is easier than append in Prolog) each item in it to the each sub-list in the result. We will end up with [[3,1], [4,1]]. The sub-lists are then reversed and we have the result [[1,3],[1,4]].
Now the implementation:
The vertical predicate is the core, it goes through the list of lists and the result is step by step accumulated in the Acc varible.
For each of the sublists, the vertical predicate calls the addfirst predicate, which takes each element of that sublist and prepends it to the list in which the previous results were accumulated.
vertical([X|Xs],Result):-
createempty(X, Acc),
vertical([X|Xs], Acc, ReversedResults),
reverseall(ReversedResults, Result).
reverseall([], []).
reverseall([X|Xs], [XReversed|Rest]):-
reverse(X, XReversed),
reverseall(Xs, Rest).
createempty([], []).
createempty([X|Xs], [[]|R]):-createempty(Xs,R).
vertical([], Result, Result).
vertical([X|Xs], Acc, Result):-
addfirst(X, Acc2, Acc),
vertical(Xs, Acc2, Result).
addfirst([], [], []).
addfirst(
[Y|Ys],
[[Y|YVerticalRest]|ResultRest],
[YVerticalRest|VerticalsRest]):-
addfirst(Ys, ResultRest, VerticalsRest).
Here goes a small implementation of transpose:
It works by taking the first element of every sublist. When it finishes, it recursively does the same but now with the next item of each list, and so on.
transpose(M, T):-
transpose(M, [], T).
transpose([], [], []).
transpose([], S, [[]|T]):-
S \= [] ->
(reverse(S, M), transpose(M, [], T)).
transpose([[]|MTail], S, T):-
transpose(MTail, S, T).
transpose([[Item|Tail]|MTail], S, [[Item|NTail]|T]):-
transpose(MTail, [Tail|S], [NTail|T]).
transpose([[]|_],[]) :- !.
transpose(L,[L1|R2]) :-
transpose(L,L2,L1),
transpose(L2,R2).
transpose([],[],[]) :- !.
transpose([[A|R1]|R2],[R1|R3],[A|R4]) :-
transpose(R2,R3,R4).