List of doubled even numbers. Elixir - list

I'm trying to implement a function called even/2 that takes a list of numbers and returns an equivalent list but one where all even numbers have been doubled. I'm supposed to use the
function rem(n, k) which returns the reminder when dividing n with k.
I understand /2 means takes two arguments.
I tried to solve it by using an anonymous function to check the remainders of each element in the list if it's even, but I don't know how to place it in new list then output it.

One can use rem/2 in guards:
Enum.map(input, fn
even when rem(even, 2) == 0 -> even * 2
odd -> odd
end)

UPDATE/REWRITE: Use this tail recursion
defmodule Main do
def doubleEven( [], output ) do # case of input empty list
Enum.reverse output
end
def doubleEven( [head | tail], output ) do # any other length list
if rem(head, 2) == 0 do
doubleEven(tail, [head*2 | output])
else
doubleEven(tail, [head | output])
end
end
end
Which get called using:
Main.doubleEven( [1,2,3,4,5,6,7,8,9], [] )
and outputs
[1, 4, 3, 8, 5, 12, 7, 16, 9]

Here you go best implementation you can find :P
def double_even([]) do [] end
def double_even([h|t]) do
case rem(h,2) do
0 ->
[h*2|double_even(t)]
_ ->
[h|double_even(t)]
end
end

def even([], acc), do: Enum.reverse(acc)
def even([h|t], acc) when rem(h,2) == 0, do: even(t, [2*h|acc])
def even([h|t], acc), do: even(t, [h|acc])

First, a simple way to do this with one argument:
defmodule Double do
def double([]), do: []
def double([head | tail]) when rem(head, 2) == 0, do: [head * 2 | double(tail)]
def double([head | tail]), do: [head | double(tail)]
end
This uses pattern matching of the argument to assign the first element of the list to the head variable.
when rem(head, 2) == 0 is a guard that means this function clause will only get executed when it is true (the first item of the list is even, in this case).
We then return a new list consisting of the possibly doubled value, and use recursion to compute the rest of the list.
The above method builds up the result in the call stack. I suspect the reason you are asked to use two arguments is to take advantage of tail-call optimisation, which means even though a recursive call it made, no extra stack frames are used. Because we don't have a call stack in which to build the result, we add an extra output argument and build it there:
defmodule Double do
def double([], output), do: Enum.reverse(output)
def double([head | tail], output) when rem(head, 2) == 0, do: double(tail, [head * 2 | output])
def double([head | tail], output), do: double(tail, [head | output])
end
Here we write a function that takes an input and an output list.
The function calls itself until the input has been exhausted (is the empty list []), and builds up the answer in the output list, which it eventually returns. In each call, we prepend the current item to the output list.
iex> Double.double([1,2,3,4], [])
[1, 4, 3, 8]

Related

Reversing list with recursion in Elixir

My task is to take a list and then reverse it recursively, using one parameter.
What I have arrived at is this solution:
def reverse(l) do
[head | tail] = l
cond do
tail == [] ->
head
true ->
[reverse(tail) , head]
end
end
I have attempted having a | instead of a comma in the true statement, but to no avail.
The problem with this solution is that it prints out the following when inputting [1,2,3,4,5]:
[[[[5, 4], 3], 2], 1]
It doesn't actually add the head part to the list aside from when returning the final value of the list. (in this case 5)
One cannot expect implicit flattening for [list, elem] as you do in [reverse(tail), head].
The former is a list, and this is why you receive nested lists back.
One way to approach the problem would be to indeed add lists one to another with reverse(tail) ++ [head]. It’s not efficient though because it would produce new lists on each step and is not tail-recursive.
The proper solution would be to introduce an accumulator to collect the processed items
def reverse(input, acc \\ [])
def reverse([], acc), do: acc
def reverse([head | tail], acc) do
reverse(tail, [head | acc])
end
reverse([1, 2, 3])
#⇒ [3, 2, 1]
I personally like to use pattern matching in this way instead of the cond as I feel like it makes it easier to reason about it.
defmodule M do
def reverse(list) do
reverse_helper(list, [])
end
defp reverse_helper([], reversed) do
reversed
end
defp reverse_helper([h|t], reversed) do
reverse_helper(t, [h|reversed])
end
end
For fixing your solution you could use List.flatten:
#spec reverse(list()) :: list()
def reverse([]), do: []
def reverse([head | tail]) do
cond do
tail == [] ->
[head]
true ->
List.flatten(reverse(tail) ++ head)
end
end
Flatten for example takes [1, [2]] and returns [1, 2].
But this solution is not efficient. You could use #aleksei-matiushkin solutions or you can use foldl which is tail recursive:
#spec reverse_fold(list()) :: list()
def reverse_fold(l) do
List.foldl(l, [], fn x, acc ->
[x | acc]
end)
end

