Bezdepbonusu7Программирование: статьи и ответы

Кривая обучения Эликсиру для начинающих - последовательность Фибоначчи

Архив Bezdepbonusu74 мин чтения

Понимание вызова функций и сопоставления с образцом

Прошел месяц с тех пор, как я начал изучать программирование на Эликсире, сегодня мне удалось написать код для получения последовательности Фибоначчи самостоятельно, без обращения к какой-либо документации или помощи моего учителя.

И это заняло всего 2 часа ;)

Позвольте мне провести вас через путешествие.

|› Последовательность Фибоначчи

Таким образом, последовательность Фибоначчи начинается с 0,1, а следующее число в последовательности является суммой двух предыдущих чисел. Образец "0,1,1,2,3,5,8,..."

|› Определение функций и элементов

Чтобы начать последовательность, мне нужно как минимум два целых числа, поэтому я начал со следующего.

defmodule Fibonacci do
 def fib(n) do
  fib(0, 1, [], n)
 end
end

Здесь я определил функцию "fib(n)" ​​с одной арностью "n", которая является входным значением от пользователя, что означает, что программа должна возвращать первое число "n" значений в последовательности Фибоначчи. Это также количество раз, которое должна произойти рекурсия для получения желаемого результата.

В теле вышеуказанной функции я назвал другую функцию "fib(0, 1, [], n)", которая еще не существует, и эта функция имеет 4 арности, и эта функция отличается от той, которую я определил ранее.

|› Сопоставление шаблонов и рекурсия

Теперь я определяю функцию "fib(prev, curr, acc, n)", которая также имеет 4 арности. когда я вызываю эту функцию в строке 3, значения в "fib(0, 1, [], n)" соответствуют образцу функции в строке 6, и эти значения будут скомпилированы в теле функции.

Здесь я также принимаю входное значение от пользователя "n = 5", полученное из функции в строке 2 "fib (n)".

defmodule Fibonacci do
 def fib(n) do
   fib(0, 1, [], n)
 end
 def fib(prev, curr, acc, n) do
   fib(curr, prev + curr, [curr | acc], n - 1)
 end
end

Итак, строка 6 'fib(prev, curr, acc, n)' берет значения из строки 3 'fib(0, 1, [], 5)' и вводит эти значения в строку 7 'fib(curr, prev + curr, [curr | acc], n - 1)", которое станет "fib(1, 1+1, [ 1,[1]], 5-1)". Это когда рекурсия начинается, когда я вызываю функцию в теле той же функции, что означает, что она вызывает ту же функцию с новыми значениями и продолжает добавлять последовательность Фибоначчи к "acc". вот что происходит в строке 7

fib(1, 1+1, [ 1,[1] ], 5-1) → fib(1, 2, [ 1,[1] ], 4)

fib(2, 1+2, [ 2,[1,1] ], 4-1) → fib(2, 3, [ 2,[1,1] ], 3)

fib(3, 2+3, [ 3,[2,1,1] ], 3-1) → fib(3, 5, [ 3,[2,1,1] ], 2)

fib(5, 3+5, [ 5,[3,2,1,1] ], 2-1) -> fib(5, 8, [ 3,[2,1,1] ], 1)

fib(8, 5+8, [ 8,[5,3,2,1,1] ], 1-1) → fib(8, 13, [ 5,[3,2,1,1] ], 0)

Теперь значение "n" стало равным нулю, и мне нужно написать случай/функцию, что происходит, когда "n = 0", что, очевидно, возвращает последовательность в "acc", которая равна "[5,3,2,1,1] '

|› Возврат выхода из аккумулятора

строка 6 - это новая функция с 4 ариями, которая должна соответствовать шаблону с нашей предыдущей функцией, и она должна быть написана перед предыдущей функцией, чтобы компиляция вернула "acc", что "n = 0". я отключил первые два символа подчеркивания, так как они не требуются в этой функции.

defmodule Fibonacci do
 def fib(n) do
   fib(0, 1, [], n)
 end
 def fib(_prev, _curr, acc, 0) do
   acc
 end
 def fib(prev, curr, acc, n) do
 fib(curr, prev + curr, [curr | acc], n - 1)
 end
end

Когда вы компилируете код, он возвращает следующее.

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

|› перечисление

defmodule Fibonacci do
 def fib(n) do
   fib(0, 1, [], n)
 end
 def fib(_prev, _curr, acc, 0) do
   acc |> Enum.reverse()
 end
 def fib(prev, curr, acc, n) do
   fib(curr, prev + curr, [curr | acc], n - 1)
 end
end

Добавьте ‘|› Enum.reverse()’ в строку 7 после ‘acc’, это меняет порядок списка в ‘acc’ и возвращает список, как показано ниже.

|› Изменение входных значений

Теперь для нуля я ввожу "[0]" в "acc" вместо пустого списка "[]", и это вернет 6 значений вместо 5 в последовательности, поэтому я также вычитаю "1" из "n".

defmodule Fibonacci do
 def fib(n) do
   fib(0, 1, [0], n - 1)
 end
 def fib(_prev, _curr, acc, 0) do
   acc |> Enum.reverse()
 end
 def fib(prev, curr, acc, n) do
   fib(curr, prev + curr, [curr | acc], n - 1)
 end
end

После изменения строки 3, ниже возврат.

|› Отказоустойчивый

Я пошел немного дальше, чтобы защитить код от попадания в цикл, если пользователь вводит ноль, используя "если еще".

defmodule Fibonacci do
 def fib(n) do
   if n > 0 do
     fib(0, 1, [0], n - 1)
   else
     "Please enter a value greater than zero"
   end
 end
 def fib(_prev, _curr, acc, 0) do
   acc |> Enum.reverse()
 end
 def fib(prev, curr, acc, n) do
   fib(curr, prev + curr, [curr | acc], n - 1)
 end
end

Возвращает

Финито.. Увидимся позже на другом |›

ElixirCodingProgrammingSoftware Development

Похожие материалы

Статья из архива сайта: перевод и редактура материала сообщества разработчиков. Версии библиотек и инструментов могли измениться, сверяйтесь с официальной документацией.