Nano Hash - криптовалюты, майнинг, программирование

Ограничение повторяющихся случайных чисел

Я просто хочу знать, как ограничить количество раз, когда появляется случайное число. Я сгенерировал случайные числа от 1 до 10 и хочу, чтобы каждое число отображалось 4 раза.

myArray[i][j] = rand.nextInt(11);

for (int i=0; i < myArray.length; i++) {
   for (int j=0; j < myArray[i].length; j++) {
       myArray[i][j] = rand.nextInt(11);
       System.out.print(" " + myArray[i][j]);

Приведенный выше код создает случайные числа. Просто хочу их ограничить.

11.02.2014

  • Каковы размеры myArray[][]?) 11.02.2014
  • Сколько раз вы вызываете rand.nextInt(11), т.е. сколько элементов у вас есть в вашем массиве? 11.02.2014
  • Несколько подходов рассматриваются здесь. 11.02.2014
  • По крайней мере, не чаще 40 раз :-) Надеюсь... 11.02.2014
  • Я бы предложил создать цикл с другим массивом счетчиков и создать еще один цикл с предложением if в нем, что, если определенный счетчик превысит 4, вы рандомизируете другое число. 11.02.2014
  • Да, кстати... вы включаете ноль в результаты. Вероятно, вам следует использовать (Random.nextInt(10) + 1) вместо этого 11.02.2014
  • Я отредактировал код выше. У меня есть двумерный массив, в котором хранится таблица 15 x 20. Код будет случайным образом заполнять каждую строку и столбец случайными числами от 1 до 10. Я хочу, чтобы он ограничивал повторяющиеся случайные числа в каждой строке до 4. Возможно ли это? 11.02.2014
  • Заполните массив длиной 40 цифрами от 1 до 10, повторенными 4 раза. Затем для каждой строки выполните перетасовку Фишера-Йейтса массива и выберите нужный количество элементов. Вам понадобится только один массив, потому что вы можете перетасовывать его столько раз, сколько захотите. 11.02.2014

Ответы:


1

Мое решение сохраняет результат в arrayList:

