簡體   English   中英

八個隨機整數的數組,其中每個整數與數組中所有其他整數的差值至少為15?

[英]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[]{});
    }
}

要查找MINMAX (不包括)范圍內相距超過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的值。

您正在生成行星軌道,因此可以單調增加數字。 您生成的每個數字都有以下數字強加的約束,一旦生成,數字又會對其施加約束。

約束:如果要在minmax之間生成ND分隔的軌道,則第一個軌道的邊界為[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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM