由抽獎軟體想到的隨機演算法總結

來源:互聯網
上載者:User

標籤:

    整整三年沒更新部落格了,今天和女友聊天,聊到了部落格,就回來看看。

    最近接觸到抽獎軟體,下載的源碼是http://download.csdn.net/detail/ghz_sd/6918125,在這裡為開源軟體作出貢獻的人致敬,這個軟體的作者a米山,是個非常好的人,耐心的幫我調試,他的演算法很簡單,就是純粹的random,用的rand()函數,我給他提了個需求,寫一個作弊類,實現的功能是:指定人的中獎機率提高,設定檔類似於這樣:

<xml>    <win>        <name=‘a‘ probability=20>        <name=‘b‘ probability=20>    </win></xml>

  他實現的話,中獎了就給他好吃哈!!!

  抽獎實際上用的是隨機演算法,在此進行歸納總結

一、選摘《演算法導論》

在僱傭問題中,如果應聘者是以隨機順序出現的話,僱傭一個新的辦公室助理的期望次數是lnn。這個演算法是隨著輸入的變化而變化的。對於某個特定的輸入,它總是會
產生固定的僱傭次數。

如果先對應聘者進行隨機排列,此時隨機發生在演算法上而不是發生在輸入分布上。 每次運行這個演算法,執行依賴於隨機的選擇,而不是依賴於輸入。這就是隨機演算法和機率分析的區別。

RANDOMIZED-HIRE-ASSISTANT(n)1 randomly permute the list of candidates2 best ← 0      ® candidate 0 is a least-qualified dummy candidate3 for i ← 1 to n4       do interview candidate i5          if candidate i is better than candidate best6             then besti7                  hire candidate i

隨機演算法事實上就是在演算法裡,對輸入預先進行重排,其他完全一樣。


在這裡,要介紹2種對輸入進行重排的演算法,他們是隨機重排。這兩個方法都能產生均勻的隨機排列。(每一種排列都等可能的被產生)。

要特別注意均勻隨機排列的定義!!!!本書下面給出的2個演算法對數組進行重排,產生的都是均勻隨機排列,並給出了嚴格的數學證明,理論性很高,我們在這裡這著重於介紹和瞭解這兩種方法,不深究證明,欲看證明的可去看書。


---------------------------------------------------------------------------------------------------------------------------------------------------


隨機排列數組:


1)PERMUTE-BY-SORTING(A)

為數組的每個元素賦一個隨機的優先順序,然後根據優先順序對數組A進行排序。

 

PERMUTE-BY-SORTING(A)1 nlength[A]2 for i ← 1 to n3      do P[i] = RANDOM(1, n

3

)4 sort A, using P as sort keys5 return A


這樣顯然可以打亂數組的順序,關鍵在於我們要去證明它是均勻隨機打亂的。這個要根據均勻隨機排列的定義,即證明產生每一個排列的機率都是1/n!

潛在的,我們可以知道:


a)如果一個演算法總共還產生不到n!種排列,那麼顯然它不是一個均勻隨機排列的演算法。課後某習題

b)有人可能會說,要證明一個排列是均勻隨機排列,只要證明每個元素在每個位置上出現的機率是1/n就可。這是對均勻隨機排列的誤解。課後某習題

PERMUTE-BY-SORTING比較難,不能直接看出可以產生多少種排列。



2)RANDOMIZE-IN-PLACE(A

對數組一遍迴圈,每個元素A[i]與  A[i]到最後一個元素  中的某個交換(如下代碼),容易看出,總共的排列數就是n!個

RANDOMIZE-IN-PLACE(A)1 nlength[A]2 for ito n3      do swap A[i] ↔ A[RANDOM(i, n)]


對於1)2)是均勻隨機排列的證明這裡就不講了,書上有。


--------------------------------------------------------------------------------------------------------------------------------------------------


習題  


(證明均勻隨機排列的過程是非常麻煩的,我們重點關註上面畫底線的a,b兩條,來判斷某個演算法是否可以產生均勻隨機排列就行)