How can I count the number of times an element is greater than its successor?

I'm currently trying to solve the following exercise:
Given a list of Ints, count the number of times, an element is greater than the element that comes after it. The exercise forces me not to use explicit recursions.
Here are some example outputs given function :: [Int] -> Int:
function [1, 2, 3, 4, 5] == 0 -- only increasing numbers
function [5, 4, 3, 2, 1] == 4 -- only decreasing numbers
function [2, 1, 3, 1, 0, 4] == 3
-- 2 > 1
-- 3 > 1
-- 1 > 0
function [1] == 0 -- no successor
function [ ] == 0 -- no numbers at all
I imagined to use in some way foldl but after many attempts and not working idea I had to give up.
How can I count the number of times an element is greater than its successor without using recursion?
First we need to pair up the consecutive elements,
foo :: [Int] -> Int
foo xs = result
where
pairs = zip xs (drop 1 xs)
then we can process each pair
biggers = [ () | (x,y) <- pairs, x > y]
and now we can count them,
result = .......
All the nested names belong to the same, shared, nested scope. result must make use of the value of biggers, and biggers refers to the value of pairs which refers to the value of foo's parameter, xs. Make sure to put these code lines into the same definition, all indented by the same amount as the first one, for pairs, one under the other.
Actually using a left fold is also possible:
foo (h:t) = snd ( foldl' (\ (a, !c) x -> (x, if (a > x) then (c+1) else c))
(h,0) t )
foo [] = 0
I think you'll agree though that this is much less self-apparent than the first definition. Also note that it uses a "bang pattern", !, together with foldl', not foldl, to do the counting as soon as possible as we go along the input list, not delaying it until all the input list is traversed in full as foldl would do, needlessly, harming the overall efficiency.

SML List [1, 2, 3,...n]

I need to create a list [1,2,3...n] without using pre implemented List fuctions. I can make the list backwards by writing :
fun makeList(x : int) =
if x = 0
then []
else x :: makeList(x-1)
Then I could reverse it and get [1,2,3,4] if inputting 4. How would I do this in only one function?
You've made the reverse list in one function and without using the List library.
To make it in the right order, you can use an accumulating argument:
fun makeList 0 result = result
| makeList n result = makeList (n-1) (n :: result)
Testing this:
- makeList 10 [];
> val it = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : int list
This function takes an extra argument in which it accumulates the result in the right order.
This is what trips up other correspondents in this Q&A and what has made previous answerers delete their responses: Either you accept that this makeList takes an extra empty list as initial argument, which is kind of messy, or you nest this function inside another function that hides this mechanism:
fun makeList n =
let fun go 0 result = result
| go i result = go (i-1) (i :: result)
in go n [] end
But then you would not have used one function. Unless you mean one exposed function, since the inner function is only available in the context of the definition of makeList. As the problem statement is unclear about this, answering can be unsatisfactory.
Either you make one function, and allow for its type signature to be different (taking an extra argument), or you make one exposed function and allow for it to have an inner function that accumulates the result in reverse.

Return the n-th element of a list

