[英]Array of eight random Integers where each Integer has a difference of at least 15 from all others in the array?
我正在嘗試編寫一種方法,該方法創建並返回長度為8且在[25, 725]
范圍內的隨機Integer
數組。
數組中的每個Integer
必須比數組中的所有其他Integer
高或低至少15。但是,我的方法不是返回滿足此要求的數組。
我設置了一個main()
方法,該方法檢查我的方法的輸出100,000次,如果有太靠近的Integers
,則拋出Exception
。
我如何創建一個將返回一個Integers
數組的方法,其中每個Integer
與每個其他Integer
之間的差至少為15?
public class Test {
public static void main(String[] args) throws Exception {
Integer[] distances = new Integer[8];
for (int i = 0; i < 100000; i++) {
distances = createPlanetDistances(distances.length);
// check distances for values within 15
for (int x = 0; x < distances.length; x++) {
for (int y = 0; y < distances.length; y++) {
if (x == y)
continue;
if (Math.abs(distances[x] - distances[y]) < 15) {
System.out.println(distances[x] + " " + distances[y]);
throw new Exception("Doesn't work");
}
}
}
for (int distance : distances)
System.out.print(distance + " ");
System.out.println(System.lineSeparator());
}
}
/**
* Creates an array of distances-from-the-sun for a given number of Planets.
* It does not allow distances to be within 15 of any other distance.
*
* @param planetAmount The number of distances to return.
* @return An array of distances-from-the-sun.
*/
private static Integer[] createPlanetDistances(int planetAmount) {
SplittableRandom random = new SplittableRandom();
final int min = 25;
final int max = 726;
HashSet<Integer> distanceSet = new HashSet<>();
// make sure there are no duplicate Integers
for(int i = 0; i < planetAmount; i++) {
int num = random.nextInt(min, max);
while (distanceSet.contains(num))
num = random.nextInt(min, max);
distanceSet.add(num);
}
// make sure each distance is 15 away from all others
Integer[] distances = distanceSet.toArray(new Integer[]{});
for(int i = 0; i < distances.length; i++) {
// check distances[i] with all other Integers
for (int j = 0; j < distances.length; j++) {
// do not compare an element with itself
if (j == i)
continue;
int difference = Math.abs(distances[i] - distances[j]);
if (difference < 15) {
while (difference < 15) {
distances[i] = random.nextInt(min, max);
difference = Math.abs(distances[i] - distances[j]);
}
// check all Integers again
System.out.println("HERE " + i + " " + j);
i = 0;
break;
}
}
}
return distanceSet.toArray(new Integer[]{});
}
}
要查找MIN
到MAX
(不包括)范圍內相距超過DISTANCE
COUNT
數字,請構建一個TreeSet
並使用ceiling(...)
方法查找附近的值。
例
final int DISTANCE = 15, MIN = 25, MAX = 726, COUNT = 8;
ThreadLocalRandom random = ThreadLocalRandom.current();
TreeSet<Integer> numbers = new TreeSet<>();
while (numbers.size() < COUNT) {
int value = random.nextInt(MIN, MAX);
Integer ceiling = numbers.ceiling(value - DISTANCE);
if (ceiling == null || ceiling > value + DISTANCE)
numbers.add(value);
}
System.out.println(numbers);
樣本輸出
[86, 104, 120, 369, 425, 532, 682, 713]
如果您不希望結果按升序排列,則始終可以對其進行隨機排序。
這個怎么運作
ceiling
方法將返回集合中大於或等於給定值的最小值;如果沒有該值,則返回null。
因此,例如,如果value
為134且DISTANCE
為15,則ceiling(value - DISTANCE)
將找到> = 119的最小值。如果該值> = 149,則我們知道附近的119-149范圍是清晰的,我們可以使用134的值。
您正在生成行星軌道,因此可以單調增加數字。 您生成的每個數字都有以下數字強加的約束,一旦生成,數字又會對其施加約束。
約束:如果要在min
和max
之間生成N
由D
分隔的軌道,則第一個軌道的邊界為[min, max - D * (N - 1)]
。 這僅僅是因為您不能將以下N - 1
行星裝填到小於D * (N - 1)
。
您可以隨時更新第二個約束,因為新的最小值將是最后生成的數字+ D
這是一個簡單的O(n)
實現(假設生成一個隨機數為O(1)
):
final int DISTANCE = 15, MIN = 25, MAX = 726, COUNT = 8;
Random random = Random();
orbits = new int[COUNT];
if(MAX - MIN < DISTANCE * COUNT) {
throw new IllegalArgumentException("Insert pithy comment about COUNT");
}
min = MIN;
for(int i = 0; i < COUNT; i++) {
max = MAX - DISTANCE * (COUNT - i - 1);
orbits[i] = random.nextInt(max - min + 1) + min;
min = orbits[i] + DISTANCE;
}
下面的方法通過消除間距要求,在相應縮短的范圍內均勻地生成值,向后添加間距間隙並改組以隨機順序產生結果,從而避免了接受/拒絕采樣。
static Random r = new Random();
public static ArrayList<Integer>
gen_array(int lower_bound, int upper_bound, int n, int separation) {
upper_bound -= (n - 1) * separation;
if(upper_bound < lower_bound) {
throw new IllegalArgumentException("Infeasible arguments");
}
ArrayList<Integer> ary = new ArrayList<>();
while(ary.size() < n) {
ary.add(lower_bound + r.nextInt(upper_bound - lower_bound + 1));
}
Collections.sort(ary);
for (int i = 0; i < n; ++i) {
ary.set(i, ary.get(i) + i * separation);
}
Collections.shuffle(ary);
return ary;
}
如果使用n
的8值, lower_bound
25, upper_bound
130和separation
15來調用它,則在接受/拒絕方法可能需要大量迭代才能咳嗽的情況下,立即產生正確的結果。答案的唯一值集。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.