2011-12-21 3 views
10

Я пытаюсь создать случайный текст с использованием частот букв, которые я получил. Во-первых, мне удалось получить следующий код:Использование массива для генерации случайного текста

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') 
    .... 

Это до буквы z и пробела. Это дает мне> 50 строк кода, и я хочу получить тот же результат, используя массив.

До сих пор у меня есть:

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]') 

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

+0

(частоты во втором коде являются правильными) – Julia

ответ

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]) 

делает трюк и возвращает (пример):

л wefboethol gsplotfoh иа onpedefh dnolnairnioeiegehhecaworonnfmeuej dsiauhpbfttwcknal ateof ар cgbr sunnee leseaeeecltaiaur у OEN vxntgsoio kdeniei OT DF HTR dcencrsrrfp bwelsuoaslrnr хех й TPT oeejaldeatcto фи а.е. idimiadmgglral ома iaielbtnt эс ае shlspudwdfrrsvol оо я tlwh DRI swhsnloai р swlooi WBE пп sshth nsawtnrqsud MTW ДИИТ pner г nitmah todf zcsehma гл д ROS ctee toiouinn я гл hlonphioe пН ган хо heein itrgeylftn epaacrmanhe

alphabet можно также определить как простую строку (доступ к ее элементам - одиночные символы) работает как списки)

bisect.bisect(list, value) принимает отсортированный список и значение и сообщает, где это значение должно быть помещено между ними. Подробнее о bisect.

+1

+1 для использования алгоритма бинарного поиска. Люди по-прежнему используют много алгоритмов в линейном времени. – v1Axvw

+1

СПАСИБО ВАС! это потрясающе. я выучил. x Julia – Julia

+0

@eumiro нужна ваша помощь, чтобы понять часть бинарного поиска. – DhruvPathak

2

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

У меня даже была ссылка на discussion about weighted random generators , из которой я позаимствовал алгоритм «Царь горы».

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() 
Смежные вопросы