Заполнение массива уникальным int - PullRequest
0 голосов
/ 12 июля 2020

У меня есть скетч Arduino, который генерирует случайные числа. Мне нужно заполнить массив 5 уникальными сгенерированными числами. Чтобы сделать это внутри loop(), я сделал следующее:

  for (int i=0; i<5; i++){

number=mappedForNumber(50);

if (isUnique(number)==true){

 numbers[i]=number;

}

}

, где число - это глобальное целое число, а числа - это массив, который также объявлен глобально в верхней части на скетче

функция isUnique выглядит следующим образом:

bool isUnique (int foo){

  bool pepe=true;

   int sizeOfNumbers=sizeof(numbers)/sizeof(numbers[0]);
    
    for (int i=0; i<sizeOfNumbers; i++){

      if (numbers[i]==foo){

        pepe=false;
        break;
      }

    }

  
  return pepe;
  }

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

Я давно не кодировал, и я очень ржавый. Любая помощь будет оценена. Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 12 июля 2020

Вы используете for l oop для заполнения массива чисел. Это для l oop заполнит выбранный индекс числом, если он уникален, и не изменит данные внутри индекса, если это не так.
Чтобы исправить код:

int i = 0;
int number;
while(i < 5)
{
  number = mappedForNumber(50);
  if (isUnique(number) == true)
  {
    numbers[i]=number;
    i++;
  }
}
0 голосов
/ 12 июля 2020

Я бы использовал усеченный алгоритм Фишера-Йейтса для этого, предполагая, что вам нужно часто выбирать наборы из пяти чисел.

Имея колоду «карт», помеченных от 1 до 50, вы перетасовываете свою колоду и возьмите пять верхних карт. Используйте их по своему усмотрению.

Однако, поскольку вам нужно всего пять, вам просто нужно перемешать «пятерку лучших». Это «усеченная» часть Фишера-Йейтса. Перейдите от конца колоды к пяти картам и выберите пять карт под этой картой (включая эту карту), чтобы поменять местами с этой.

Затем, когда вам понадобятся еще пять случайных чисел, перемешайте снова.

// swaps two integers
void swap(int& a, int& b) {
  int temp = a;
  a = b;
  b = temp;
}

// returns a pointer to an array of ints randomly
// selected between consecutive values in [1, 50]
// num_ints_requested must be <= the size of the deck
const int* ShuffleRandomInts(int num_ints_requested) {
  constexpr int kNumInts = 50;
  static bool initialized = false;
  static int deck[kNumInts];

  if (!initialized) {
    for (int i = 0; i < kNumInts; ++i) {
      deck[i] = i + 1;
    }
    initialized = true;
  }

  // do the truncated shuffle
  for (int i = kNumInts - 1; i >= kNumInts - num_ints_requested; --i) {
    int j = random(0, i);
    swap(deck[i], deck[j]);
  }

  return &deck[kNumInts - num_ints_requested];
}

void loop() {
  // do work
  ...

  // get 5 random numbers between 1 and 50
  // and do something with them
  const int* numbers = ShuffleRandomInts(5);
  DoSomethingWithFive(numbers);

  // get 10 random numbers between 1 and 50
  // (this invalidates the previously selected numbers)
  numbers = ShuffleRandomInts(10);
  DoSomethingWithTen(numbers);

  // do other stuff
  ...
}

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

Мы возвращаем указатель на const int чтобы вы случайно не изменили колоду после ее возврата. Если продолжить аналогию с перетасованной колодой, это будет похоже на раздачу кому-то пяти карт и их вытаскивание карт маркером перед тем, как передать их вам для повторного перемешивания. Вам это не нужно, поэтому вы указываете, что вы не можете изменять числа после их возврата.

(Если вам нужно изменить их, вы должны скопировать их в неконстантный int или не- массив const int).

...