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

#dart

Вопрос:

У меня есть два списка чисел, один от 0 до 100, а другой от 0 до 30. Как сгенерировать комбинацию случайных чисел из этих списков при нажатии кнопки, не повторяя одну и ту же комбинацию в течение одного дня в flutter

 import 'dart:math';
Num1 = Random().nextInt(100); Num2 = Random().nextInt(30);
DateTime now = new DateTime.now();
DateTime date = new DateTime(now.year, now.month, now.day);
 

При нажатии кнопки в один и тот же день одна и та же комбинация цифр не должна возникать.
Пример: При первом нажатии кнопки скажите
Num1 = 4 и Num2 = 5

Когда кнопка нажата в другое время в тот же день, предыдущие результаты Num1= 4 и Num2= 5 не должны возникать.

Пожалуйста, опубликуйте немного логики..спасибо

Ответ №1:

Насколько я вижу, вы можете использовать две разные стратегии. Вы можете либо отслеживать созданные вами пары, либо отслеживать их. Или вы можете сгенерировать все пары, сохранить их в коллекции и удалить из этой коллекции, когда вы предоставите случайную пару.

Я создал следующий пример последнего предложенного решения:

 import 'dart:collection';

void main() {
  final generator = RandomPairGenerator(maxNum1: 100, maxNum2: 30);

  print(generator.getRandomAndUniquePair()); // (50, 27)
  print(generator.getRandomAndUniquePair()); // (51, 12)
  print(generator.getRandomAndUniquePair()); // (89, 16)
  print(generator.getRandomAndUniquePair()); // (29, 9)
  print(generator.getRandomAndUniquePair()); // (28, 0)
}

class RandomPairGenerator {
  final Queue<Pair> _pairs;

  RandomPairGenerator({required int maxNum1, required int maxNum2})
      : _pairs = Queue.of([
          for (var num1 = 0; num1 < maxNum1; num1  )
            for (var num2 = 0; num2 < maxNum2; num2  ) Pair(num1, num2)
        ]..shuffle());

  Pair getRandomAndUniquePair() => _pairs.removeFirst();
}

class Pair {
  final int num1, num2;

  Pair(this.num1, this.num2);

  @override
  String toString() => '($num1, $num2)';
}
 

Вместо того, чтобы вызывать генератор случайных чисел для каждой пары , проще просто сгенерировать все возможные пары в a List , перемешать List и затем сохранить их в a Queue , которые оптимизированы для удаления (и добавления) элементов либо с начала, либо с начала.

Редактировать

Вот (не очень эффективный) пример другого подхода, при котором мы сохраняем генерируемые нами числа, чтобы не генерировать их снова:

 import 'dart:math';
import 'package:quiver/core.dart';

void main() {
  final generator = RandomPairGenerator(maxNum1: 2, maxNum2: 2);

  print(generator.getRandomAndUniquePair()); // (8, 12)
  print(generator.getRandomAndUniquePair()); // (81, 6)
  print(generator.getRandomAndUniquePair()); // (53, 21)
  print(generator.getRandomAndUniquePair()); // (81, 6)
  print(generator.getRandomAndUniquePair()); // (58, 18)
}

class RandomPairGenerator {
  final int maxNum1;
  final int maxNum2;
  final Random _random = Random();
  final Set<Pair> _previousPairs = {};

  RandomPairGenerator({required this.maxNum1, required this.maxNum2});

  Pair getRandomAndUniquePair() {
    Pair pair;

    do {
      pair = Pair(_random.nextInt(maxNum1), _random.nextInt(maxNum2));
    } while (!_previousPairs.add(pair));

    return pair;
  }
}

class Pair {
  final int num1, num2;

  Pair(this.num1, this.num2);

  @override
  String toString() => '($num1, $num2)';

  @override
  int get hashCode => hash2(num1, num2);

  @override
  bool operator ==(Object other) =>
      other is Pair amp;amp; other.num1 == num1 amp;amp; other.num2 == num2;
}
 

