Функция с двумя аргументами, которая возвращает, когда аргументы равны
Я пытаюсь создать функцию, которая принимает два аргумента. Это будет неоднократно вызывать первый аргумент, в моем случае
f()
пока f не вернет то же значение 3x подряд. Затем он вызовет второй аргумент
g()
и если g возвращает то же значение, что и f, возвращенное ранее, то функция должна вернуть это значение. В противном случае он вернется назад и снова вызовет первый аргумент f() и повторите цикл.
Это то, что я до сих пор.
call_until = function(f, g) {
while(1) {
n = f %>% chunk(3) %>% filter(f, function(v) length(unique(v)) == 1)
x = n()[1]
if (x == g()) {
return(x)
}
}
}
Например, если f возвращает 4 три раза подряд, перейдите к g. Если g равно тому, что f вернул три раза подряд (что в этом примере равно 4); так что если g == 4, то call_until должен вернуть 4.
3 ответа
Вот еще один пример того, как вы могли бы сделать это
call_until = function(f, g) {
while(TRUE) {
value <- f()
seen <- 1
while(seen < 3) {
next_value <- f()
if (next_value == value) {
seen <- seen + 1
} else {
value <- next_value
seen <- 1
}
}
if (value == g()) {
return(value)
}
}
}
Хотя это имеет значение, если вы должны нарисовать три новых f
значения, если g
не соответствует или только одно новое значение.
Вот несколько полезных функций тестирования. Они просто возвращают значения из вектора по порядку, повторяя при необходимости.
cycler <- function(vals) {
i <- 1
function() {
i<<-i+1
vals[(i-2) %% length(vals)+1]
}
}
f <- cycler(c(1,2,2,2,3,4,5,5,5,1,1))
g <- cycler(c(5,4))
С этим мы получаем
call_until(f, g)
# [1] 5
Рекурсивная функция, вероятно, не лучший выбор, рассмотрите этот ответ как вариант.
f <- function(){
sample(1:2, 1)
}
g <- function(){
sample(1:2, 1)
}
fg <- function(f, g){
res <- c(replicate(3, f()), g())
message(paste("[-] f():", paste(res[1:3], collapse = ","),
"g():", res[4], "\n"))
if(var(res) == 0){
message(paste("[+] Magic value is ", res[1]))
return(invisible(res[1]))
}
return(fg(f, g))
}
fg(f,g)
[-] f(): 1,1,1 g(): 2
[-] f(): 1,1,1 g(): 2
[-] f(): 1,2,2 g(): 1
[-] f(): 2,1,1 g(): 2
[-] f(): 1,1,1 g(): 2
[-] f(): 1,2,2 g(): 1
[-] f(): 1,1,1 g(): 1
[+] Magic value is 1
Вот пример того, как это может быть реализовано:
f <- function(){
return(sample(1:10,1))
}
g <- f
call_until <- function(f, g){
results <- c(f(), f(), f())
test <- g()
while(length(unique(results)) > 1 || test != results[3]){
results <- c(results[2:3], f())
test <- g()
}
return(test)
}
Теперь здесь я создал несколько простых функций f;g
который будет случайным образом выбирать между 1-10
(даже не требуя аргументов в качестве входных данных). Так что, возможно, потребуется адаптировать. Вот некоторые выводы:
> call_until(f,g)
[1] 3
> call_until(f,g)
[1] 7
> call_until(f,g)
[1] 10
> call_until(f,g)
[1] 9