2009-04-13 53 views
2

例如, 函數可能類似於def randABCD(n,.25,.34,.25, 0.25):我需要一個Python函數,當給出所需的字符概率時,它將輸出一個4個不同字符的隨機字符串

其中n是要生成的字符串的長度和下面的數字是A,B,C的期望概率,D.

我可以想象這是相當簡單的,但是我在創建工作程序時遇到困難。任何幫助將不勝感激。

+0

請發表您到目前爲止的代碼。當我們看到你嘗試過的東西時,幫助你更容易。 – 2009-04-13 14:49:49

+0

檢測到家庭作業氣味。 – Welbog 2009-04-13 14:50:23

+0

作爲示例,函數如何知道它需要哪些4個字符來衡量概率? – 2009-04-13 14:51:42

回答

0

謝謝大家的幫助,我能夠找出一些東西,主要是這個信息。 對於我的特殊需求,我做了這樣的事情:

import random 
#Create a function to randomize a given string 
def makerandom(seq): 
    return ''.join(random.sample(seq, len(seq))) 
def randomDNA(n, probA=0.25, probC=0.25, probG=0.25, probT=0.25): 
    notrandom='' 
    A=int(n*probA) 
    C=int(n*probC) 
    T=int(n*probT) 
    G=int(n*probG) 

#The remainder part here is used to make sure all n are used, as one cannot 
#have half an A for example. 
    remainder='' 
    for i in range(0, n-(A+G+C+T)): 
     ramainder+=random.choice("ATGC") 
    notrandom=notrandom+ 'A'*A+ 'C'*C+ 'G'*G+ 'T'*T + remainder 
    return makerandom(notrandom) 
2

隨機類在Python中非常強大。您可以根據適當的權重生成所需字符的列表,然後使用random.choice來獲取選擇。

首先,確保你做一個隨機導入。

例如,假設您想要A,B,C或D中的一個真正的隨機字符串。 1.使用字符 li = ['A','B','C' 'd']

  • 然後從它使用random.choice 輸出獲得的值= 「」。加入([random.choice(LI),其中i在範圍(0,n)的])
  • 你可以很容易地用n作爲參數來創建一個函數。

    在上述情況下,你獲得A,B,C或D.

    您可以使用重複的條目列表中的給人物的概率更高的機會均等。所以,舉個例子,假設你想要A和B分別有50%的機會和25%的機會。你可以有一個這樣的數組:

    LI = [ 'A', 'A', 'B', 'C']

    等。

    這將是不難的參數化字符進入期望的權重,以模型,我會用字典。

    characterbasis = { 'A':25, 'B':25, 'C':25, 'd':25}

    作出這樣的第一個參數,以及第二個是字符串的長度並使用上面的代碼來生成你的字符串。

    2

    對於四個字母,這裏的東西快了我的頭頂部:

    from random import random 
    
    def randABCD(n, pA, pB, pC, pD): 
        # assumes pA + pB + pC + pD == 1 
        cA = pA 
        cB = cA + pB 
        cC = cB + pC 
        def choose(): 
         r = random() 
         if r < cA: 
          return 'A' 
         elif r < cB: 
          return 'B' 
         elif r < cC: 
          return 'C' 
         else: 
          return 'D' 
        return ''.join([choose() for i in xrange(n)]) 
    

    我毫不懷疑,這是可以做出更清潔/更短的,我只是有點着急權現在。

    我不會滿足於David在達科塔的答案中使用重複字符列表的原因是,根據您的概率,可能無法在正確的數字中創建重複列表以模擬概率你要。 (好吧,我想這可能總是可能的,但是你可能需要一個巨大的清單 - 如果你的概率是0.11235442079,0.4072777384,0.2297927874,0.25057505341?)

    編輯:這裏有一個更清潔的通用版本,與任意數量的字母與任何權重的工作原理:

    from bisect import bisect 
    from random import uniform 
    
    def rand_string(n, content): 
        ''' Creates a string of letters (or substrings) chosen independently 
         with specified probabilities. content is a dictionary mapping 
         a substring to its "weight" which is proportional to its probability, 
         and n is the desired number of elements in the string. 
    
         This does not assume the sum of the weights is 1.''' 
        l, cdf = zip(*[(l, w) for l, w in content.iteritems()]) 
        cdf = list(cdf) 
        for i in xrange(1, len(cdf)): 
         cdf[i] += cdf[i - 1] 
        return ''.join([l[bisect(cdf, uniform(0, cdf[-1]))] for i in xrange(n)])   
    
    0

    這裏是什麼可能適合你

    import random as r 
    
    def distributed_choice(probs): 
        r= r.random() 
        cum = 0.0 
    
        for pair in probs: 
         if (r < cum + pair[1]): 
          return pair[0]   
         cum += pair[1] 
    

    一個粗略的想法參數probs獲取表單(對象,概率)對的列表。假定概率之和是1(否則,它的平凡歸一化)。

    要使用它,執行:

    ''.join([distributed_choice(probs)]*4) 
    
    4

    下面是選擇單個加權值的代碼。你應該可以從這裏拿走它。它使用bisectrandom來完成這項工作。

    from bisect import bisect 
    from random import random 
    
    def WeightedABCD(*weights): 
        chars = 'ABCD' 
        breakpoints = [sum(weights[:x+1]) for x in range(4)] 
        return chars[bisect(breakpoints, random())] 
    

    這樣稱呼:WeightedABCD(.25, .34, .25, .25)

    編輯:這裏是即使權重加起來也不到1.0可用的版本:

    from bisect import bisect_left 
    from random import uniform 
    
    def WeightedABCD(*weights): 
        chars = 'ABCD' 
        breakpoints = [sum(weights[:x+1]) for x in range(4)] 
        return chars[bisect_left(breakpoints, uniform(0.0,breakpoints[-1]))] 
    
    0

    嗯,是這樣的:

    import random 
    class RandomDistribution: 
        def __init__(self, kv): 
         self.entries = kv.keys() 
         self.where = [] 
         cnt = 0 
         for x in self.entries: 
          self.where.append(cnt) 
          cnt += kv[x] 
         self.where.append(cnt) 
    
        def find(self, key): 
         l, r = 0, len(self.where)-1 
         while l+1 < r: 
          m = (l+r)/2 
          if self.where[m] <= key: 
           l=m 
          else: 
           r=m 
         return self.entries[l] 
    
        def randomselect(self): 
         return self.find(random.random()*self.where[-1]) 
    
    rd = RandomDistribution({"foo": 5.5, "bar": 3.14, "baz": 2.8 }) 
    for x in range(1000): 
        print rd.randomselect() 
    

    應該讓你最的方式...

    相關問題