2011-12-21 15 views
10

Estoy tratando de generar texto aleatorio utilizando las frecuencias de letras que he obtenido. En primer lugar, tuve éxito con el siguiente código:Usando matriz para generar texto aleatorio

for i in range(450): 
    outcome=random.random() 
    if 0<outcome<0.06775: 
     sys.stdout.write('a') 
    if 0.06775<outcome<0.07920: 
     sys.stdout.write('b') 
    if 0.07920<outcome<0.098: 
     sys.stdout.write('c') 
    .... 

Este hasta que la letra Z y la barra espaciadora. Esto me da> 50 líneas de código y quiero obtener el mismo resultado usando una matriz.

hasta ahora tengo:

f_list = [0, 0.06775, 0.08242, 0.10199, 0.13522, 0.23703, 0.25514, 0.27324, 0.32793, 0.38483, 0.38577, 0.39278, 0.42999, 0.45023, 0.50728, 0.56756, 0.58256, 0.58391, 0.62924, 0.68509, 0.7616, 0.78481, 0.79229, 0.81161, 0.81251, 0.82718, 0.82773, 0.99998] 
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' '] 

import random 
import sys 

for i in range(25): 
    outcome=random.random() 
    if f_list[i]<outcome<f_list[i+1]: 
     sys.stdout.write('alphabet[i]') 

Pero no funciona correctamente, ya que el rango parece ahora a relacionarse con la matriz y no el número de iteraciones que quiero. La salida está en blanco.

+0

(las frecuencias en el segundo código son las correctas) – Julia

Respuesta

17
import random 
import sys 
import bisect 

f_list = [0, 0.06775, 0.08242, 0.10199, 0.13522, 0.23703, 0.25514, 0.27324, 0.32793, 0.38483, 0.38577, 0.39278, 0.42999, 0.45023, 0.50728, 0.56756, 0.58256, 0.58391, 0.62924, 0.68509, 0.7616, 0.78481, 0.79229, 0.81161, 0.81251, 0.82718, 0.82773, 0.99998] 
alphabet = 'abcdefghijklmnopqrstuvwxyz ' 

for i in xrange(450): 
    sys.stdout.write(alphabet[bisect.bisect(f_list, random.random()) - 1]) 

hace el truco y vuelve (ejemplo):

l wefboethol gsplotfoh ua onpedefh dnolnairnioeiegehhecaworonnfmeuej dsiauhpbfttwcknal ateof ap CGBR Sunnee leseaeeecltaiaur u oen vxntgsoio kdeniei ot df htr dcencrsrrfp bwelsuoaslrnr je ee TPT oeejaldeatcto fi au idimiadmgglral om iaielbtnt es oe shlspudwdfrrsvol oo i tlwh dri swhsnloai p swlooi wbe nn sshth nsawtnrqsud mtw DIIT PNER r nitmah todf zcsehma hl e ros Ctee toiouinn i hl hlonphioe nh gan ho heein itrgeylftn epaacrmanhe

alphabet se puede definir como una cadena simple también (accediendo a sus elementos - caracteres individuales - funciona como para listas)

bisect.bisect(list, value) toma una lista ordenada y un valor y dice dónde debe colocarse este valor. Más sobre bisect.

+1

+1 para el uso del algoritmo de búsqueda binaria. La gente todavía usa muchos algoritmos en tiempo lineal. – v1Axvw

+1

¡MUCHAS GRACIAS! esto es perfecto. he aprendido. x Julia – Julia

+0

@eumiro necesita su ayuda para entender la parte de búsqueda binaria. – DhruvPathak

2

La respuesta de Eumiros es perfecta, y mucho más simple que la mía, pero como hice el esfuerzo de modificar una solución anterior a un problema similar, no quiero que se desperdicie.

Incluso tuve el enlace todavía para el discussion about weighted random generators del cual tomé prestado el algoritmo "King of the hill".

from string import lowercase 
from random import random 

class TextGenerator(object):   
     def __init__(self, flist, textlength, charmap = lowercase + ' '):    
      self.text_length = textlength 
      self.chars = charmap 
      self.weights = self._get_weight_list(flist)    

     def create_new_weights(self, flist): 
      self.weights = self._get_weight_list(flist) 

     def get_weight(self, char): 
      return self.weights[self.chars.index(char)]    

     def change_weight(self, char, weight): 
      self.weights[self.chars.index(char)] = weight 

     def _get_weight_list(self, flist): 
      return map (lambda x, y: y-x, 
         flist, 
         flist[1:] + [1.0])[:-1] 

     def windex(self): 
      assert(len(self.weights) == len(self.chars)) 
      rnd = random() * sum(self.weights) 
      for i, w in enumerate(self.weights): 
       rnd -= w 
       if rnd < 0: 
        return i 

     def create_text(self, flist = None): 
      weights = self._get_weight_list(flist)if flist else self.weights 
      return u''.join([self.chars[self.windex()] for i in range(self.text_length)]) 

flist = [0, 0.067750000000000005, 0.082419999999999993, 0.10199, 0.13522000000000001, 0.23702999999999999, 0.25513999999999998, 0.27323999999999998, 0.32793, 0.38483000000000001, 0.38577, 0.39278000000000002, 0.42998999999999998, 0.45023000000000002, 0.50727999999999995, 0.56755999999999995, 0.58255999999999997, 0.58391000000000004, 0.62924000000000002, 0.68508999999999998, 0.76160000000000005, 0.78481000000000001, 0.79229000000000005, 0.81161000000000005, 0.81250999999999995, 0.82718000000000003, 0.82772999999999997, 0.99997999999999998] 

texter = TextGenerator(flist, 1000) 
print texter.create_text() 

texter.change_weight('i', texter.get_weight('e') * 2) 
print texter.create_text() 
Cuestiones relacionadas