'''Тема урока: модуль random
Случайные числа
Модуль random
Аннотация. Урок посвящен модулю random, который содержит функции по работе со случайными числами.

Случайные числа
Случайные числа широко используются в различных задачах программирования:

случайные числа используются в играх. Например, компьютерным играм, которые позволяют игроку подбрасывать игральный
кубик, нужны случайные числа для представления значений кубика. Программы, которые раскрывают игральные карты,
вынимаемые из перетасованной колоды, используют случайные числа для представления достоинства карт;
случайные числа применяются в программах имитационного моделирования. В некоторых симуляциях компьютер должен
случайным образом решить, как будет вести себя человек, животное, насекомое или другое живое существо. Нередко
конструируются формулы, где случайное число используется для определения различных вариантов действий и событий,
происходящих в программе;
случайные числа распространены в статистических программах, случайным образом отбирающих данные для анализа;
случайные числа используются в компьютерной безопасности для шифрования уязвимых данных.
Python предлагает встроенные функции для работы со случайными числами. Эти функции хранятся в модуле random в
стандартной библиотеке.

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

Для использования этих функций в начале программы необходимо подключить модуль, что делается командой import:

import random
После подключения модуля мы можем использовать его функции.

Функция randint()

Функция randint() принимает два обязательных аргумента a и b и возвращает случайное целое число из отрезка
 [a; \, b][a;b].

Следующий код выводит два случайных целых числа: num1 из отрезка [0; 17] и num2 из отрезка [-5; 5] .

import random

num1 = random.randint(0, 17)
num2 = random.randint(-5, 5)

print(num1)
print(num2)
Важно: левая и правая граница a и b включаются в диапазон генерируемых случайных чисел. Результатом вызова функции
random.randint(2, 9) может быть любое число от 22 до 99 включительно.

Следующий код выводит 1010 случайных целых чисел из диапазона [1; \, 100][1;100]:

import random

for _ in range(10):
    print(random.randint(1, 100))
Среди этих чисел возможны повторения, поскольку каждый раз выбирается случайное.

Функция randrange()
Если вы помните, как применять функцию range(), то почувствуете себя непринужденно с функцией randrange().
 Функция randrange() принимает такие же аргументы, что и функция range(). Различие состоит в том, что
 функция randrange()
не возвращает саму последовательность чисел. Вместо этого она возвращает случайно выбранное число из
последовательности чисел.

Следующий код присваивает переменной num случайное число в диапазоне от 00 до 99:

import random

num = random.randrange(10)
Аргумент 1010 задает конечный предел последовательности значений. Функция возвратит случайно выбранное число
из последовательности чисел от 00 до конечного предела, исключая сам предел.

Следующий код задает начальное значение и конечный предел последовательности:

import random

num = random.randrange(5, 10)
Таким образом в переменной num будет храниться случайное число в диапазоне от 55 до 99.

Следующий код задает начальное значение, конечный предел и величину шага:

import random

num = random.randrange(0, 101, 10)
Таким образом в переменной num будет храниться случайное число из последовательности чисел:
 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100.

Функция random()
Функции randint() и randrange() возвращают случайное целое число. А вот функция random() возвращает случайное число
 с плавающей точкой (вещественное число). В функцию random() никаких аргументов не передается. Функция random()
 возвращает случайное число с плавающей точкой в диапазоне от 0.00.0 до 1.01.0 (исключая 1.01.0).

Следующий код выводит случайное число с плавающей точкой из диапазона [0.0; \, 1.0)[0.0;1.0):

import random

num = random.random()
print(num)
Функция uniform()
Функция uniform() тоже возвращает случайное число с плавающей точкой, но при этом она позволяет задавать диапазон
 для отбора значений.

Следующий код выводит случайное число с плавающей точкой из диапазона [1.5; \, 17.3][1.5;17.3]:

import random

num = random.uniform(1.5, 17.3)
print(num)
Начальные значения случайного числа
Числа, генерируемые функциями модуля random, не являются подлинно случайными. Несмотря на то, что обычно их называют
случайными числами, это псевдослучайные числа, вычисляемые на основе формулы. Формула, генерирующая случайные числа,
 должна быть инициализирована начальным значением. Оно используется в вычислении, возвращающем следующее случайное
 число в ряду. Когда модуль random импортируется, он получает системное время из внутреннего генератора тактовых
 импульсов компьютера и использует его как начальное значение. Системное время - целое число, представляющее текущую
 дату и время вплоть до одной сотой секунды. Если бы всегда использовалось одно и то же начальное значение, функции
 генерации случайных чисел всегда  возвращали бы один и тот же ряд псевдослучайных чисел. Поскольку системное время
  меняется каждую сотую долю секунды, можно без опасений утверждать, что всякий раз, когда импортируется модуль
  random, будет сгенерирована отличающаяся от предыдущих последовательность случайных чисел.

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

Следующий код генерирует 1010 случайных чисел, и при этом содержит инструкцию, явно устанавливающую начальное
значение для генератора случайных чисел:

import random

random.seed(17)   # явно устанавливаем начальное значение для генератора случайных чисел

for _ in range(10):
    print(random.randint(1, 100))
Результатом выполнения такого кода может быть:

67
54
39
47
38
23
99
91
91
70
Если выполнить такой код еще раз, то мы получим ту же самую последовательность псевдослучайных чисел.

Примечания
Примечание 1. Подключение модуля следующим образом:

from random import *
позволяет в дальнейшем не писать название модуля и символ точки при вызове функций модуля.

Примечание 2. Функции модуля random на самом деле являются методами одноименного класса random.

Примечание 3. Функция randint() реализована на основе функции randrange() следующим образом:

# Return random integer in range [a, b], including both end points.
def randint(self, a, b):
    return self.randrange(a, b + 1)'''

