Random без повтора чисел

Random без повтора чисел

Еще в прошлом году мы познакомились со стандартным оператором рандом , отвечающим за генерацию случайных чисел. Оператор очень полезный ,так как нам не приходится лично вбивать данные с клавиатуры или подключать файлы с массивами данных. Однако у рандома как оператора есть один маленький минус : так как числа берутся случайно и ограничение имеют только в диапазоне , то они могут повторятся . Конечно, кого-то это устраивает , однако для некоторых это проблема ,которую приходится решать самому . Совсем недавно меня попросили написать как можно более простую программу, в которой random выводил бы числа так,чтобы ни одно число не повторялось . На самом деле сделать это просто . Как мы знаем ,оператор random выводит случайные числа и они могут повторяться . Особенно это видно при задании узкого диапазона , например если вывести 10 элементов массива ,заполнив их случайными числами в диапазоне от 0 до 9 , то среди них почти всегда есть повторы . Ниже код реализации .

const
  n = 10;

var
  m: array [1..n] of integer;
  i:integer;

begin
  randomize;
  for i := 1 to n do
  begin
    z: m[i] := random(1, 10);
    write(m[i]);
  end;
end.
  

Каков наш алгоритм, позволяющий убрать повтор чисел ? Для того,чтобы числа не повторялись, нам достаточно сделать своего рода фильтр ,который из всех случайных чисел будет брать только те,которых еще не было . Объясняю на примере массива. Смотрим последовательность.

Шаг 1.Заполняем первый элемент массива
Шаг 2.Заполняем второй элемент
Подшаг 1. Сверяем его с первым.
а) Если элементы разные ,то переходим к следующему шагу .
б) Если они одинаковы ,то заполняем второй элемент еще раз до тех пор , пока они не будут неравными.
Шаг 3. Заполняем третий элемент.
Подшаг 1. Сверяем его с первым.
а) Если элементы разные ,то переходим к следующему подшагу .
б) Если они одинаковы ,то заполняем третий элемент еще раз до тех пор , пока они не будут неравными.
Подшаг 2. Сверяем его со вторым.
а) Если элементы разные ,то переходим к следующему шагу.
б) Если они одинаковы ,то заполняем третий элемент еще раз до тех пор , пока они не будут неравными.
Шаг 4. ......

Random без повтора чисел

На картинке изображен момент ,когда шаг равен 3 и происходит сначала сравнение третьего элемента и первого, а затем третьего и второго.И таким вот образом алгоритм повторяется от первого щага до десятого . Каждый раз,когда мы делаем i шагов ,мы делаем i-1 подшагов .

А теперь весь алгоритм . Для алгоритма был использован оператор goto . О нем я уже упоминал в статье выход из цикла .Итак код алгоритма


randomize;
  for i := 1 to n do
  begin
    z: m[i] := random(1, 10);
    for k := 1 to i - 1 do
      if m[k] = m[i] then goto z;
  end;  


Полный код с выводом сгенерированных элементов массива на экран .

label z;
const
  n = 10;

var
  m: array [1..n] of integer;
  i, k: integer;

begin
  randomize;
  for i := 1  to n do
  begin
    z: m[i] := random(1, 10);
    for k := 1 to i - 1 do
      if m[k] = m[i] then goto z;
  end;
  
  for i := 1 to n do
    write(m[i]:3);
end.


Тот же код, но без использования метки.

const
  n = 10;

var
  m: array [1..n] of integer;
  i, k: integer;

begin
  randomize;
  i := 0;
  while i < n do
  begin
    i := i + 1;
    m[i] := random(1, 10);
    for k := 1 to i - 1 do
      if m[k] = m[i] then
      begin
        i := i - 1;
        break;
      end;
  end;
  
  for i := 1 to n do
    write(m[i]:3);
end.




На этом все . В следующий я планирую написать статью о НОД (наименшем общем делителе) . Чтобы не пропустить ее вы можете подписаться на обновления с сайта . Удачи вам)
Понравилась новость? Добавь в закладки!
Хочешь получать свежие новости? Подпишись на обновления с сайта!
Рекомендуем посмотреть:
#1 | написал: UnlimNET | 20 февраля 2012 19:57 | ICQ: 408600480 | Пользователь offline

