Sorting tuples based on elements in Erlang - sorting

Having read current answer THIS I did the following:
A = {1, 99}, B = {5, 15}.
F = fun({key_X, val_X},{key_Y, val_Y}) ->
{val_X, key_X} =< {val_Y, key_Y}
end.
And then, put it to lists:sort/2 function.
As follows:
lists:sort(F, [A, B]).
But got the error exception :
exception error: no function clause matching erl_eval:'-inside-an-interpreted-fun-'({1,99},{5,15})
What is a mistake here? Can you guide me through?

You have to note that Erlang differentiates atoms and identifiers using their case.
Eg:
[a, b, bla, key_1, val_X] is a list of atoms
[A, B, Bla, Key_1, Val_X] is a list of variables
In your code you defined F so that it behaves a certain way for specific atoms as input.
What you should have done (and what they did in your link) is use variable identifiers:
F = fun({Key_X, Val_X},{Key_Y, Val_Y}) -> {Val_X, Key_X} =< {Val_Y, Key_Y} end.
See?

Related

Make multiple replacements in a list by index

I have this program that makes multiple replacements in a list given by
another list with pairs in the format (Index, Elem).
Example:
replace_multiple([A, B, C, D, E], [(2, b), (1, a), (3, c), (4, d)]).
###
should result:
####
Lst = [a, b, c, d, E],
false
####
However this is my output:
A = a,
B = b,
C = c,
D = d
false
####
What am i doing wrong?
What am i doing wrong?
Here are a few things:
You may be unsure about the fact that the list you want to replace contains elements starting with uppercase letters, i.e. logical variables.
In replace_multiple/2, the new element is described as Elem in the head, but as Letter in the body.
In replace_multiple/2, the call to replace/4 has Lst on first and second position. The meaning of a logical variable like Lst is the same as the name of a shared global variable, which, however, cannot be modified unless you replace more logical variables in that logical variable with other stuff. So you have the same structure as "input" and "output". This is probably not what you want.
Same for replace_multiple/2 per se, which should take Lst and build ("return") a modified LstMod given as third argument.
There is fat syntax error at the end of replace/4.
It is better to use [x,y] or x-y than (x,y) as a notation for a pair.

Prolog Sorting List By Rule Position

I am new to Prolog and for the following program:
place(Store,2,a).
place(Store,1,b).
place(Store,3,d).
place(Store,4,c).
placeSort(S,List):- findall(L,place(S,N,L),List).
output: List = [a, b, d, c].
By using placeSort(S,List) , I can find all the elements(a,b,c,d) that contains S (Store).
However what I want to achieve here is to sort the Position of a,b,c,d by using N, however I dont know how to do so as using sort will just sort it out by alphabetical order
placeSort(S,NewList):- findall(L,place(S,N,L),List),sort(List,NewList).
output: List = [a, b, c, d].
what I want to achieve : List = [b,a,d,c]
**I know by using placeSort(S,NewList):- findall([N,L],place(S,N,L),List),sort(List,NewList).
it will return a list of lists sorted by numbers.
output : List = [[1, b], [2, a], [3, d], [4, c]].
but im not sure how to take away the numbers and just take the alphabets instead.
Any help would be greatly appreciated.
SWI-Prolog offers the interesting builtin order_by/2, filling the gap traditional Prolog suffers when compared to SQL, with library(solutionsequences):
?- order_by([asc(X)],place(P,X,W)).
X = 1,
W = b ;
X = 2,
W = a ;
...
So you can avoid full list construction.
The easiest way to do this is to use setof/3 (which sorts by term) and pick a term form that works for you on your sort. In this case, you can collect terms of the form N-X where they satisfy, place(_, N, X):
setof(N-X, place(S,N,X), OrderedList). % Assuming `S` is bound
This will result in:
OrderedList = [1-b, 2-a, 3-d, 4-c]
Then you can use maplist/3 to get your list by defining a simple mapping:
foo(_-X, X).
maplist(foo, OrderedList, List).
This will then give you just the elements you want.
Your complete predicate would look like:
foo(_-X, X).
placeSort(S, List) :-
setof(N-X, place(S,N,X), OrderedList),
maplist(foo, OrderedList, List).
Obviously, you'd choose sensible names for your facts, predicates, and variables. My names (foo, List, OrderedList, S, N, X) are not sufficient, in my opinion, for an application but I am not familiar with your actual problem domain, so this is just for illustration purposes.
As an aside, note that in your facts Store is a variable, so that's not particularly meaningful in the facts. I kept your use of S in your predicate, but it's unclear to me how you really intend to use it.

