Как и этот ответ , вы можете сделать выборку отклонения , но равномерное распределение фиксированного числа выборок идеально подходит для очень простого хэш-набора. (Хотя асимптотическое время выполнения может быть несущественным для n=6
.)
#include <stdlib.h> /* (s)rand */
#include <stdio.h> /* printf */
#include <time.h> /* clock */
#include <assert.h> /* assert */
/* Double-pointers are confusing. */
struct Reference { int *ref; };
/* Simple fixed hash set. */
static struct Reference bins[256];
static int nums[6];
static const size_t no_bins = sizeof bins / sizeof *bins,
no_nums = sizeof nums / sizeof *nums;
static size_t count_num;
/* Uniformly distributed numbers are great for hashing, but possibly clump
together under linear probing. */
static size_t hash(const int n) { return ((size_t)n * 21) % no_bins; }
/* Linear probing. */
static struct Reference *probe(const int n) {
size_t bin_index;
struct Reference *bin;
assert(sizeof bins > sizeof nums);
for(bin_index = hash(n); bin = bins + bin_index,
bin->ref && *bin->ref != n; bin_index = (bin_index + 1) % no_bins);
return bin;
}
/* Return whether it's a new value. */
static int put_in_set(const int n) {
struct Reference *bin = probe(n);
int *num;
assert(count_num < no_nums);
if(bin->ref) return 0; /* Already in hash. */
num = nums + count_num++;
*num = n;
bin->ref = num;
return 1;
}
/* http://c-faq.com/lib/randrange.html */
static int rand_range(const unsigned n) {
unsigned int x = (RAND_MAX + 1u) / n;
unsigned int y = x * n;
unsigned int r;
assert(n > 0);
do {
r = rand();
} while(r >= y);
return r / x;
}
/* Generates random numbers between the inputed max and min without
repetition; [min, max] inclusive. */
static int unique_uniform(const int min, const int max) {
int n;
assert(min <= max && (size_t)(max - min) >= count_num);
do { n = rand_range(max - min + 1) + min; } while(!put_in_set(n));
return n;
}
int main(void) {
int n = 6;
srand((int)clock()), rand(); /* My computer always picks the same first? */
while(n--) { printf("%d\n", unique_uniform(1, 50)); }
return EXIT_SUCCESS;
}
Однако, если числа плотно упакованы (например, unique_uniform(1, 6)
,), они отклонят много чисел. Другое решение состоит в том, чтобы принять распределенные числа Пуассона в качестве промежуточной суммы (повторение T(n+1)=T(n)+\mu_{n+1}
,), где ожидаемое значение - это диапазон чисел, разделенных на общие выборки, а затем принять случайную перестановку .