Группа: Читатели
Публикаций: 0
Комментариев: 5

Спасибо за статью ) Всегда с удовольствием читаю ваши посты


#2 | написал: Mr.Cheater | 20 февраля 2012 21:39 | ICQ: 360239964 | Пользователь offline

Группа: Администраторы
Публикаций: 33
Комментариев: 68

Не за что)
Для этого и создавался сайт
Жаль,что в последнее время много дел,из-за чего я не успеваю писать. Но это ненадолго.
Кстати, советую Вам подписаться ,если Вы еще не подписаны) 


#3 | написал: Евгения | 24 августа 2012 00:42 | ICQ: |

Группа: Гости
Публикаций: 0
Комментариев: 0

Здравствуйте, хотелось бы уточнить, используете ли Вы всегда только PascalABC.net для своих программ? Дело в том, что TurboPascal почему-то "ругается" на массив, когда я ввожу тот же самый код программы, что и у Вас. При запуске программы получаю сообщение об ошибке "type mismatch".

Спасибо.


#4 | написал: Mr.Cheater | 24 августа 2012 13:17 | ICQ: 360239964 | Пользователь offline

Группа: Администраторы
Публикаций: 33
Комментариев: 68

Евгения,
Здравствуйте,

Вообще мы пишем код для  PascalABC и TurboPascal, просто есть некоторые вещи, которые необходимо дописывать, если Вы хотите запустить программу через  TurboPascal. Например пустой readln  в самом конце любой программы (для вывода результата на экран ) или тот же самый random в TurboPascal пишеться по-другому (подробнее в статье Оператор random ). Я проверил код в TurboPascal - все работает. Не могли бы Вы прислать скриншот программы ?

#5 | написал: PascalABC | 1 декабря 2012 02:10 | ICQ: |

Группа: Гости
Публикаций: 0
Комментариев: 0

без меток было бы красивее ... ибо плохой тон .


#6 | написал: SumanDark | 4 декабря 2012 07:30 | ICQ: | Пользователь offline

Группа: Администраторы
Публикаций: 1
Комментариев: 4

Абсолютно согласен ;)


#7 | написал: Mr.Cheater | 4 декабря 2012 10:27 | ICQ: 360239964 | Пользователь offline

Группа: Администраторы
Публикаций: 33
Комментариев: 68

Грамотное использование меток приводит к тому, что код становится короче и прозрачней. Есть пара случаев, когда без меток просто не обойтись. Но здесь согласен: можно и без них. Поэтому добавил вариант без меток


#8 | написал: Данил | 8 июня 2013 13:23 | ICQ: |

Группа: Гости
Публикаций: 0
Комментариев: 0
Хотелось бы спросить,   write(m[i]:3); почему мы делим на 3 ?

#9 | написал: Mr.Cheater | 17 июня 2013 22:37 | ICQ: 360239964 | Пользователь offline

Группа: Администраторы
Публикаций: 33
Комментариев: 68
Данил,

Это не деление на 3
деление обозначается как /
это write(m[i]:3) значит, что при выводе на экран каждому элементу массива будет даваться 3 "клетки", т.е например
числа
3,2,4,10,-12
будут выведены так
3  2  4 10-12
делается это, чтобы числа не стояли вплотную друг к другу

#10 | написал: Антон | 10 августа 2013 22:15 | ICQ: |

Группа: Гости
Публикаций: 0
Комментариев: 0
Способ, конечно, простой. Код небольшой - тоже хорошо. Но такой генератор неповторяющихся чисел будет работать медленно, особенно это будет заметно на больших диапазонах. Как вариант решения предлагаю следующий код: http://pastebin.com/Kz1uT17D

#11 | написал: бряк | 21 марта 2015 13:06 | ICQ: |

Группа: Гости
Публикаций: 0
Комментариев: 0
Не метки так брейк, лол :D

Добавление комментария

Ваше Имя:
Ваш E-Mail:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Вставка исходного кода Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера

Введите два слова, показанных на изображении: