I have implemented a function which deleting elements of a list one by one:
remove(_,[])->
[];
remove(Elem, L)->
Rest = lists:delete(Elem,L),
remove(Elem,Rest).
But it hangs when I tried with this example:
L = [1,2,3,4].
remove(hd(L), [L]).
What is wrong with it? Or is there a better way to delete elements in the list one by one starting from the first element of a list.
It makes an infinite loop. First, you call
remove(1, [1,2,3,4]) ->
[2,3,4] = lists:delete(1, [1,2,3,4]),
remove(1, [2,3,4]).
So you call
remove(1, [2,3,4]) ->
[2,3,4] = lists:delete(1, [2,3,4]),
remove(1, [2,3,4]).
And then you call it again with the same input and again and again.
One way to fix it is to check if lists:delete/2 returns same result
remove(Elem, L)->
case lists:delete(Elem,L) of
L -> L;
Rest -> remove(Elem,Rest)
end.
(Function clause remove(_,[]) is not necessary even it doesn't do any harm.)
But there is a more strightforward approach:
remove(_, []) -> [];
remove(H, [H|T]) ->
remove(H, T);
remove(X, [H|T]) ->
[H | remove(X, T)].
Which could be written using list comprehensions:
remove(X, L) ->
[Y || Y <- L, Y =/= X].
The resulting code will be basically the same.
You can also use the lists module, it has a lot of useful functions defined.
Take this for example, for you case:
1> A = [1,2,3,4,5,6,7,8,9,10].
[1,2,3,4,5,6,7,8,9,10]
2> B = [2,3,4].
[2,3,4]
3> lists:filter(fun (Elem) -> not lists:member(Elem, B) end, A ).
[1,5,6,7,8,9,10]
simple answer is
A = [1,2,3,3,4]
B = [3,4]
A -- B = C
[1,2,3,3,4] -- [3,4] = [1,2,3].
Related
I tried with something like this but it doesn't work how I wanted it to do. I'm new kinda new to Haskell, and I don't really know how to do it, and what's wrong.
insert a (x:xs) = insert2 a (x:xs) []
where insert2 el (x:xs) hd =
if (x:xs) == []
then []
else if ( a>=x && a < head(xs))
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd++[x]
main = do
let list =[1 ,2 ,3 ,4 ,5 ,6]
let out = insert 2 list
print out
The output I get is [2,2,3,4,5,6,1]
First a couple of cosmetics:
Ensure indentation is right. When copy/pasting into StackOverflow, it's generally best to use ctrl+k to get it in code-block style.
There's no point matching (x:xs) only to pass the entire thing into your local function.
Omit unnecessary parentheses and use standardised spacing.
With that, your code becomes
insert a allxs = insert2 a allxs []
where insert2 el (x:xs) hd =
if x:xs == []
then []
else if a >= x && a < head xs
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd ++ [x]
main = do
let list = [1, 2, 3, 4, 5, 6]
let out = insert 2 list
print out
Algorithmically speaking, there's no point in using an “accumulator argument” here. It's easier and actually more efficient to directly recurse on the input, and simply pass on the remaining tail after done with the insertion. Also remember to have a base case:
insert a [] = [a]
insert a (x:xs) = ...
You also don't need to use head. You've already pattern-matched the head element with the x:xs pattern. If you did need another list element, you should match that right there too, like
insert a (x:x':xs) = ...
...but you don't in fact need that, x is enough to determine what to do. Namely,
insert a (x:xs)
| a<=x = -- if the list was ordered, this implies that now _all_
-- its elements must be greater or equal a. Do you
-- need any recursion anymore?
| otherwise = -- ok, `x` was smaller, so you need to insert after it.
-- Recursion is needed here.
Here are some hints. It's a lot simpler than you're making it. You definitely don't need a helper function.
insert a [] = ??
insert a (x : xs)
| a <= x = ???
| otherwise = ???
Two things:
Prepending to a list is more efficient than appending to one.
Haskell lets you write separate definitions to avoid having to write single, nested conditional expressions.
There are two kinds of list you can insert into: empty and non-empty. Each can be handled by a separate definition, which the compiler will use to define a single function.
insert a [] = [a]
insert a (x:xs) = ...
The first case is easy: inserting into an empty list produces a singleton list. The second case is tricker: what you do depends on whether a is smaller than x or not. You can use a conditional expression
insert a (x:xs) = if a < x then a : insert x xs else x : insert a xs
thought you may see guards used instead:
insert a (x:xs) | a < x = a : insert x xs
| otherwise = x : insert a xs
In both cases, we know (because the list argument is already sorted) that insert x xs == x : xs, so we can write that directly to "short-circuit" the recursion:
insert a (x:xs) = if a < x then a : x : xs else x : insert a xs
don't complicate! , make simple ...
insertme a list = takeWhile (<a) list ++ [a] ++ dropWhile (<a) list
I am trying to invert two-elements lists in xs. For example, invert [[1,2], [5,6,7], [10,20]] will return [[2,1], [5,6,7], [20,10]]. It doesn't invert [5,6,7] because it is a 3 element list.
So I have written this so far:
invert :: [[a]] -> [[a]]
invert [[]] = [[]]
which is just the type declaration and an empty list case. I am new to Haskell so any suggestions on how to implement this problem would be helpful.
Here's one way to do this:
First we define a function to invert one list (if it has two elements; otherwise we return the list unchanged):
invertOne :: [a] -> [a]
invertOne [x, y] = [y, x]
invertOne xs = xs
Next we apply this function to all elements of an input list:
invert :: [[a]] -> [[a]]
invert xs = map invertOne xs
(Because that's exactly what map does: it applies a function to all elements of a list and collects the results in another list.)
Your inert function just operations on each element individually, so you can express it as a map:
invert xs = map go xs
where go = ...
Here go just inverts a single list according to your rules, i.e.:
go [1,2] = [2,1]
go [4,5,6] = [4,5,6]
go [] = []
The definition of go is pretty straight-forward:
go [a,b] = [b,a]
go xs = xs -- go of anything else is just itself
I would do this:
solution ([a,b]:xs) = [b,a] : solution xs
solution (x:xs) = x : solution xs
solution [] = []
This explicitly handles 2-element lists, leaving everything else alone.
Yes, you could do this with map and an auxiliary function, but for a beginner, understanding the recursion behind it all may be valuable.
Note that your 'empty list case' is not empty. length [[]] is 1.
Examine the following solution:
invert :: [[a]] -> [[a]]
invert = fmap conditionallyInvert
where
conditionallyInvert xs
| lengthOfTwo xs = reverse xs
| otherwise = xs
lengthOfTwo (_:_:_) = True
lengthOfTwo _ = False
I would solve it by comparing the first index of the first list and adding 2 to the index. But I do not know how to check for indexes in prolog.
Also, I would create a counter that ignores what is in the list when the counter is an odd number (if we start to count from 0).
Can you help me?
Example:
everyOther([1,2,3,4,5],[1,3,5]) is true, but everyOther([1,2,3,4,5],[1,2,3]) is not.
We present three logically-pure definitions even though you only need one—variatio delectat:)
Two mutually recursive predicates list_oddies/2 and skipHead_oddies/2:
list_oddies([],[]).
list_oddies([X|Xs],[X|Ys]) :-
skipHead_oddies(Xs,Ys).
skipHead_oddies([],[]).
skipHead_oddies([_|Xs],Ys) :-
list_oddies(Xs,Ys).
The recursive list_oddies/2 and the non-recursive list_headless/2:
list_oddies([],[]).
list_oddies([X|Xs0],[X|Ys]) :-
list_headless(Xs0,Xs),
list_oddies(Xs,Ys).
list_headless([],[]).
list_headless([_|Xs],Xs).
A "one-liner" which uses meta-predicate foldl/4 in combination with Prolog lambdas:
:- use_module(library(lambda)).
list_oddies(As,Bs) :-
foldl(\X^(I-L)^(J-R)^(J is -I,( J < 0 -> L = [X|R] ; L = R )),As,1-Bs,_-[]).
All three implementations avoid the creation of useless choicepoints, but they do it differently:
#1 and #2 use first-argument indexing.
#3 uses (->)/2 and (;)/2 in a logically safe way—using (<)/2 as the condition.
Let's have a look at the queries #WouterBeek gave in his answer!
?- list_oddies([],[]),
list_oddies([a],[a]),
list_oddies([a,b],[a]),
list_oddies([a,b,c],[a,c]),
list_oddies([a,b,c,d],[a,c]),
list_oddies([a,b,c,d,e],[a,c,e]),
list_oddies([a,b,c,d,e,f],[a,c,e]),
list_oddies([a,b,c,d,e,f,g],[a,c,e,g]),
list_oddies([a,b,c,d,e,f,g,h],[a,c,e,g]).
true. % all succeed deterministically
Thanks to logical-purity, we get logically sound answers—even with the most general query:
?- list_oddies(Xs,Ys).
Xs = [], Ys = []
; Xs = [_A], Ys = [_A]
; Xs = [_A,_B], Ys = [_A]
; Xs = [_A,_B,_C], Ys = [_A,_C]
; Xs = [_A,_B,_C,_D], Ys = [_A,_C]
; Xs = [_A,_B,_C,_D,_E], Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F], Ys = [_A,_C,_E]
; Xs = [_A,_B,_C,_D,_E,_F,_G], Ys = [_A,_C,_E,_G]
; Xs = [_A,_B,_C,_D,_E,_F,_G,_H], Ys = [_A,_C,_E,_G]
...
There are two base cases and one recursive case:
From an empty list you cannot take any odd elements.
From a list of length 1 the only element it contains is an odd element.
For lists of length >2 we take the first element but not the second one; the rest of the list is handled in recursion.
The code looks as follows:
odd_ones([], []).
odd_ones([X], [X]):- !.
odd_ones([X,_|T1], [X|T2]):-
odd_ones(T1, T2).
Notice that in Prolog we do not need to maintain an explicit index that has to be incremented etc. We simply use matching: [] matches the empty list, [X] matches a singleton list, and [X,_|T] matches a list of length >2. The | separates the first two elements in the list from the rest of the list (called the "tail" of the list). _ denotes an unnamed variable; we are not interested in even elements.
Also notice the cut (!) which removes the idle choicepoint for the second base case.
Example of use:
?- odd_ones([], X).
X = [].
?- odd_ones([a], X).
X = [a].
?- odd_ones([a,b], X).
X = [a].
?- odd_ones([a,b,c], X).
X = [a, c].
?- odd_ones([a,b,c,d], X).
X = [a, c].
?- odd_ones([a,b,c,d,e], X).
X = [a, c, e].
For example I have a list [1,3,5] and another list [2,4,6], how do I append these two lists in such way it will form into a List of Lists like this: [[1,3,5],[2,4,6]]?
How do I manipulate the list if I add another list at the end [7,8,9] to look like [[1,3,5],[2,4,6],[7,8,9]]?
L1 = [1,3,5],
L2 = [2,4,6],
[L1,L2].
You just need create a list containing both lists.
A = [1,3,5],
B = [2,4,6],
[A, B].
-module(lol).
-export([new/0, append/2, head/1, tail/1]).
new() -> [].
append(H, []) when is_list(H) -> [H];
append(H, T) when is_list(H) -> [H | T].
head([H | _]) when is_list(H) -> H.
tail([_ | T]) -> T.
In the shell you could then:
> Herp = lol:append([1,3,4], lol:new()).
[[1,2,3]]
> Derp = lol:append([4,5,6], Herp).
[[4,5,6],[1,2,3]]
> lol:head(Derp).
[4,5,6]
I leave the rest as exercise for the user.
1> [1,2,3 | [1,2,3]].
[1,2,3,1,2,3]
2> lists:append([1,2,3], [1,2,3]).
[1,2,3,1,2,3]
How can I remove the duplicate from a list in Erlang?
Suppose I have a list like:
[1,1,2,3,4,5,5,6]
How can I get:
[1,2,3,4,5,6]
You could use sets, for example:
my_nonDuplicate_list1() ->
List = [1,1,2,3,4,5,5,6],
Set = sets:from_list(List),
sets:to_list(Set).
This returns [1,2,3,4,5], no more duplicates, but most likely not sorted.
Another possibility without the usage of sets would be:
my_nonDuplicate_list2() ->
List = [1,1,2,3,4,5,5,6],
lists:usort(List).
In this case it returns [1,2,3,4,5], no more duplicates and sorted.
And for those looking to preserve the order of the list:
remove_dups([]) -> [];
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]].
A possible solution that will Preserve the order of the elements to help you learn how to manipulate lists, would involve two functions:
delete_all(Item, [Item | Rest_of_list]) ->
delete_all(Item, Rest_of_list);
delete_all(Item, [Another_item| Rest_of_list]) ->
[Another_item | delete_all(Item, Rest_of_list)];
delete_all(_, []) -> [].
remove_duplicates(List)-> removing(List,[]).
removing([],This) -> lists:reverse(This);
removing([A|Tail],Acc) ->
removing(delete_all(A,Tail),[A|Acc]).
To test,
Eshell V5.9 (abort with ^G)
1> mymod:remove_duplicates([1,2,3,1,2,4,1,2,1]).
[1,2,3,4]
2>
I would do something like this at first to preserve order, though it is not recommended. Remember that AddedStuff ++ Accumulator is OK but Accumulator ++ AddedStuff is really bad.
rm_dup(List) ->
lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
Acc ++ [Elem]
end
end, [], List
).
This solution is much more efficient if you want to preserve order:
rm_dup(List) ->
lists:reverse(lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
[Elem] ++ Acc
end
end, [], List
)).
for my opinion, the best option is to use lists:usort()
But in case you don't want to use BIF's, and you want the list to be sorted, I suggest a version of quick sort, in this implementation you will get the list sorted without duplicate values.
unique_sort([]) -> [];
unique_sort([Pivot|T]) ->
unique_sort ([X || X <- T, X < Pivot ) ]++
[Pivot] ++
unique_sort ([X || X <- T, X > Pivot ]).
Module sets has two functions that can be composed and do the job in an efficient way: sets:from_list/1 returns a set with all the elements of a list (with no duplicated elements from definition) and sets:to_list/1 returns a list with the elements of a set. Here is an example of use:
4> sets:to_list(sets:from_list([1,1,2,3,4,5,5,6])).
[3,6,2,5,1,4]
We could define the function as
nub(L) -> sets:to_list(sets:from_list(L)).