2016-02-21 3 views
4

Я хочу, чтобы генерировать 100 чисел от 1 до 100000, где пространство между каждой составляет по меньшей мере 10.Генерация случайных чисел расстоянии друг от друга по меньшей мере, 10 друг от друга

Один из способов заключается в разделении 100000 на 10, и делать выборку (1000 100) и получите ответ, раз 10, но цифры все заканчиваются 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 
2

Попробуйте отбор проб. Выполнить выборку без ограничений и если два меньше, чем 10 друг от друга бросить результат прочь и сделать это снова, пока это не удается:

repeat { 
    s <- sample(100000, 100) 
    mindiff <- min(diff(sort(s))) 
    if (mindiff >= 10) break 
} 

Это не ясно из формулировки вопроса, если различия последовательных чисел при сортировке необходимо должно быть 10 или больше или должно быть больше 10. Я принял первое, но использую> в выражении 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 
+0

Я думаю, что этот подход будет очень быстрым для малых (n_desired/n_initial --ie, 100/100000 здесь), но отвергающие часто, как это поднимается.моя страдает из-за другого недостатка - она ​​потерпит неудачу, если у нас закончится доступная ничья (по голубике, это должно произойти, если n_desired> n_initial/10, грубо, но произойдет для подавляющего большинства путей рисования, поскольку n_desired подходы, которые связаны) – MichaelChirico

0

Подобно @ G.Grothendieck я полагаю, повторить выборку, но отвергают, если она не соответствует вашим критериям.

set.seed(1337) 

## minimum separation 
min_gap <- 10 

## first entry 
samp_vec <- sample(seq(1,1e5L,1), 1) 
for (isamp in 1:100) { 

    possible_new_value <- samp_vec[1] 
    while(any(abs(samp_vec - possible_new_value) < min_gap)) { 
    possible_new_value <- sample(seq(1,1e5L,1), 1) 
    } 
    samp_vec <- c(samp_vec, possible_new_value) 


} 

min(abs(diff(samp_vec))) 
# 92 
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(...)).

Идея функции состоит в том, чтобы разделить интервал [нижний, верхний] на блоки длины space - 1 и на образец n-1 блоков с 2-го, 4-го, 6-го, ... блоков; это будут «запрещенные» блоки, то есть у нас не будет никаких чисел из этих блоков. Затем оставшиеся «разрешенные» блоки могут быть, например, 1, 2, 5; в этом случае мы имеем две группы последовательных блоков (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 
} 
+0

хороший подход. вы должны рандомизировать, являются ли четные или нечетные «запретными» блоки (т. е. «seq (sample (2, 1), b - 1, by = 2)») - вы все равно не получите вселенную возможных «действительных «образцы, но вы получите намного ближе – MichaelChirico

+0

@MichaelChirico, я согласен с тем, что мое решение может быть улучшено в этом направлении, но, рассматривая нечетные блоки, могут быть некоторые осложнения, и я решил избежать их. Вот что я имею в виду; предположим, что 'n = 3' и всего 5 блоков. Из-за того, что блоки 2 и 4 запрещены, мы получаем результат, хотя и не идеальный, путем отбора одного номера из каждого из блоков 1, 3, 5. Если блокировать блоки 1, 3 и 5, нам может потребоваться отбирать 3 числа из группа блоков 3, 4, 5, где возможен сбой. – Julius

Смежные вопросы