5.3.2   Kelp教授決定用下列演算法來隨機產生非同一排列的任意排列,他實現了意圖嗎?

PERMUTE-WITHOUT-IDENTITY(A)1 nlength[A]2 for i ← 1 to n3      do swap A[i] ↔ A[RANDOM(i + 1, n)]


不行,這段代碼總共只能產生(n-1)!種排列(自己算),達到他的意圖的必要條件就需要能夠產生n!-1種排列。

上述第a)點。



5.3.3  假設不是將 A[i] 與 A[i....n] 上的數隨機的交換一個(注意這是我們的正確演算法),而是每次將它與數組上任意位置上的數隨機交換,可以產生均勻隨機排列嗎?

PERMUTE-WITH-ALL(A)1 nlength[A]2 for i ← 1 to n3      do swap A[i] ↔ A[RANDOM(1, n)]

不能,也是第a)點,可以自己分析下。

舉個特例,假設排列長度為n=3。那麼就要調用3次RANDOM,每次返回3個值中的一個,則執行完過程PERMUTE-WITH-ALL後將會有27種可能的結果。因為排列長度為n,則一共有3!=6個排列,如果PERMUTE-WITH-ALL產生均勻的隨機排列,那麼每個排列出現的機率均為1/6。也就是說每個排列都應該出現m次使m/27=1/6。由於不存在整數m使m/27=1/6,因此PERMUTE-WITH-ALL不一定產生均勻的隨機排列。


5.3.4  Armstrong建議用下列過程來產生均勻隨機排列:

PERMUTE-BY-CYCLIC(A)1  nlength[A]2  offset ← RANDOM(1, n)3  for i ← 1 to n4       do desti + offset5          if dest > n6             then destdest -n7          B[dest] ← A[i]8  return B
證明任意元素在B中任意位置出現的機率都是1/n,證明該演算法不能產生均勻隨機排列。

1)注意第2行,offset在這就求出來了,在for中使用的時候是一個定值。

offset可以有n個值,所以任意元素在B中任意位置出現機率都是1/n.

2)這段代碼只能產生n個不同的排列(原因仍是第2行)


這就說明了劃線部分b)

二、抽獎機率-三種演算法
點擊標題即可跳轉原博文
三、平台抽獎演算法總結-再也不用怕獎品被提前搶光 http://www.xuanfengge.com/luck-draw.html(前端的網站都有演算法文章)
前言

但凡商戶搞點營銷活動,為了能觸達更多的顧客,來點兒抽獎的把戲,應該是極好的,什麼“刮刮樂”、“砸金蛋”、“大轉盤”等等,換湯不換藥,屢試不爽。從微客多營銷平台各種活動的使用方式也能看出,抽獎活動一直是商戶用得最多的線上活動,正所謂無利不起早,給點“花蜜”犒勞下“蜜蜂”也是應該的。

需求分析

那麼問題來了,發獎機制怎麼玩?作為一個服務商戶的營銷平台,怎樣將商戶配置的獎品發出去才能起到比較好的效果呢?

先來看目標,什麼是比較好的效果,也就是使用者(商戶)的需求是什麼:

  • 抽獎活動期間獎品數量是固定的
  • 稀有的獎品盡量靠後被抽中
  • 物盡其用,獎品不希望有剩餘
  • 每個獎品可以設定被抽中的機率

 

情境類比

為了討論方便,我們先把情境假設一下:

抽獎啟用時間:

00:00:00-23:59:59

獎品設定:

獎品層級 獎品名稱 獎品數量
一等獎 A 2
二等獎 B 3
三等獎 C 4
具體分析

第一種能想到的做法就是給每種獎品設定中獎機率,每次按設定好的中獎機率派獎,但是問題又來了:

獎品數量固定,但是參與抽獎的人數不可預知,根本無法控制獎品的消耗速度,如果機率設定高了,抽獎者一擁而上獎品很快就沒了,設定低了,獎品可能到最後都發不完。另外,機率這個偏技術的術語使用者理解起來肯定五花八門,使用時溝通成本非常高。

