fizzbuzz в Python с использованием случайных чисел, как это работает?

Мне трудно понять, как работает приведенный ниже код:

import random

for i in range(0, 100):
    if not i % 15:
        random.seed(1178741599)
    print [i+1, "Fizz", "Buzz", "FizzBuzz"][random.randint(0,3)]

Я понимаю, что когда i делится на 15, random будет использовать тот же seed и, следовательно, randint(0, 3) всегда будет возвращать один и тот же индекс, но когда я попытался

for i in range(100):
    random.seed(1178741599)
    print random.randint(0,3) #always print 0

приведенный выше код всегда печатает 0, не должно ли это быть 3 (как индекс "FizzBuzz" в списке [i+1, "Fizz", "Buzz", "FizzBuzz"]?(это правильное поведение и соответствует i+1 в списке.)

А что если i делится на 3 или 5?

В чем магия семени 1178741599?

Изменить: как указал jonrsharpe, код fizzbuzz работает только в python 2.x.


person Chuntao Lu    schedule 06.01.2014    source источник


Ответы (2)


random.seed(n)

Означает «сбросить генератор случайных чисел в некоторую известную позицию n». Это означает, что будущие выходы генератора могут быть известны заранее. Это полезно для тестирования с одними и теми же «случайными» данными снова и снова.

Что делает этот код, так это сбрасывает генератор каждые 15 шагов, поэтому каждый раз вы получаете одну и ту же последовательность из 15 «случайных» целых чисел (и, следовательно, строк из списка). В Python 2.x первое «случайное» целое число после сброса всегда равно 0 (когда я только что пробовал в Python 3, после random.seed(1178741599) я получаю random.randint(0, 3) == 1).

Обратите внимание, что этот код не делает то, что делает обычная программа FizzBuzz, и сильно зависит от реализации random. У меня это работает в 2.7.3, но не работает в 3.3.2 (см. Почему генератор чисел random не стабилен между версиями Python?).

person jonrsharpe    schedule 06.01.2014
comment
Теперь у меня есть лучшее понимание. Таким образом, из-за «волшебства» этого конкретного начального числа его первые 15 случайных целых чисел — это именно то, что нужно fizzbuzz для подбора правильных элементов в [i+1, "Fizz", "Buzz", "FizzBuzz"]. Я думаю, вы не должны получать 1, так как i+1 имеет индекс 0. - person Chuntao Lu; 07.01.2014
comment
Это правильно, но, как я только что добавил, похоже, он не работает в Python 3.x. - person jonrsharpe; 07.01.2014
comment
Я только что попробовал в Python 3.3, вы правы, он всегда дает 1 - person Chuntao Lu; 07.01.2014

Вот наивный способ найти начальное число для вашего генератора случайных чисел:

import random

expected = [0, 0, 1, 0, 2,
            1, 0, 0, 1, 2,
            0, 1, 0, 0, 3]

def is_working_seed(s):
    random.seed(s)
    return all(random.randint(0, 3) == e for e in expected)

seed = 0
while not is_working_seed(seed):
    seed += 1

print seed

(очевидно, цикл по всем 2^32 значениям начального числа — не лучший план)

Поскольку существует 4**15 == 1073741824 способов создания списка случайных чисел в 0:4, вы ожидаете, что в пространстве 32-битных чисел будет около 4 начальных чисел.

person Eric    schedule 06.01.2014
comment
Хороший анализ семени, теперь мне интересно, есть ли эффективный способ или какой-то теоретический подход, чтобы найти правильное семя... - person Chuntao Lu; 07.01.2014