public class Example {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    final int range = 10;
    int[] numbers = new int[range + 1];
    int sum = 0;
    final int noOfOccurances = 4;
    final int size = range * noOfOccurances;
    Arrays.fill(numbers, 0);
    Random generator = new Random();
    List<Integer> numbersArray = new ArrayList<>();
    while (sum != size) {
        int randomNumber = generator.nextInt(range) + 1;
        if (numbers[randomNumber] != noOfOccurances) {
            numbers[randomNumber]++;
            sum++;
            numbersArray.add(randomNumber);
        }
    }
    System.out.println(numbersArray);
}
}
11.02.2014
  • хорошо, я скопировал вашу идею в свой ответ 11.02.2014
  • @ ring0 есть только один цикл, поэтому не могли бы вы объяснить, почему сложность равна O (n²)? 11.02.2014
  • Я был не прав: сложность равна O(size) - потому что ваша программа не работает :-) numbers[randomNumber] никогда не увеличивается, поэтому программа останавливается после циклов size, но вы можете получить 2 1, 5 2, .. Как только ваш алгоритм будет исправлен (приращение, где сумма), вы увидите, что когда sum == size-1 последнее число имеет 9/10 вероятность быть выбранным случайным образом, то есть в среднем 10 циклов, чтобы получить это число. Вероятность уменьшается с предыдущими номерами - но если вам не повезет, вы найдете 4 последних одинаковых номера! или в среднем 40 петель... Расчет не делал, но должно быть близко к O(n²) 11.02.2014
  • Если диапазон и количество вхождений фиксированы, и вы генерируете весь список чисел, этот подход дает тот же результат, что и помещение всех чисел в список, а затем перемешивание списка, но крайне неэффективно. Смотрите ответ giorashc (включая комментарии) для гораздо лучшего решения с тем же результатом. 12.02.2014

  • 2

    Поскольку вы ограничены 10 * 4 = 40 числами, вы можете использовать список и рандомизировать индекс:

    List<Integer> numbers = new ArrayList<Integer>();
    for (int i = 1; i < 11; ++i) {
       for (int j = 0; j < 4; ++j) 
          numbers.add(i);
    }
    

    И затем, когда вы назначаете случайное число:

    int i = rand.nextInt(numbers.size());
    myArray[i][j] = numbers.get(i);
    numbers.remove(i);
    

    Это предполагает, что ваш двумерный файл не будет содержать более 40 чисел.

    11.02.2014
  • Вам не понадобится косвенное обращение через случайный индекс, если вы просто перемешать список, а затем всегда удалять первую или последнюю запись. 11.02.2014
  • Вы будете перемешивать список только после создания, а не на каждой итерации. 11.02.2014

  • 3

    Как насчет хранения количества сгенерированных целых чисел в массиве, карте или чем-то еще?

    Map<Integer, Integer> randomCounts = new HashMap<Integer, Integer>(); 
    ... your for loops
    myArray[i][j] = rand.nextInt(11);
    if (randomCounts.containsKey(myArray[i][j])) { 
       randomCounts.put(myArray[i][j],randomCounts.get(myArray[i][j])+1);
    } else {
       randomCounts.put(myArray[i][j],1);
    }
    

    И если вы хотите их проверить, просто просмотрите свою карту и вуаля. :)

    11.02.2014
  • Пока количество сгенерированных значений фиксировано, я бы просто использовал массив целых чисел и сделал randomCounts[randomNumber]++ Но это само по себе не ограничивает повторение одного числа, оно только регистрирует его... 11.02.2014
  • Хм... Спасибо за обзор! Я выбираю Map, а не массивы, потому что так легче проверить, генерируется ли какое-либо из чисел более 5 раз — вместо меня будет работать randomCounts.containsValue(5) (но Collections сделает это и для массивов). :) Кстати, почему вы используете массивы? 11.02.2014
  • Просто потому, что у массивов меньше накладных расходов. 12.02.2014

  • 4

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

    import java.util.Random;
    
    public class rndNumberGenerator {
    
        public static void main (String[] args) {
    
            int[][] myArray = new int[2][5];
            Random rand = new Random();
            int randomNumber;
    
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 5; j++) {
    
                    do {
                        randomNumber = rand.nextInt(11);
                    } while(overMax(myArray, randomNumber) == true);
    
                    myArray[i][j] = randomNumber;
    
                    System.out.print(" " + myArray[i][j]);
    
                }
            }
    
        }
    
        public static boolean overMax(int[][] array, int number) {
    
            int max = 4;
            int count = 0;
    
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 5; j++) {
    
                    if (array[i][j] == number) {
                        count++;
                    }
    
                }
            }
    
            if (count >= max)
                return true;
            else
                return false;
    
        }
    }
    

    Надеюсь, это помогло вам, если у вас есть другие вопросы, не стесняйтесь спрашивать.

    11.02.2014

    5

    Я принимаю предложение pshemek (голосовать за): вместо ArrayList я использую Set, потому что он не может содержать повторяющиеся числа, и вам не нужно усиливать контроль.

    Реализация: копия{правая, левая принадлежит пшемеку, я лишь расширил идею :)

    public class Example {
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            int[] numbers = new int[11];
            int sum = 0;
            final int range = 10;
            final int noOfOccurances = 4;
            Arrays.fill(numbers, 0);
            Random generator = new Random();
            Set<Integer> numbersArray = new TreeSet<Integer>();
            while (sum != range * noOfOccurances) {
                int randomNumber = generator.nextInt(range) + 1;
                sum++;//correction for first comment
                numbersArray.add(randomNumber); // randomNumber will never be twice: a Set cointains ever one and only one instance of an determinated element
            }
            System.out.println(numbersArray);
        }
    
      }//end class
    
    11.02.2014
  • где вы увеличиваете сумму. 11.02.2014

  • 6

    Вы можете написать свой собственный:

    public static class CountedRandom {
        // My rng.
        Random rand = new Random();
        // Keeps track of the counts so far.
        Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
        // The limit I must apply.
        final int limit;
    
        public CountedRandom(int limit) {
            this.limit = limit;
        }
    
        public int nextInt(int l) {
            int r;
            do {
                // Keep getting a new number until we hit one that has'n been overused.
                r = rand.nextInt(l);
            } while (count(r) >= limit);
            return r;
        }
    
        private int count(int r) {
            // How many times have we seen this one so far.
            Integer counted = counts.get(r);
            if ( counted == null ) {
                // Never!
                counted = new Integer(0);
            }
            // Remember the new value.
            counts.put(r, counted + 1);
            // Returns 0 first time around.
            return counted;
        }
    }
    
    public void test() {
        CountedRandom cr = new CountedRandom(4);
        for ( int i = 0; i < 50; i++ ) {
            System.out.print(cr.nextInt(4)+",");
        }
        System.out.println();
    }
    

    Обратите внимание, что это зависнет, если вы запросите слишком много чисел в слишком маленьком диапазоне (как у меня в моем тесте).

    Отпечатки

    2,0,1,2,1,1,3,3,0,3,0,2,2,0,1,3,
    

    а потом зависает.

    11.02.2014
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..