ПРИМЕЧАНИЕ: Основная проблема с этим решением заключается в том, что стоимость выполнения будет бесконечной, если мы попытаемся сгенерировать больше возможных чисел. Причина в том, что мы на самом деле просто пытаемся сгенерировать а Pair , а затем проверяем, было ли это Pair уже сгенерировано.

Чем больше Pair мы создали в прошлом, тем меньше доступно. Таким образом, вероятность случайного создания равного по возрастет, и, следовательно, потребуется больше циклов, пока мы не получим уникальный Pair .

Я не уверен, сможем ли мы добиться большего успеха с помощью этого подхода, если не сделаем что-то подобное моему предыдущему решению.

ПРАВКА 2

Я думаю, что лучшее, что вы можете сделать, это объединить два решения в нечто подобное:

 import 'dart:collection';
import 'package:quiver/core.dart';

void main() {
  final generator = RandomPairGenerator(
      maxNum1: 2, maxNum2: 2, previousGenerated: {const Pair(1, 1)});

  print(generator.getRandomAndUniquePair()); // (0, 1)
  print(generator.getRandomAndUniquePair()); // (1, 0)
  print(generator.getRandomAndUniquePair()); // (0, 0)
  print(generator.previousGenerated); // {(1, 1), (1, 0), (0, 0), (0, 1)}
  print(generator.getRandomAndUniquePair()); // Exception: No more random Pairs available!
}

class RandomPairGenerator {
  final Set<Pair> _previousGenerated;
  final Queue<Pair> _pairs;

  RandomPairGenerator(
      {required int maxNum1,
      required int maxNum2,
      Set<Pair>? previousGenerated})
      : _pairs = Queue.of([
          ...{
            for (var num1 = 0; num1 < maxNum1; num1  )
              for (var num2 = 0; num2 < maxNum2; num2  ) Pair(num1, num2)
          }.difference(previousGenerated ?? {})
        ]..shuffle()),
        this._previousGenerated = previousGenerated ?? {};

  Pair getRandomAndUniquePair() {
    if (_pairs.isEmpty) {
      throw Exception('No more random Pairs available!');
    }

    final pair = _pairs.removeFirst();
    _previousGenerated.add(pair);
    return pair;
  }

  Set<Pair> get previousGenerated => {..._previousGenerated};
}

class Pair {
  final int num1, num2;

  const Pair(this.num1, this.num2);

  @override
  String toString() => '($num1, $num2)';

  @override
  int get hashCode => hash2(num1, num2);

  @override
  bool operator ==(Object other) =>
      other is Pair amp;amp; other.num1 == num1 amp;amp; other.num2 == num2;
}
 

С помощью этого вы можете предоставить Set список уже сгенерированных Pair объектов и получить генератор, который их не генерирует. Вы также можете извлечь a Set из всех чисел, которые он уже сгенерировал, чтобы сохранить его и использовать в следующий раз, когда вам понадобится создать a RandomPairGenerator .

Комментарии:

1. Спасибо за решение.. Когда пары генерируются в каком-то другом экземпляре или в какое-то другое время в этот день, есть вероятность, что пара повторится..

2. Вместо того, чтобы генерировать все пары в начале и хранить в очереди, мы можем вызвать случайную пару один раз и сохранить ее в массиве списка.. Когда кнопка будет нажата в следующий раз, проверьте условие, если оно возникло раньше, а затем сгенерируйте другое число и сохраните его в приведенном выше массиве..Можем ли мы сделать так?

3. @AzReddy Ну, мы никогда не сможем создать генератор, который защитит вас от повторяющихся шаблонов, если у нас нет центрального экземпляра, который предоставляет указанные номера (например, сервер). Вопрос о том, следует ли вам сгенерировать все или сохранить сгенерированные данные, в основном связан с эффективностью и количеством чисел, которые вы собираетесь сгенерировать. Но я приведу вам пример сохранения чисел, которые у нас уже есть.