I want to find the n-th element of my list[1,2,3]. I want to choose element 2, using recursion.
I have already found the length using:
def module T do
def main do
len([1,2,3])
end
def len([]), do: 0
def len([h|t]), do: 1+len(t)
end
There's def a library function for that (Enum.at/2), but if you want your own implementation:
# Little extra to handle negative positions (from the end of the list)
# element_at([1,2,3], -1) == 3
def element_at(list, n) when n < 0 do
element_at(Enum.reverse(list), -n - 1)
end
def element_at([], _), do: nil
def element_at([h | _t], 0), do: h
def element_at([_h | t], n), do: element_at(t, n - 1)
I suppose you want to implement it by yourself. Otherwise there are a lot of functions you my use in the Enum and List modules.
defmodule Test do
def nth_element(list, n) when is_list(list) and is_integer(n) do
case {list, n} do
{[], _} -> nil
{[element | _], 0} -> element
{[_ | rest], _} -> nth_element(rest, n - 1)
end
end
def nth_element(_, _), do: nil
end
Argument n of the nth_element function is the index (it starts with 0) of the element you are looking for. If the list is empty or it has no element at the given index, it returns nil. Otherwise the function uses pattern matching to get an element and the rest of the list. If you are looking for the first element (index = n = 0) then it will return the element. If you are looking for an element at a higher index, the function will be called recursively with the rest of the list and the given index minus one element. This way you find the element you want in the recursion if n == 0. In the case the list is empty but n >= 0 the recursion ends, because of the first function definition and it returns nil.
I saved the module in test.ex. Execution:
$ iex
iex(1)> c "test.ex"
iex(2)> Test.nth_element([1,2,5], 0)
# => 1
iex(3)> Test.nth_element([1,2,5], 1)
# => 2
iex(4)> Test.nth_element([1,2,5], 2)
# => 5
iex(5)> Test.nth_element([1,2,5], 3)
# => nil

Manipulating Lists in Haskell using Higher-Order Functions and Lambda Calculus

I am trying to write a very simple function that takes a list (for example : [1,2,3,1,5]) and returns a list of elements that are directly after a specific element.
What I have reached so far is:
function element list = filter (\x -> element:x) list
My desired output:
function 1 [1,2,3,1,5]
=>   [2,5]
Try this
map snd $ filter ((== x) . fst) $ zip theList (tail theList)
This won't work on an empty list, you will still need extra code to deal with that.
How does this work?
First, note that the values flow from right to left. The ($) operator allows this to happen. So, the first part evaluated is the zip function.
zip theList (tail theList)
For your example above, this would yield
zip [1,2,3,1,5] [2,3,1,5]
equaling
[(1,2), (2, 3), (3, 1), (1,5)]
which is the set of concurrent pairs in the list.
Next, the filter is applied
filter ((== x) . fst) $ ....
In English, what this says is, filter out only the concurrent pairs whose first element equals x. The output is
[(1,2), (1,5)]
Now we have the list of concurrent pairs starting with 1.
Finally, we apply the map
map snd $ ....
This just pulls out the second value of the pair.
map snd [(1,2), (1,5)] = [2,5]
which is the desired value.
Note, my comment above about failing on the empty list.
This is because tail crashes on the empty list
tail [] --error
There are ways to patch this behavior (see the safe package, for instance), but it is mostly bookkeeping at this point, so I left that for you to work out.
Also note that since all of the functions we used are lazy, this approach would work for lists of infinite length as well.
You can do this quite easily with a simple list comprehension, e.g.:
successors xs i = [y | (x,y) <- zip xs (drop 1 xs), x == i]
This will work to your specifications
next x (i:y:ys) -- look at the first two items in the list
| x == i = -- if the first item == x,
y : next x (y:ys) -- take the second, and continue minus the first element
|otherwise = -- not equal,
next x (y:ys) -- so skip that element
next _ [_] = [] -- if there's no second element, then stop
next _ _ = [] -- if the list is empty, stop