4.3. Демонстрация - Числа Фибоначчи
Шаг 1
Посмотрим на ещё одну классическую и простую для рекурсивного решения задачу: функция для получения числа из последовательности Фибоначчи по индексу. Первое её число — 0, второе — 1, а каждое последующее — сумма двух предыдущих. Если вы ещё не решали такую задачу — попробуйте сами найти базовый и рекурсивный случай для этой функции.
import {test} from "./tester"
/*
Примеры:
fibonacci(1) // 0
fibonacci(2) // 1
fibonacci(13) // 144
*/
function fibonacci(index) {
return 0;
}
test(fibonacci(1), 0)
test(fibonacci(2), 1)
test(fibonacci(13), 144)
Шаг 2
Базовых случаев у этой задачи будет два — 0 и 1 для первых двух элементов, которые мы уже знаем.
import {test} from "./tester"
/*
Примеры:
fibonacci(1) // 0
fibonacci(2) // 1
fibonacci(13) // 144
*/
function fibonacci(index) {
if (index === 1) {
return 0;
}
if (index === 2) {
return 1;
}
}
test(fibonacci(1), 0)
test(fibonacci(2), 1)
test(fibonacci(13), 144)
Шаг 3
А в рекурсивном случае мы будем пытаться прийти к базовым — вызывать ту же функцию, но понижая индексы у её аргументов.
import {test} from "./tester"
/*
Примеры:
fibonacci(1) // 0
fibonacci(2) // 1
fibonacci(13) // 144
*/
function fibonacci(index) {
if (index === 1) {
return 0;
}
if (index === 2) {
return 1;
}
return fibonacci(index - 1) + fibonacci(index - 2);
}
test(fibonacci(1), 0)
test(fibonacci(2), 1)
test(fibonacci(13), 144)
Шаг 4
И ещё добавим обработку некорректных входных данных. Как видно на этих двух примерах, рекурсия — довольно простая для использования концепция, нужно лишь научиться сводить «сложные» задачи к их самым простым случаям. Конечно, обе реализации можно написать множеством других более оптимальных по времени и памяти способов, но эти — самые простые для восприятия и написания. Как оптимизировать решение задач через рекурсию мы узнаем чуть позже — в разделе про стек (хотя, казалось бы, при чём тут стек).
import {test} from "./tester"
/*
Примеры:
fibonacci(1) // 0
fibonacci(2) // 1
fibonacci(13) // 144
*/
function fibonacci(index) {
if (index < 1 || !Number.isInteger(index)) {
throw new Error("Индекс должен быть целым числом больше или равным единице!");
}
if (index === 1) {
return 0;
}
if (index === 2) {
return 1;
}
return fibonacci(index - 1) + fibonacci(index - 2);
}
test(fibonacci(1), 0)
test(fibonacci(2), 1)
test(fibonacci(13), 144)
File tester.js
const results = document.getElementById('results')
export function test(left, right) {
const result = document.createElement('li');
if (left === right) {
result.innerHTML = "Тест пройден!";
result.style.color = "green";
} else {
result.innerHTML = `Тест не пройден! ${left} не равно ${right}`;
result.style.color = "red";
}
results.appendChild(result);
}