加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

perl – 按使用频率随机选择字母

发布时间:2020-12-16 06:08:27 所属栏目:大数据 来源:网络整理
导读:在将少量莎士比亚书籍送到我的Perl脚本后,我有一个哈希,其中包含26个英文字母作为键,以及它们在文本中出现的次数 – 作为值: %freq = ( a = 24645246,b = 1409459,.... z = 807451,); 当然还有所有字母的总数 – 让我们说在$total变量中. 是否有一个很好的
在将少量莎士比亚书籍送到我的Perl脚本后,我有一个哈希,其中包含26个英文字母作为键,以及它们在文本中出现的次数 – 作为值:

%freq = (
    a => 24645246,b => 1409459,....
    z => 807451,);

当然还有所有字母的总数 – 让我们说在$total变量中.

是否有一个很好的技巧来生成一个包含16个随机字母的字符串(一个字母可以在那里出现几次) – 按使用频率加权?

要在类似于Ruzzle的文字游戏中使用:

优雅的东西 – 比如从文件中挑选一条随机行,如Perl Cookbook收据所示:

rand($.) < 1 && ($line = $_) while <>;

解决方法

选择随机线的Perl Cookbook技巧(也可以在 perlfaq5中找到)也可以用于加权采样:

my $chosen;
my $sum = 0;
foreach my $item (keys %freq) {
    $sum += $freq{$item};
    $chosen = $item if rand($sum) < $freq{$item};
}

这里,$sum对应于行计数器$.和$freq {$item}到Cookbook版本中的常量1.

如果您要选择大量加权随机样本,可以通过一些准备加快这一点(注意这会破坏%freq,所以如果你想保留它,请先复制一份):

# first,scale all frequencies so that the average frequency is 1:
my $avg = 0;
$avg += $_ for values %freq;
$avg /= keys %freq;
$_ /= $avg for values %freq;

# now,prepare the array we'll need for fast weighted sampling:
my @lookup;
while (keys %freq) {
    my ($lo,$hi) = (sort {$freq{$a} <=> $freq{$b}} keys %freq)[0,-1];
    push @lookup,[$lo,$hi,$freq{$lo} + @lookup];
    $freq{$hi} -= (1 - $freq{$lo});
    delete $freq{$lo};
}

现在,要从准备好的分布中绘制随机加权样本,您只需执行以下操作:

my $r = rand @lookup;
my ($lo,$threshold) = @{$lookup[$r]};
my $chosen = ($r < $threshold ? $lo : $hi);

(这基本上是Marsaglia,Tsang& Wang(2004),“Fast Generation of Discrete Random Variables”,J.Stat.Soft.11(3)中描述的Square Histogram方法,最初归于A.J.Walker(1974).)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读