Список удвоенных четных чисел.Эликсир - PullRequest
0 голосов
/ 16 февраля 2019

Я пытаюсь реализовать функцию с именем even/2, которая принимает список чисел и возвращает эквивалентный список, но в котором все четные числа были удвоены.Я должен использовать функцию rem(n, k), которая возвращает напоминание при делении n на k.

Я понимаю, /2 означает, что принимает два аргумента.

Я пыталсярешить эту проблему с помощью анонимной функции, чтобы проверить остатки каждого элемента в списке, если он четный, но я не знаю, как поместить его в новый список, а затем вывести его.

Ответы [ 5 ]

0 голосов
/ 07 марта 2019
  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])
0 голосов
/ 07 марта 2019

Здесь вы найдете лучшую реализацию, которую сможете найти: 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
0 голосов
/ 16 февраля 2019

Можно использовать rem/2 в охранниках:

Enum.map(input, fn
  even when rem(even, 2) == 0 -> even * 2
  odd -> odd
end)
0 голосов
/ 17 февраля 2019

Во-первых, простой способ сделать это с одним аргументом:

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

При этом используется сопоставление с шаблоном аргумента для назначения первого элемента списка переменной head.

when rem(head, 2) == 0 - это защита, означающая, что это функциональное предложение будет выполняться только тогда, когда оно истинно (в данном случае первый элемент списка является четным).

Затем мы возвращаем новый список, состоящий извозможно удвоенное значение и использовать рекурсию для вычисления остальной части списка.

Приведенный выше метод создает результат в стеке вызовов.Я подозреваю, что причина, по которой вас просят использовать два аргумента, состоит в том, чтобы воспользоваться оптимизацией хвостового вызова , что означает, что даже при совершении рекурсивного вызова он не использует никаких дополнительных стековых фреймов.Поскольку у нас нет стека вызовов для построения результата, мы добавляем дополнительный аргумент output и собираем его там:

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

Здесь мы пишем функцию, которая принимает input иoutput список.Функция вызывает себя до тех пор, пока input не будет исчерпана (это пустой список []), и выстраивает ответ в списке output, который она в конечном итоге возвращает.При каждом вызове мы добавляем текущий элемент в список вывода.

iex> Double.double([1,2,3,4], [])
[1, 4, 3, 8]
0 голосов
/ 16 февраля 2019

ОБНОВЛЕНИЕ / ОБНОВЛЕНИЕ : используйте эту хвостовую рекурсию

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  

, которая вызывается с использованием:

Main.doubleEven( [1,2,3,4,5,6,7,8,9], [] )

и выводит

[1, 4, 3, 8, 5, 12, 7, 16, 9]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...