R: Вопрос для начинающих: рекурсивная функция на функции - PullRequest
3 голосов
/ 27 сентября 2019

У меня есть вопрос.Моя основная проблема с чтением решений в Интернете состоит в том, что я не могу понять 95% из них, потому что ответы обычно слишком технические.

Вопрос: Я создал базовую функцию, которая возвращает один ответ.Теперь мне нужно, чтобы эта функция повторялась N / 2 раза и возвращала N / 2 ответов.

Базовая функция указана ниже.Пользователь вводит функцию с переменной N. Предполагая, что он вводит N = 100, функция генерирует список a, список b и список c.Затем функция подсчитывает, сколько раз критерий достигнут и возвращает значение счетчика.В базовом случае список b создается с первыми 10 элементами списка a, а список c создается с оставшимися N-10 элементами.

f <- function (N) {
  count <- 0
  for (nn in 1:100) {
    a <- sample(1:N)
    b <- a [1:10] 
    c <- a [11:N]
    pass <- which(c>=max(b))
    if (length(pass) == 1) {
        count <- count + 1
    }
  }
  return (count)
}

answer <- f(100)
answer

Рекурсивная функция должна заставить эту базовую функцию повторять N/2 раза.Разделение списка b и c больше не основано на 10 элементах и ​​(N-10) элементах.Теперь он основан на 1) 1, N-1 элементах, затем 2) 2, N-2 элементах, затем 3) 3, N-3 элементах и ​​т. Д. До случая N / 2 (то есть оба списка разделены равномерно).

Как таковой я пробовал это, но это не работает.Мне нужна рекурсивная функция, которая может генерировать N / 2 ответа, то есть один ответ для каждого из случаев.Поскольку я действительно новичок в программировании, я надеюсь, что предложения могут быть явными.У меня может не быть возможности понимать неявные и частичные коды.

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

f <- function (N) {
  for (mm in 1: N/2) {
    number <- list()
    count <- 0
    for (nn in 1:100) {
      a <- sample(1:N)
      b <- a [1:mm] 
      c <- a [mm+1:N]
      pass <- which(c>=max(b))
      if (length(pass) >= 1) {
        count <- count + 1
      }
    }
    number[mm] <- count
  }
}

answer <- f(100)
answer
# NULL

Последний отредактированный код, полезныйкомментатор (Оливер) придумал, как указано ниже.Но это работает только для одного случая.В основном функция пытается разделить список из 100 случайных чисел на 2 части, b и c.Затем он пытается увидеть, содержит ли c ровно одно число, которое больше, чем наибольшее число в b.Петля for (мм в 1: (N / 2)) имитирует непрерывное нарезание для b и c.Начинается с 1 и заканчивается 50 (N / 2).Когда он равен 1, b имеет 1 элемент, а c имеет 100-1 элемент, а когда 2 равен 2, b имеет 2 элемента, а c имеет 98 элементов ... в последнем случае b и c оба имеют 50 элементов.

f <- function (N) {
  for (mm in 1: (N/2)) {
    number <- list()
    count <- 0
    for (nn in 1:100) {
      a <- sample(1:N)
      b <- a [1:mm] 
      c <- a [mm+1:N]
      pass <- which(c>=max(b))
      if (length(pass) == 1) {
        count <- count + 1
      }
    }
    number[mm] <- count
  }
  number
}

bb <- f(100)
bb

[[46]]
NULL

[[47]]
NULL

[[48]]
NULL

[[49]]
NULL

[[50]]
[1] 26

Если код работает правильно, ожидаемые ответы для [46], [47], [48] и [49] должны быть 20+, а не NULL.Я считаю, что код для number[mm] <- count работает не так, как задумано.Я считаю, что number[mm] не успешно передается в окончательный код number, за исключением number[50], который передается правильно.

Ответы [ 2 ]

3 голосов
/ 27 сентября 2019

Добро пожаловать в ТАК, спасибо за хорошо сформулированный вопрос.

Первые вещи прямо.Рекурсия относится к вызову функции в той же функции, что и в (не очень явном) примере ниже:

f <- function(x){
    some code
    n <- f(x2)
    some more code
    return(x3)
}

Теперь к вашей проблеме.Вы близки к ответу, который вы хотите.В процессе запутались три вещи:

  1. Запомните ваши скобки.
  2. Возвращение результата
  3. Сброс number на каждой итерации.

Для 1. R читает код слева направо и будет очень строг в том, как он вычислит ваш код.1:N/2 эквивалентно 1: N/2, что эквивалентно c(1, 2, ..., N) / 2.Вы ищете 1:(N/2) или seq(1, N/2) и, вероятно, хотели бы использовать floor или ceiling для округления неравномерных результатов N/2, таких как 5/2=2.5, 13/2=6.5 и т. Д.

Для 2. в настоящее время вы ничего не возвращаете из своей функции.В R вы можете явно вернуть значение, используя return(...), или вы можете просто напечатать объект / номер как последнюю вещь в вашей функции.

Для 3 обратите внимание, что во внешнем цикле вы звоните number <- list().На каждой итерации внешнего цикла это будет сбрасывать список отсчетов, тем самым удаляя любой предыдущий ответ.Это должно быть перемещено

Объединение их, получение правильного фрагмента кода соответствует приведенному ниже примеру:

f <- function (N) {
  number <- list() # <=== initiate your canister only once.
  for (mm in 1:(N/2)) { #<=== remember parenthesis. Or use seq(1, N/2)
    count <- 0
    for (nn in 1:100) {
      a <- sample(1:N)
      b <- a [1:mm] 
      c <- a [mm+1:N]
      pass <- which(c>=max(b))
      if (length(pass) >= 1) {
        count <- count + 1
      }
    }
    number[mm] <- count
  }
  number #<== or return(number)
}

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

1 голос
/ 27 сентября 2019

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

f <- function(N, d) {
  count <- 0
  for (nn in 1:100) {
    a <- sample(1:N)
    b <- a[1:d]
    c <- a[(d+1):N]
    pass <- sum(c >= max(b))
    if (pass == 1) {
        count <- count + 1
    }
  }
  count
}

set.seed(1)
f(50, 10)
# [1] 16


f2 <- function(N) {
    l <- floor(N/2)
    v <- vector(length=l)
    for (i in 1:l) {
        v[i] <- f(N, i)
    }
    v
}

set.seed(1)
f2(10)
# [1]  9 13 26 30 27

Как отмечалось другими, это не является рекурсивнымфункция, но итеративная.Он перебирает целые числа 1:floor(1/N).


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

fib <- function(x, n) {
    if (n > 0) {
        x <- c(x, sum(tail(x, 2)))
        fib(x, n-1)
    } else {
        x
    }
}

fib(c(1, 1), 10)
#  [1]   1   1   2   3   5   8  13  21  34  55  89 144
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...