Ecco cosa farei:
Per prima cosa inizia con un array la dimensione del numero di intervalli per tenere traccia della lunghezza di ogni intervallo. Chiamiamo questo bucket_sizes[number_of_ranges]
- Inizializza la dimensione di ogni bucket con la lunghezza più uniforme possibile:
(max-min+1)/number_of_ranges
(divisione intera)
- Quindi, trova l'eccedenza che non può essere adattata in modo uniforme in ogni segmento,
(max-min+1) % number_of_ranges
(resto della divisione intera)
- Distribuisci l'eccedenza il più uniformemente possibile tra ciascun bucket (inizia dall'indice 0, aggiungi 1 a ciascun bucket mentre sottrai 1 dall'eccedenza. Se l'indice esegue il wrapping alla fine dell'array bucket_size, inizia di nuovo dall'indice 0 e continua finché il surplus non è 0 ).
Ora che conosciamo le dimensioni di ciascun bucket, possiamo generare gli intervalli:
for (i=0, k=min; i<number_of_ranges; i++) {
ranges[i].lo = k;
ranges[i].hi = k+bucket_sizes[i]-1;
k += bucket_sizes[i];
}
Per trovare l'intervallo di un numero specifico, semplicemente itera l'array ranges
e abbina l'intervallo in cui ranges[i].lo <= number <= ranges[i].hi
.
Ecco il codice sorgente completo che ho usato per testarlo (è scritto in C):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct range
{
int lo;
int hi;
};
int generate_ranges(int min, int max, int number_of_ranges, struct range ranges[])
{
int i;
int bucket_sizes[number_of_ranges];
int even_length = (max-min+1)/number_of_ranges;
for(i=0; i<number_of_ranges; ++i)
bucket_sizes[i] = even_length;
/* distribute surplus as evenly as possible across buckets */
int surplus = (max-min+1)%number_of_ranges;
for(i=0; surplus>0; --surplus, i=(i+1)%number_of_ranges)
bucket_sizes[i] += 1;
int n=0, k=min;
for(i=0; i<number_of_ranges && k<=max; ++i, ++n){
ranges[i].lo=k;
ranges[i].hi=k+bucket_sizes[i]-1;
k += bucket_sizes[i];
}
return n;
}
int number_range_index(int number, int number_of_ranges, const struct range ranges[]) {
int i;
for(i=0; i<number_of_ranges; ++i)
if(number >= ranges[i].lo && number <= ranges[i].hi)
return i;
return number_of_ranges;
}
#define MAX_RANGES 50
int main(int argc, char *argv[]) {
int i;
struct range ranges[MAX_RANGES];
if(argc != 5) {
printf("usage: %s <min> <max> <number_of_ranges> <number>\n", argv[0]);
return EXIT_FAILURE;
}
int min = atoi(argv[1]);
int max = atoi(argv[2]);
int number_of_ranges = atoi(argv[3]);
int number = atoi(argv[4]);
assert(max > min);
assert(number >= min && number <= max);
assert(number_of_ranges > 0);
assert(number_of_ranges <= MAX_RANGES);
printf("min=%d max=%d number_of_ranges=%d number=%d\n\n", min, max, number_of_ranges, number);
int n = generate_ranges(min, max, number_of_ranges, ranges);
for(i=0; i<number_of_ranges; i++) {
if(i<n)
printf("%s[%d-%d]", i>0?",":"", ranges[i].lo, ranges[i].hi);
else
printf("%s[]", i>0?",":"");
}
printf("\n\n");
int number_idx = number_range_index(number, n, ranges);
printf("method(%d)->[%d,%d]\n", number, ranges[number_idx].lo, ranges[number_idx].hi);
return EXIT_SUCCESS;
}