Description:
Be u(n) a sequence beginning with:
u[1] = 1, u[2] = 1, u[3] = 2, u[4] = 3, u[5] = 3, u[6] = 4,
u[7] = 5, u[8] = 5, u[9] = 6, u[10] = 6, u[11] = 6, u[12] = 8,
u[13] = 8, u[14] = 8, u[15] = 10, u[16] = 9, u[17] = 10, u[18] = 11,
u[19] = 11, u[20] = 12, u[21] = 12, u[22] = 12, u[23] = 12 etc...
- How is
u[8]
calculated?
We have u[7] = 5
and u[6] = 4
. These numbers tell us that we have to go backwards from index 8
to index 8 - 5 = 3
and to index 8 - 4 = 4
so to index 3
and 4
.
u[3] = 2
and u[4] = 3
hence u[8] = u[3] + u[4] = 2 + 3 = 5
.
- Another example: let us calculate
u[13]
. At indexes12
and11
we have8
and6
. Going backwards of8
and6
from13
we get indexes13 - 8 = 5
and13 - 6 = 7
.u[5] = 3
andu[7] = 5
sou[13] = u[5] + u[7] = 3 + 5 = 8
.
Task
- Express u(n) as a function of n, u[n - 1], u[n - 2]. (not tested).
- Given two numbers
n, k (integers > 2)
write the functionlength_sup_u_k(n, k) or lengthSupUK or length-sup-u-k
returning the number of termsu[i] >= k
with1 <= i <= n
. If we look above we can see that betweenu[1]
andu[23]
we have fouru[i]
greater or equal to12
:length_sup_u_k(23, 12) => 4
- Given
n (integer > 2)
write the functioncomp(n)
returning the number of times where a term ofu
is less than its predecessor up to and including u[n].
Examples:
u(900) => 455 (not tested)
u(90000) => 44337 (not tested)
length_sup_u_k(23, 12) => 4
length_sup_u_k(50, 10) => 35
length_sup_u_k(500, 100) => 304
comp(23) => 1 (since only u(16) < u(15))
comp(100) => 22
comp(200) => 63
Note: Shell
Shell tests only lengthSupUk
Test Cases:
dotest1 <- function(n, k, expected) {
actual <- lengthSupUK(n, k)
expect_equal(actual, expected)
}
test_that("test lengthSupUK", {
dotest1(50, 25, 2);
dotest1(3332, 973, 1391);
dotest1(2941, 862, 1246);
dotest1(3177, 573, 2047);
dotest1(1745, 645, 474);
dotest1(4451, 663, 3135);
dotest1(1956, 602, 770);
dotest1(1971, 547, 883);
dotest1(1881, 975, 7);
dotest1(1138, 821, 0);
dotest1(1774, 581, 624);
dotest1(1361, 655, 66);
dotest1(3501, 940, 1627);
dotest1(2642, 945, 753);
dotest1(3137, 775, 1571);
dotest1(4903, 557, 3803);
dotest1(3270, 679, 1912);
dotest1(3030, 825, 1393);
dotest1(2936, 655, 1637);
dotest1(2592, 734, 1119);
dotest1(18230, 9181, 201);
dotest1(25071, 6290, 12391);
dotest1(19309, 9486, 457);
dotest1(23165, 8277, 6627);
dotest1(22859, 5283, 12339);
dotest1(30951, 9048, 12876);
dotest1(12862, 7384, 0);
dotest1(48320, 7209, 33898);
dotest1(31984, 8901, 14194);
dotest1(17971, 7807, 2349);
})
dotest2 <- function(n, expected) {
actual <- comp(n)
expect_equal(actual, expected)
}
test_that("test comp", {
dotest2(74626, 37128);
dotest2(71749, 35692);
dotest2(56890, 28281);
dotest2(60441, 30054);
dotest2(21361, 10581);
dotest2(39298, 19536);
dotest2(55599, 27646);
dotest2(11567, 5683);
dotest2(32970, 16347);
dotest2(41250, 20511);
dotest2(44964, 22372);
dotest2(77129, 38415);
dotest2(59973, 29826);
dotest2(47936, 23859);
dotest2(50748, 25211);
dotest2(91785, 45789);
dotest2(37132, 18442);
dotest2(34236, 16987);
dotest2(23933, 11856);
dotest2(44130, 21953);
})
u1777 <- function(n) {
memu <- rep(1, n)
memu[3] <- 2
i <- 3
while (i <= n) {
memu[i] <- memu[i - memu[i - 1]] + memu[i - memu[i - 2]]
i <- i + 1
}
memu
}
comp777 <- function(n) {
memu <- u1777(n)
prev <- 1; cnt <- 0; i = 2;
while (i <= n) {
cur <- memu[i]
if (cur < prev)
cnt <- cnt + 1
prev <- cur
i <- i + 1
}
cnt
}
yTests <- function() {
i <- 0
while (i < 50) {
n <- floor(runif(1, 10000, 25000))
dotest2(n, comp777(n))
i <- i + 1
}
}
test_that("Random tests comp", {
yTests()
})
我的思路与代码
思路
我的思路很简单,先写一个函数,只需要输入n
,就可以得到这种类型的数列的前n
个数,有了这些数,剩下的需要写的两个函数就变得异常简单了。
对于函数lengthSupUK
函数,直接逻辑运算再对逻辑值求和就行了;对于comp
函数,也是算出来之后逻辑运算就行了,不再多说,直接上代码。
代码
fib <- function(n){
u <- c(1,1)
for(i in 3:n) u[i] <- u[i-u[i-2]]+u[i-u[i-1]]
u
}
lengthSupUK <- function(n, k) {
sum(fib(n) >= k)
}
comp <- function(n) {
fibnums <- fib(n)
sum(fibnums[2:n]<fibnums[1:(n-1)])
}
这道题的代码我觉得是蛮简单的,看来看去好像没啥要说明的,如果还有啥疑问,评论区提或者私信我吧。
做一点点补充,我看到有人在写comp
函数的时候,用到了diff
函数,然后判断diff
后的结果是否大于0并做逻辑运算就得到了结果。