Menu
Coddy logo textTech

Рекурсивные функции

Часть раздела Логика и потоки выполнения путешествия по R на Coddy. Урок 50 из 64.

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

fact <- function(n) {
  if (n <= 1) return(1)
  n * fact(n - 1)
}
print(fact(5))

Вывод:

[1] 120

Каждый вызов ждёт завершения меньшего вызова: fact(3) вычисляет 3 * fact(2), который вычисляет 2 * fact(1), а тот возвращает 1. Каждый шаг должен приближать к базовому случаю:

count_down <- function(n) {
  if (n == 0) {
    cat("go\n")
    return(invisible(NULL))
  }
  cat(n, "")
  count_down(n - 1)
}
count_down(3)

Вывод:

3 2 1 go

Рекурсия подходит для данных, содержащих уменьшенные копии самих себя, например для списка, в котором находятся списки. Эта функция складывает все числа, независимо от глубины их вложенности:

deep_sum <- function(x) {
  if (is.numeric(x)) return(sum(x))
  total <- 0
  for (item in x) total <- total + deep_sum(item)
  total
}
print(deep_sum(list(1, list(2, 3), list(list(4)), 5)))

Результат:

[1] 15

Рекурсивный вызов также может разделить задачу пополам. Двоичный поиск проверяет середину отсортированного вектора и продолжает поиск в той половине, которая может содержать искомый элемент:

find <- function(v, target, lo = 1, hi = length(v)) {
  if (lo > hi) return(NA)
  mid <- (lo + hi) %/% 2
  if (v[mid] == target) return(mid)
  if (v[mid] < target) find(v, target, mid + 1, hi) else find(v, target, lo, mid - 1)
}
print(find(c(2, 5, 8, 12, 19), 12))
print(find(c(2, 5, 8, 12, 19), 7))

Результат:

[1] 4
[1] NA
challenge icon

Задание

Легко

Рекурсивно завершите count_digits(n). Число меньше 10 имеет 1 цифру; любое большее число имеет на одну цифру больше, чем n %/% 10. Не преобразуйте число в текст.

Предоставленный код считывает целое число n (0 или больше) и выводит возвращённое значение.

Попробуйте сами

count_digits <- function(n) {
  # Напишите ваш код здесь
  0
}

# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
cat(count_digits(as.numeric(input[1])), sep = "\n")
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и потоки выполнения

Потренируйтесь самостоятельно: Онлайн-компилятор R