Лицензия Creative Commons
Содержимое блога доступно по лицензии Creative Commons Атрибуция — С сохранением условий
(Attribution-ShareAlike) 3.0 Unported
, если не указано иное.

понедельник, 10 января 2011 г.

Заполнение массива равным количеством случайных положительных и отрицательных чисел

В процессе решения одной из задач столкнулся с интересной проблемой. Как заполнить массив размером N случайными положительными и отрицательными числами так, чтобы количество отрицательных чисел в массиве было равно количеству положительных? И не подряд (например, сначала отрицательные числа, потом - положительные), а, цитируя знаменитое произведение Льюиса Кэрролла в переводе Бориса Заходера, "строго как попало"?

Дабы отвлечься от конкретного применения рассматриваемого далее алгоритма, "упакую" его в функцию. Эта функция получает на вход массив, его размер и максимальное значение, которое может быть сгенерировано и помещено в одну из ячеек массива (как потом станет ясно, реальное "максимальное" значение будет лишь вполовину заданного). Далее полученный массив заполняется поровну случайными положительными и отрицательными числами в случайном порядке.

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

Генерирую случайное число


Для генерации случайных чисел, мне потребуются библиотеки


#include <stdlib.h>
#include <time.h>


Разумным будет задание размера массива N и максимальное значение MAX для генератора случайных чисел с помощью define:


#define N 10
#define MAX 100


Далее нужно запустить генератор случайных чисел с помощью srand() на основе текущего времени, возвращаемого функцией time(). Внутрь функции я поместил цикл while(), и с каждой новой итерацией будет генерироваться случайное число с помощью функции rand() и сохраняться в переменную buf.

Чтобы генерировать числа от 0 до 99, я должен получить остаток от деления результата работы rand() на MAX.


srand(time(0)); // Завожу генератор случайных чисел
buf = rand() % MAX; // Генерирую случайное число


Отлично, но мне нужно, чтобы генератор случайных чисел генерировал и отрицательные числа. В таком случае, нужно вычесть из полученного случайного числа другое число. Например, если мне требуется получить случайные числа в диапазоне от -50 до 49, то я могу сделать следующее:


buf = rand % MAX - (MAX / 2);


Теперь самое интересное. Мне предстоит...

Заполнение массива


Как заполнить массив одинаковым количеством положительных и отрицательных чисел в случайном порядке? Судя по условию поставленной задачи, количество положительных и отрицательных чисел в массиве размером N должно быть равно N / 2.

Отсюда следует, что можно проследить за количеством накиданных в массив положительных и отрицательных чисел. Так же можно предварительно сохранить случайно сгенерированное число в некий буфер, и посмотреть его знак. На основании этого, принимать решение - заносить очередное сгенерированное число в массив, или нет?

Отлично. Завожу два счётчика, один из которых будет считать количество "положенных" в массив отрицательных чисел, другой - положительных. Цикл while() будет выполняться, пока rand() не сгенерирует достаточное количество случайных чисел для заполнения массива.


int array_fill(int *arr, int len, int max) {
  int max_h = max / 2;
  int len_h = len / 2;
  int buf;
  int p = 0; // Счётчик положительных чисел
  int n = 0; // Счётчик отрицательных чисел
  int i = 0;

  srand(time(0));
  
  while(i < len) {
    buf = rand() % max - max_h;
 
    if((buf < 0) && (n < len_h)) {
      arr[i] = buf;
      n++;
      i++;
    }

    if((buf >= 0) && (p < len_h)) {
      arr[i] = buf;
      p++;
      i++;
    }
    
  }

  return 0;
}

Итак, предположим, что "лимит" на отрицательные числа исчерпан (n == len_h). Цикл будет повторяться, пока в buf не окажется положительное число. То же произойдёт, если p == len_h, только в этом случае цикл будет повторяться до появления в buf отрицательного числа. Таким образом, мы получаем массив, заполненный в равном количестве как положительными, так и отрицательными числами. Задача решена.

Пример вызова функции:


array_fill(arr, N, MAX);



P.S. На самом деле, у этой функции есть один недостаток - при нечётном размере массива она зацикливается. Этот недостаток можно преодолеть, добавив в функцию проверку на чётность размера массива. Если проверка даёт положительный результат, то остаётся сгенерировать ещё одно число и записать его в начало (или конец) массива.

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

Отправить комментарий