Objective-C中的加权随机字母

时间:2012-06-05 21:47:27

标签: objective-c random

我需要一种简单的方法来随机选择字母表中的一个字母,并根据我希望它出现的百分比进行加权。例如,我想要这封信' E'在5.9%的时间内提出随机函数,但我只想要' Z'在0.3%的时间内出现(依此类推,基于字母表中每个字母的平均出现次数)。有什么建议?我看到的唯一方法就是填充一个数组,例如10000个字母(590' E' 3' Z'等等),然后从中随机选择一个字母。那个数组,但它看起来像内存密集和笨拙。

4 个答案:

答案 0 :(得分:5)

不确定这是否可行,但似乎可以解决这个问题:

  1. 记下您的字母和频率列表并对其进行排序 最小频率到最大频率。
  2. 创建一个26元素数组,其中每个元素n包含所有先前权重的总和以及频率列表中的元素n。记下中的总和 数组的最后一个元素
  3. 生成一个介于0和上面记录的总和之间的随机数
  4. 对和数组进行二元搜索,直到到达该数字落下的元素
  5. 这有点难以理解,所以它会是这样的:

    1. 如果你有一个带有这些频率的5个字母的字母,a = 5%,b = 20%,c = 10%,d = 40%,e = 25%,按频率排序:a,c,b, e,d
    2. 保持元素的运行总和:5,15,35,60,100
    3. 生成0到100之间的随机数。说出来了22.
    4. 二元搜索22将落下的元素。在这种情况下,它将在元素2和3之间,这将是字母“b”(我认为这是你想要的,我认为)

答案 1 :(得分:2)

你已经承认了空间和速度之间的权衡,所以我不会深入研究。

如果您可以计算每个字母先验的频率,那么您可以预先生成一个数组(或动态创建并填充数组一次),以便按照您所需的精度水平进行扩展。

由于您在小数点后使用了具有单位精度的百分比,因此请考虑1000个条目的数组。每个指数代表频率百分之十的十分之一。因此,您letter[0]letter[82]等于'a'letter[83]letter[97]等于'b',依此类推至{{ 1}}等于letter[999]。 (根据Relative frequencies of letters in the English language的值)

现在生成一个介于0和1之间的随机数(使用您喜欢的任何PRNG,假设均匀分布)并将结果乘以1000.这将为您提供数组的索引和加权随机字母。

答案 2 :(得分:0)

使用此处说明的方法。唉,这是为Python,但可以为C等重写。 https://stackoverflow.com/a/4113400/129202

答案 3 :(得分:0)

首先,您需要制作字母及其频率的NSDicationary;

我将用一个例子来解释它: 假设您的词典是这样的:

  

{@“a”:@ 0.2,@“b”,@ 0.5,@“c”:@ 0.3};

所以你的字母频率以这种方式覆盖[0,1]的间隔:

  

a-> [0,0.2] + b-> [0.2,0.7] + c-> [0.7,1]

您生成一个0到1之间的随机数。然后通过检查此随机属于哪个区间并返回相应的字母,您可以轻松获得所需的字符。

您在程序开头播种随机函数:srand48(time(0));

  

- (NSSting *)weightedRandomForDicLetters:(NSDictionary *)letterFreq   {

double randomNumber = drand48();

double endOfInterval = 0;
for (NSString *letter in dic){
    endOfInterval += [[letterFreq objectForKey:letter] doubleValue];
    if (randomNumber < endOfInterval) {
        return letter;
    }
}

}