PROLOG defining 'delete' predicate

delete(X,[X|R],[_|R]).
delete(X,[F|R],[F|S]) :-
delete(X,R,S).
Above is my definition of delete predicate, for delete(X,L,R), intended to delete every occurrence of X in L with result R.
I had queried below, and get "G2397797". What does this string stand for?
?- delete(1,[1,2,3,4,5],X).
X = [_G2397797, 2, 3, 4, 5] .
If you simply correct your first clause and remove the unnecessary anonymous variable, you would get:
delete_each(X, [X|L], L).
delete_each(X, [Y|Ys], [Y|Zs]) :-
delete_each(X, Ys, Zs).
This will use unification, and delete each occurrence of X in the list upon backtracking:
?- delete_each(a, [a,b,a,c], R).
R = [b, a, c] ;
R = [a, b, c] ;
false.
Do you see how this is identical to select/3?
If you want to delete all occurrences of X in the list, you can see the answer by #coder.
In the answer you get X = [_G2397797, 2, 3, 4, 5] . , _G2397797 is not a string it is a variable that is not instantiated. This is due to the clause:
delete(X,[X|R],[_|R]).
which places in the output list an anonymous variable "_". You could write delete(X,[X|R],R).
But this has multiple problems. Firstly it only deletes the first occurrence of X not all because in the above clause when you find one you succeed. Also you haven't thought the case of empty list which is also the base case of the recursion. Finally in your second clause you haven't applied any rule that says F and X differ and this clause give wrong results when F equals to X.
So you could write:
delete(_,[],[]).
delete(X,[X|R],S):-delete(X,R,S).
delete(X,[F|R],[F|S]):-dif(X,F),delete(R,S).

Add a character before each atom in a list in prolog

I am trying to learn Prolog.I am suppose to write a predicate which will place 'bubbles' before each atom in a list.The empty list is unchanged.
?-addbubbles([a,b,8,c],X).
X=[bubbles,a,bubbles,b,8,bubbles,c]
I wrote the foll Code:
Addbubbles([],[]).
addbubbles([H|T],[A|B]) :-append([bubbles],[H],A),addbubbles(T,B).
But the output is not as expected :
?- addbubbles([a,v,2,4,f],M).
M = [[bubbles,a], [bubbles,v], [bubbles,2], [bubbles,4], [bubbles,f]] ;
How can i remove the extra brackets so that i get the output as:
M = [bubbles,a, bubbles,v,bubbles,2,bubbles,4,bubbles,f];
You don't need to use append/3 here. Just write down the specification verbatim:
% The empty list is left alone:
addbubbles([], []).
% Add 'bubbles' before each element in the list (recursively):
addbubbles([Element|OldTail], [bubbles,Element|NewTail]) :-
addbubbles(OldTail, NewTail).
A list has the form [Element1, Element2, Element3… | Tail]. So you can use [bubbles,Element|NewTail] to prepend two elements.
And it works:
?- addbubbles([a,b,8,c],X).
X = [bubbles, a, bubbles, b, bubbles, 8, bubbles, c].
?- addbubbles(X, [bubbles, a, bubbles, b, bubbles, 8, bubbles, c]).
X = [a, b, 8, c].
If you want to use append/3, then you need to flatten the list. C.f. "Flatten a list in Prolog".
But look out for typos in your code. In Prolog you finish clauses with a dot, and the capitalization is important.

append two incomplete lists in prolog

L = [a, b, c|_]. - an example of an incomplete list. how do I append two of these? How do I reverse an incomplete list? Can someone give me tips how to deal with these in general?
append([x|t],y,[x|r]):-append(t,y,r). This is how two lists are appended.
for instance
?- A=[1,2,3|X], B=[a,b,c|Y], X=B.
A = [1, 2, 3, a, b, c|Y],
X = B, B = [a, b, c|Y].
These patterns are of little utility.
As #Daniel Lyons suggests, you can as well use append/3
?- A=[1,2,3|X], B=[a,b,c|Y], append(A,B,C).
A = [1, 2, 3],
X = [],
B = [a, b, c|Y],
C = [1, 2, 3, a, b, c|Y]
You can see the difference between those patterns: first directly binds X to B (1 inference), while append requires a number of inferences equal to first list length, to reach the tail before binding.
You can read more about incomplete data structures here. The most useful pattern is difference lists, the base for dcg.

Resources