2010-04-17 8 views
2

Je veux vérifier la limite centrale avec des dés. Rouler les dés. Somme les résultats. Répétez la même chose pour N fois. Changez D et répétez.générateurs de réutilisation

Il n'est pas nécessaire de stocker des valeurs aléatoires, donc je ne veux utiliser que des générateurs. Le problème est que les générateurs sont consommés; Je ne peux pas les réutiliser plusieurs fois. Maintenant, mon code utilise explicitement for et je ne l'aime pas.

dice_numbers = (1, 2, 10, 100, 1000) 
repetitions = 10000 
for dice_number in dice_numbers: # how many dice to sum 
    sum_container = [] 
    for r in range(repetitions): 
     rool_sum = sum((random.randint(1,6) for _ in range(dice_number))) 
     sum_container.append(rool_sum) 
     plot_histogram(sum_container) 

Je veux créer quelque chose comme

for r in repetitions: 
    rools_generator = (random.randint(1,6) for _ in range(dice_number) 
    sum_generator = (sum(rools_generator) for _ in range(r)) 

, mais la deuxième fois que je réutiliser rools_generator il est consommé. Ai-je besoin de construire une classe de générateur?

Répondre

2

Je pense que vous pouvez travailler trop dur, et vous créez des listes certainement inutiles avec la gamme(). Dans l'esprit d'être un peu plus explicite que les genexprs ci-dessus:

import random 

def die_roller(throws): 
    """generates throws rolls of a die""" 
    for _ in xrange(throws): 
     yield random.randint(1, 6) 

roller = die_roller(10) 
print type(roller)  # => <type 'generator'> 
print list(roller)  # => [6, 6, 3, 1, 6, 3, 1, 5, 4, 4] 
print sum(roller)  # roller was exhausted, generates null list thus 0 sum 

big_roller = die_roller(10**5) 
print sum(big_roller) # => 3500238 

Je pense que vous obtient les rudiments de ce que vous recherchez.

+0

-1: 'rools_generator' est un générateur. Remarquez le rond plutôt que les crochets. –

+0

vous avez remarqué que 16 secondes avant que je l'ai fait, édité. Merci. – msw

4

Vous pouvez le faire comme ceci:

for r in repetitions: 
    make_rools_generator = lambda: (random.randint(1,6) for _ in range(dice_number)) 
    sum_generator = (sum(make_rools_generator()) for _ in range(r)) 

Cela crée une fonction appelée make_rools_generator que, lorsqu'il est appelé, crée un nouveau générateur qui a fourni les jets de dés.

+2

En supposant que 'repetitions' est un int, ce sera un petit peu difficile à itérer. – msw

+0

True. Mon amélioration du code donné est limitée à la fonction retournant un générateur. :) –

0

Qu'en est-ce:

list(list((sum((random.randint(1,6) for _ in range(dn))) for __ in range(10000))) for dn in (1, 2, 10, 100, 1000))