而實際上“每個獎品可以設定被抽中的機率”是個十分模糊的說法,說它模糊,主要是因為你並不知道這個設定的機率用在什麼地方,這些機率設定需要滿足什麼條件,總樣本數量(總抽獎次數)是多少。

所以最好的做法應該是使用者不必關心所謂的“獎品被抽中的機率”,只關注前三個預期效果即可。

經過分析,我們發現,要達到使用者上面的那三個效果,只要獎品在活動期間陸續被抽走即可,那能不能給每件獎品設定一個允許被抽走的時間呢?對!如果控制好每件獎品的發放時間點,再安排好各類獎品的發放順序,大獎不會一開始就抽走,直到活動最後階段都能保證有獎。

具體設計

順著這個想法,我們來看具體的設計:

將獎品均勻地埋在整個啟用時間(3600*24=86400秒)裡,如上面假設情境,一共有9個獎品,則把啟用時間均勻的分成9份

以獎品剩餘數量作為權重,陸續隨機播放每個時間段裡的獎品類型(顏色對應的獎品見上表)

在每個時間段裡隨機播放獎品的“釋放”時間點,一是為了均勻,二是避免直接暴露精確的時間點

 
1 releaseTime(n)=startTime+(n-1)× ?t+random(?t)

實現方案

說完思路,我們再看實現:在獎品釋放時間點之後的抽獎使用者就有機會(這個機率可配置,如100%或者80%)拿到該時間段的獎品,如果獎品未被抽走,將繼續等待抽獎者的到來。

思路一

直觀的做法是建立三張表

t_award_batch(獎品描述表,用於記錄各種獎品的配置資訊),

ID 名稱(name) 獎品總量(amount)
1 A 2
2 B 3
3 C 4

 

t_award_pool(獎池表,用於產生每一次獎品釋放的時間點),

ID 獎品ID(award_id) 釋放時間(release_time) 剩餘數(balance)
1 3 1:03:27 0
2 2 3:15:13 1
3 3 5:29:57 1
4 2 9:35:34 1
5 1 12:57:20 1
6 2 13:47:03 1
7 3 17:31:50 1
8 1 18:13:26 1
9 3 22:28:40 1

 

t_record(抽獎記錄表,用於記錄每次抽獎者的抽獎記錄)

ID 獎品ID(award_id) 中獎時間(hit_time) 使用者ID(owner_id)
1 3 1:03:45 peteryan

活動開始前,根據t_award_batch中的獎品配置資訊,初始化t_award_pool中的資料,把每種獎品的釋放時間初始化好,使用者來抽獎時,根據目前時間在t_award_pool表中的查詢到一條已經釋放而且未被抽掉的獎品

 
1 select id from t_award_pool where release_time <= now() and balance > 0 limit 1 ;

查詢到後對其進行更新,如果被他人搶走,則未中獎

 
1 update t_award_pool set balance = balance – 1 where id = #{id} balance > 0 ;

同時留下抽獎情況到t_record中。

思路二

在思路一中,為了方便抽獎時判斷當前是否有可中獎品,進行了初始化每件獎品的釋放時間,當獎品數量比較小的時候,情況還好,對於獎品數非常多的時候,抽獎的查詢耗時會增加,初始化獎池也是耗時的動作,是否可以不依賴這個表之間通過即時計算判斷當前是否有獎品釋放。

在t_award_batch表中添加兩個欄位,獎品總剩餘量balance和上一次中獎時間last_update_time。

ID 名稱(name) 獎品總量(amount) 獎品餘量(balance) 更新時間(last_update_time)
1 A 2 2 1:03:45
2 B 3 3 0:00:00
3 C 4 3 0:00:00

這樣具體實現上僅需要依賴獎品配置資訊即可,範例程式碼如下(點擊圖片全屏查看):

其中awardBatch表示一類獎品,如上表中提到的一等獎。上面代碼中,隨機選出下一個待釋放的獎品邏輯如下:

通過這套發獎機制,很好地滿足了營銷商戶的目標,同時減少了對複雜機率計算的糾結,再也不用擔心獎品被提前搶光了。

 

由抽獎軟體想到的隨機演算法總結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.