Как рассчитать первое повторение циклической функции? - PullRequest
1 голос
/ 07 мая 2019

Я новичок в Python, и у меня возникла проблема со следующим заданием.

import random
print(random.randint(1, 100))

Как рассчитать, сколько случайных чисел повторяется (с использованием словаря)?

вывод должен выглядеть так:

    >>> repeat (1, 100)
    ([random1, random2, random3, ...], number of loops until the first repetition is reached)

Спасибо.

Ответы [ 7 ]

3 голосов
/ 07 мая 2019

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

2 голосов
/ 07 мая 2019

set здесь больше подходит, чем dict, потому что вы просто хотите записать повторение, здесь значение в dict бесполезно, O (1) раз проверить повторение в set:

import random
def repeat(a, b):
    nums = set()
    count = 0
    while len(nums) == count:
        nums.add(random.randint(a, b))
        count += 1
    return list(nums)
1 голос
/ 07 мая 2019

Попробуйте приведенный ниже код. Это добавляет каждое случайное число в dict и затем использует его, чтобы проверить, существует ли случайное число уже. Вы можете сделать то же самое, используя другие структуры данных, но, поскольку вы упомянули словарь, я использовал его здесь.

import random

rand_dict = {}

i = 0
while True:
    rand_num = random.randint(1,100)
    if rand_num in rand_dict:
        print("random number already in dict. rand_num = %s, Number of Loops = %s" %(rand_num, i))
        break
    else:
        i += 1
        rand_dict[rand_num] = 1

Выход:

random number already in dict. rand_num = 90, Number of Loops = 11
1 голос
/ 07 мая 2019

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

import random
def repeat_generator(min, max):
    random_dict = {}
    while True:
        random_number = random.randint(min, max)
        if random_dict.get(random_number):
            break
        else:
           random_dict[random_number] = 1
    print(random_dict.keys())
1 голос
/ 07 мая 2019

Вы можете сохранить список и добавлять свои случайные числа в этот список, и когда вы обнаружите, что ваше случайное число уже есть в вашем списке, вы нарушаете цикл. Обратите внимание, что это решение O (n), так как вам нужно найти элемент во всем списке

import random

my_list = []

while True:
    #Generate random number
    i = random.randint(1, 100)
    #If it is already in the list, break the loop
    if i in my_list:
        break
    #Append random number to list
    my_list.append(i)

print(my_list)

Вывод может выглядеть как

[5, 58, 84, 53]
[5, 29, 64, 52, 69, 53, 72, 41, 58, 50, 4, 68, 67, 22, 90, 32, 45, 17, 47, 89, 55, 6, 7, 46, 37, 88]
[17, 65, 46, 84, 30, 100, 48, 31, 80, 97, 70, 86, 47, 81, 13, 85, 60, 63, 22, 68, 8, 36, 99]
.....

Предложение O (1), уже указанное @ 6502, состоит в том, чтобы вместо этого добавить ваши случайные числа в качестве ключей словаря, этот поиск будет быстрее O(1)

import random

my_dict = {}

while True:
    #Generate random number
    i = random.randint(1, 100)
    #If it is already in the keys of dict, break the loop
    if i in my_dict:
        break
    #Append random number as key of dict with value 0
    my_dict[i] = 0

print(list(my_dict.keys()))

На самом деле мы можем проверить улучшение, используя модуль timeit, хотя это не заметно, поскольку размер случайного числа составляет всего 1-100

Первый для списка подход

In [21]: import random 
    ...:  
    ...: def get_list(): 
    ...:     my_list = [] 
    ...:     while True: 
    ...:         #Generate random number 
    ...:         i = random.randint(1, 100) 
    ...:         #If it is already in the list, break the loop 
    ...:         if i in my_list: 
    ...:             break 
    ...:         #Append random number to list 
    ...:         my_list.append(i) 
    ...:     return my_list 
    ...:                                                                                                                                                                                                              

In [22]: %timeit get_list()                                                                                                                                                                                           
16.9 µs ± 720 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Тогда для продиктованного подхода

In [27]:                                                                                                                                                                                                              

