根据使用频率随机生成字母?

时间:2010-01-27 20:11:10

标签: java algorithm random pseudocode

如何根据普通演讲中的使用频率随机生成字母?

任何伪代码都很受欢迎,但Java中的实现非常棒。否则,只要朝正确的方向捅一下就会有所帮助。

注意:我不需要生成使用频率 - 我确信我可以轻松地查看它。

5 个答案:

答案 0 :(得分:18)

我假设您将频率存储为0到1之间的浮点数,总数为1。

首先,您应准备一份累积频率表,即该字母的频率与其前所有字母的总和。

为了简化,如果从这个频率分布开始:

A  0.1
B  0.3
C  0.4
D  0.2

您的累积频率表将是:

A  0.1
B  0.4 (= 0.1 + 0.3)
C  0.8 (= 0.1 + 0.3 + 0.4)
D  1.0 (= 0.1 + 0.3 + 0.4 + 0.2)

现在生成0到1之间的随机数,并查看此列表中该数字所在的位置。选择累积频率最小的字母大于随机数。一些例子:

假设您随机选择0.612。它位于0.4和0.8之间,即在B和C之间,所以你选择C。

如果你的随机数是0.039,那么它在0.1之前,即在A之前,所以选择A.

我希望这是有道理的,否则可以随意要求澄清!

答案 1 :(得分:11)

一种快速的方法是生成一个字母列表,其中每个字母根据其频率出现在列表中。比如说,如果25.6%的时间使用“e”,而你的列表长度为1000,则会有256“e”。

然后,您可以使用(int) (Math.random() * 1000)随机选择列表中的点,以生成0到999之间的随机数。

答案 2 :(得分:5)

我要做的是将相对频率缩放为浮点数,使其总和为1.0。然后我会为每个字母创建一个累积总计的数组,即必须填充以获得该字母的数字以及所有那些“低于”它的数字。假设A的频率为10%,b为2%,z为1%;然后你的表看起来像这样:

0.000 A ; from 0% to 10% gets you an A
0.100 B ; above 10% is at least a B
0.120 C ; 12% for C...
...
0.990 Z ; if your number is >= 99% then you get a Z

然后你自己生成一个介于0.0和1.0之间的随机数,并在数组中进行二进制搜索,以获得小于随机数的第一个数字。然后在那个位置挑选信件。完成。

答案 3 :(得分:4)

甚至不是伪代码,但可能的方法如下:

设p1,p2,...,pk是您想要匹配的频率。

  1. 计算累积频率:p1,p1 + p2,p1 + p2 + p3,...,1
  2. 生成随机均匀(0,1)数字x
  3. 检查累积频率x的哪个区间属于:如果它位于p1 + .. + pi和p1 + ... + pi + p(i + 1)之间,则输出(i + 1)st信
  4. 根据你如何实现区间查找,如果p1,p2,...按递减顺序排序,过程通常会更有效,因为你通常会更早找到包含x的区间。

答案 4 :(得分:2)

使用二叉树为您提供了一种很好,干净的方法来查找正确的条目。在这里,您从frequency地图开始,其中键是符号(英文字母),值是它们出现的频率。这被反转,并且创建NavigableMap,其中键是累积概率,并且值是符号。这使查找变得容易。

  private final Random generator = new Random();

  private final NavigableMap<Float, Integer> table = 
    new TreeMap<Float, Integer>();

  private final float max;

  public Frequency(Map<Integer, Float> frequency)
  {
    float total = 0;
    for (Map.Entry<Integer, Float> e : frequency.entrySet()) {
      total += e.getValue();
      table.put(total, e.getKey());
    }
    max = total;
  }

  /** 
   * Choose a random symbol. The choices are weighted by frequency.
   */ 
  public int roll()
  {
    Float key = generator.nextFloat() * max;
    return table.higherEntry(key).getValue();
  }