'''Решение задач
Задача 1. Профессор Тимур преподает вводный курс статистики и попросил вас написать программу, которую он мог бы использовать на занятиях для имитации бросания игральных кубиков. Программа должна случайным образом генерировать два числа в диапазоне от 11 до 66 и показывать их.

Решение. Для генерации целых чисел мы будем использовать функцию randint():

import random

print('Бросаем кубики... ')
print('Значения граней:')
print(random.randint(1, 6))
print(random.randint(1, 6))
Задача 2. В интервью с профессором Тимуром вы выясняете, что он хотел бы использовать программу для имитации нескольких поочередных бросаний кубика.

Решение. Будем использовать цикл while, который имитирует один бросок кубиков и затем спрашивает пользователя,
следует ли сделать еще один бросок. Цикл будет повторяться до тех пор, пока пользователь отвечает "да", набирая букву "д":

import random

again = 'д'
while again.lower() == 'д':
    print('Бросаем кубики... ')
    print('Значения граней:')
    print(random.randint(1, 6))
    print(random.randint(1, 6))
    again = input('Бросить кубики еще раз? (д = да, н = нет): ')
Задача 3. Профессор Тимур был так доволен написанным вами симулятором бросания кубиков, что попросил вас разработать
 еще одну программу. Он хотел бы иметь симулятор десятикратного поочередного подбрасывания монеты. Всякий раз, когда 
 программа имитирует подбрасывание монеты, она должна случайным образом показывать "орла" или "решку".

Решение. Мы можем сымитировать бросание монеты путем генерации случайного числа в диапазоне от 0 до 1. Для генерации
 целых чисел мы будем использовать функцию randint():

import random

for _ in range(10):
    num = random.randint(0, 1)
    if num == 0:
        print('Орел')
    else:
        print('Решка')'''
'''Функция shuffle()
Функция shuffle() принимает список в качестве обязательного аргумента и перемешивает его случайным образом.

Следующий код перемешивает список numbers случайным образом, а затем выводит его содержимое:

import random

numbers = [1, 2, 3, 4, 5, 6, 7, 8]
random.shuffle(numbers)
print(numbers)
Результатом работы такого кода может быть:

[4, 7, 8, 1, 2, 3, 6, 5]
Функция choice()
Функция choice() принимает список (строку) в качестве обязательного аргумента и возвращает один случайный элемент из переданного списка (строки).

Следующий код выводит по одному случайному элементу из строки 'BEEGEEK' и списков [1, 2, 3, 4], ['a', 'b', 'c', 'd']:

import random

print(random.choice('BEEGEEK'))
print(random.choice([1, 2, 3, 4]))
print(random.choice(['a', 'b', 'c', 'd']))
Результатом работы такого кода может быть:

E
3
c
Функция sample()
Функция sample() принимает два обязательных аргумента: список (строку) и количество случайных элементов, а возвращает список случайных элементов в указанном количестве.

Результатом работы кода:

import random
 
numbers = [2, 5, 8, 9, 12]

print(random.sample(numbers, 1))
print(random.sample(numbers, 2))
print(random.sample(numbers, 3))
print(random.sample(numbers, 5))
может быть:

[9]
[12, 5]
[9, 2, 8]
[12, 8, 9, 5, 2]
Количество случайных элементов не должно превышать длину начального списка (строки). Следующий код:

import random
 
numbers = [2, 5, 8, 9, 12]

print(random.sample(numbers, 6))
приведет к ошибке:

ValueError: Sample larger than population or is negative
Примечания
Примечание. Подробнее о модуле random можно почитать тут.'''

import random

numbers = [1, 2, 4, 6, 7, 9]

rand_numbers = random.sample(numbers, 3)
print(rand_numbers)