In [27]: import random 
    ...:  
    ...: def get_list(): 
    ...:     my_dict = {} 
    ...:     while True: 
    ...:         # Generate random number 
    ...:         i = random.randint(1, 100) 
    ...:         # If it is already in the keys of dict, break the loop 
    ...:         if i in my_dict: 
    ...:             break 
    ...:         # Append random number as key of dict with value 0 
    ...:         my_dict[i] = 0 
In [29]: %timeit get_list()                                                                                                                                                                                           
16.1 µs ± 567 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Но разница заметна, если мы используем диапазон, скажем, 1-10000

In [38]: import random 
    ...:  
    ...: def get_list(upper): 
    ...:  
    ...:     my_list = [] 
    ...:     while True: 
    ...:         # Generate random number 
    ...:         i = random.randint(1, upper) 
    ...:         # If it is already in the list, break the loop 
    ...:         if i in my_list: 
    ...:             break 
    ...:         # Append random number to list 
    ...:         my_list.append(i) 
    ...:                                                                                                                                                                                                              

In [39]: %timeit get_list(10000)                                                                                                                                                                                      
287 µs ± 5.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [40]: import random 
    ...:  
    ...: def get_list(upper): 
    ...:    
    ...:     my_dict = {} 
    ...:  
    ...:     while True: 
    ...:         # Generate random number 
    ...:         i = random.randint(1, upper) 
    ...:         # If it is already in the keys of dict, break the loop 
    ...:         if i in my_dict: 
    ...:             break 
    ...:         # Append random number as key of dict with value 0 
    ...:         my_dict[i] = 0 
    ...:                                                                                                                                                                                                              

In [41]:  %timeit get_list(10000)                                                                                                                                                                                     
155 µs ± 2.48 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Вы можете видеть, что подход с использованием списка занял почти вдвое больше времени, чем метод dict!

1 голос
/ 07 мая 2019

Не использует словарь, но функцию repeat:

import random
def repeat(a, b):
    l = []
    while True:
        l.append(random.randint(a, b))
        if len(set(l)) != len(l):
            break
    return l

print(repeat(1, 100))

Вывод:

[13, 76, 32, 41, 59, 34, 43, 91, 28, 17, 53, 20, 46, 67, 37, 88, 16, 6, 92, 34]
0 голосов
/ 07 мая 2019

Вот расширенное решение.

Сначала создайте генератор случайных чисел:

>>> import random
>>> random.seed(100) # to make it repeatable
>>> it = iter(lambda: random.randint(1,100), -1)

Это менее известная форма функции iter: первый аргумент - этофункция, которая вызывается до достижения дозорного.Поскольку randint никогда не вернет -1, это бесконечный генератор случайных чисел:

>>> import itertools
>>> list(itertools.islice(it, 15))
[19, 59, 59, 99, 23, 91, 51, 94, 45, 56, 65, 15, 69, 16, 11]
>>> list(itertools.islice(it, 15))
[95, 59, 34, 7, 85, 83, 27, 43, 30, 40, 99, 27, 23, 19, 25]

Вы можете получить столько случайных чисел, сколько вам нужно.(Функция islice берет «кусочек» итератора).Теперь мы берем числа, а число неизвестно:

>>> seen = set()
>>> list(itertools.takewhile(lambda x: x not in seen and not seen.add(x), it))
[45, 48, 81, 53, 27, 52, 60, 72, 36, 49, 21, 84, 82, 16, 24, 1, 78, 51, 19, 100, 73]

Обратите внимание на побочный эффект: мы создаем пустой набор s для хранения видимых чисел и для каждого x проверяем,x находится в seen (мы видели x раньше) , а затем добавьте x к seen.Хитрость в том, что seen.add(x) всегда возвращает None, поэтому not seen.add(x) всегда True и b and not seen.add(x) == b and True == b.

Для проверки:

>>> random.seed(100) # to make it repeatable
>>> it2 = iter(lambda: random.randint(1,100), -1)
>>> list(itertools.islice(it2, 30, 52))
[45, 48, 81, 53, 27, 52, 60, 72, 36, 49, 21, 84, 82, 16, 24, 1, 78, 51, 19, 100, 73, 21]

21 было повторено.

...