我想生成100到1到100,000之间的数字,每个数字之间的空间至少为10。
一种方法是将100,000除以10,并做样本(1000,100)并得到答案,时间为10,但数字都以0结尾。
如何生成随机数,不仅以0结尾?
答案 0 :(得分:2)
我无法想出一种非递归方式来做到这一点(首先想到的是为你的方法添加“摇摆”,但这几乎肯定会使一些观察结果彼此过于接近),但这将起作用:
set.seed(102438)
include <- 1:100000
smpl <- integer(100)
for (i in 1:length(smpl)){
smpl[i] <- si <- sample(include, 1)
#now remove anything within 10 of the current draw
include <- setdiff(include, (si - 10L):(si + 10L))
}
min(abs(diff(smpl)))
# [1] 1105
答案 1 :(得分:2)
尝试拒绝抽样。不受限制地进行采样,如果任何两个小于10分钟,则将结果扔掉并再次进行直至成功:
repeat {
s <- sample(100000, 100)
mindiff <- min(diff(sort(s)))
if (mindiff >= 10) break
}
从问题的措辞中不清楚,如果排序时连续数字的差异必须是10或更大,或者它们是否必须大于10.我假设前者但使用&gt;在if语句中,如果是后者。
示例从种子123开始,循环仅进行3次迭代(与其他答案的100次和100,000次迭代相比)。下面我们为可重现性添加了set.seed
语句和print
语句,以便我们可以看到使用了多少次迭代。
set.seed(123)
repeat {
s <- sample(100000, 100)
mindiff <- min(diff(sort(s)))
print(mindiff)
if (mindiff >= 10) break
}
,并提供:
[1] 8
[1] 1
[1] 17
答案 2 :(得分:0)
与@ G.Grothendieck类似,我想,重复抽样,但如果不符合您的标准则拒绝。
var getOrdinal = function(n) {
var s = ["th", "st", "nd", "rd"],
v = n % 100;
return n + (s[(v - 20) % 10] || s[v] || s[0]);
};
var test = function(n) {
v = n % 100;
console.log(n, (v - 20) % 10, v, 0, getOrdinal(n))
};
for(i = 0; i < 130; i++) test(i);
答案 3 :(得分:0)
这是不依赖递归的东西:
mysample <- function(n, lower, upper, space) {
b <- ceiling((upper - lower + 1) / (space - 1))
bs <- sample(seq(2, b - 1, by = 2), n - 1)
gr <- split(setdiff(1:b,bs), cumsum(c(0, diff(setdiff(1:b, bs))) != 1))
out <- sapply(gr, function(x) (x[1] - 1) * (space - 1) + ceiling(runif(1) * length(x) * (space - 1)))
out[n] <- min(out[n], upper)
out
}
set.seed(123)
min(replicate(min(diff(mysample(100, 1, 100000, 10))), n = 1000))
# [1] 10
mysample
会返回已排序的序列,但您当然可以使用sample(mysample(...))
。
该函数的思想是将区间[lower,upper]划分为长度space - 1
的块和来自第2,第4,第6,...块的样本n-1
块;这些将被禁止&#34;块,即我们将不会从这些块中获得任何数字。然后剩下的,&#34;允许&#34;块可以是例如第1,第2,第5;在这种情况下,我们有两组连续的块(第一和第二;第五),我们从对应于这两组块的间隔中采样两个数字。我还添加了一个小小的检查,以确定最大数字是否高于上限。
一些结果:
set.seed(123)
upper <- 100000
benchmark(
mysample(100, 1, upper, 10), MichaelChirico(100, 1, upper, 10),
Grothendieck(100, 1, upper, 10), Jonathan(100, 1, upper, 10),
replications = 1, columns = c("test", "relative"))
# test relative
# 3 Grothendieck(100, lower, upper, 10) 1
# 4 Jonathan(100, lower, upper, 10) 344
# 2 MichaelChirico(100, lower, upper, 10) 2133
# 1 mysample(100, lower, upper, 10) 4
upper <- 10000
benchmark(
mysample(100, 1, upper, 10), MichaelChirico(100, 1, upper, 10),
Grothendieck(100, 1, upper, 10), Jonathan(100, 1, upper, 10),
replications = 1, columns = c("test", "relative"))
# test relative
# 3 Grothendieck(100, lower, upper, 10) 132.5
# 4 Jonathan(100, lower, upper, 10) 56.0
# 2 MichaelChirico(100, lower, upper, 10) 27.5
# 1 mysample(100, lower, upper, 10) 1.0
,其中
MichaelChirico <- function(n, lower, upper, space) {
include <- lower:upper
smpl <- integer(n)
for (i in 1:length(smpl)){
smpl[i] <- si <- sample(include, 1)
include <- setdiff(include, (si - space):(si + space))
}
smpl
}
Grothendieck <- function(n, lower, upper, space) {
repeat {
s <- sample(lower:upper, n)
mindiff <- min(diff(sort(s)))
if (mindiff >= space) break
}
s
}
Jonathan <- function(n, lower, upper, space) {
min_gap <- space
samp_vec <- sample(seq(lower,upper,1), 1)
for (isamp in 1:n) {
possible_new_value <- samp_vec[1]
while(any(abs(samp_vec - possible_new_value) < min_gap)) {
possible_new_value <- sample(seq(lower,upper,1), 1)
}
samp_vec <- c(samp_vec, possible_new_value)
}
samp_vec
}