iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 15
0
自我挑戰組

從科展學寫程式系列 第 15

15 柏拉圖問題 探討拿取總價值的期望值 II

用之前的拿取策略還有改進的空間,得到的期望值只有比亂取的期望值大而已,距離目標95.75036%還有一段距離。所以我們還要再調整另外的變因使我們得到的分數能夠更高。之前拿取的規定是只要不是最小的就拿取,這樣子取到的值可能會太小,所以我必須要嚴格一些。設:

假如我在第S家,只要在前面所有的店家價值比較,
在t%之後才可以執行拿取的動作,避免資料不足,難以判斷。
只要第S家與S之前所有的店家相比 (以PR值表示其比值),PR值>d% (PR值的比較標準) 的話就拿取。

以下為程式講解:

下面為變數設定:
前面的(from,gap,to)是指(t%開始,t%每次間隔,t%結束)
中間的limit是總共有幾家店
後面(get_from,get_gap,get_to)則是(d%開始,d%每次間隔,d%結束)

if(isset($_GET['debug'])) $debug=$_GET['debug'];
else $debug=1;//顯示步驟

if(isset($_GET['from'])) $from=$_GET['from'];
else $from=0;

if(isset($_GET['gap'])) $gap=$_GET['gap'];
else $gap=1;

if(isset($_GET['to'])) $to=$_GET['to'];
else $to=100;

if(isset($_GET['limit'])) $limit=$_GET['limit'];
else $limit=100;

if(isset($_GET['get_from'])) $get_from=$_GET['get_from'];
else $get_from=25;

if(isset($_GET['get_gap'])) $get_gap=$_GET['get_gap'];
else $get_gap=1;

if(isset($_GET['get_to'])) $get_to=$_GET['get_to'];
else $get_to=35;

if(isset($_GET['loop_num'])) $loop_num=$_GET['loop_num'];
else $loop_num=10000;//跑的次數

因為有兩個變因(t% & d%),所以我的顯示必須要是有兩軸,最後寫出來的程式長這樣:

printf("Date,percent\get,=>");
for($a=$get_from;$a<=$get_to;$a=$a+$get_gap){
printf(",$a");
}
printf("$n");

for($k=$from;$k<=$to;$k=$k+$gap)
{
 $thedate=date("m-d H:i");
 $percent=$k;
 printf("%s,%.0f,=>", $thedate, $percent);
 $total_score=0;

 
 for($p=$get_from;$p<=$get_to;$p=$p+$get_gap){
$get=$p;

 if($debug>1)
 {
  echo "From: ", $from, $n;
  echo "To: ", $to, $n;
  echo "Limit: ", $limit, $n;
  echo "Percent: ", $percent, $n;
 } 
  
 for($j=0;$j<$loop_num;$j++)
 {
  $choice_time=1;
  $max_num=0;
  $choice=0;
  $score=0;
  $percent_get=$limit*$get/100;
  $percent_PR=$percent/100;
  $thisnum=range(1,$limit,1);//(小,大,差)
  shuffle($thisnum);//洗牌
  
   for($i=0;$i<$limit;$i++)//選擇
   { 
    $num=$thisnum[$i];
    if($max_num<$num) $max_num=$num;
   
    $pos=0;
    $num_PR=0;
    for($m=0;$m<$i;$m++)//決定大小排列
    {
     if($num>$thisnum[$m]) $pos=$pos+1;
    }
    if($i>$percent_get)$num_PR=$pos/$i;
    if($debug>0) echo $i+1, " ", $num, " ", $num_PR, $n;
     if($num_PR>$percent_PR and $choice_time>0){
      $choice=$num;
      $choice_time=$choice_time-1;
     }
   }
  if($choice_time>0){
     $choice=$num;
     $choice_time=$choice_time-1;
    }
  $score=$choice;
  $total_score=$total_score+$score;
  
  if($debug>0){
   echo "Choice: ", $choice, $n;
   echo "Max: ", $max_num, $n;
   echo "choice_time: ", $choice_time, $n;
  }
  
 }  
 
 $total_score=$total_score/$loop_num;
 printf(",%.7f", $total_score);

} 

printf("$n");

}

我是一次操縱兩個變因,所以如果兩種變數都是跟以前一樣間隔0.1的話,就總共要跑 1,000x1,000=1,000,000個值,那真是個天文數字!所以我為了先知道他用這兩個變因的搭配,先把間距設成5,這樣總共只有20x20=400個值,我比較可以接受。最後如果要再更精確的話,就再將範圍縮小就可以了。最後得出下面兩個圖:

http://ithelp.ithome.com.tw/upload/images/20161230/201038524cC6gT0u6g.png
http://ithelp.ithome.com.tw/upload/images/20161230/20103852Mxfo6UeTjO.png

利用程式模擬的方式,共有100家,d%從0到100,d%每次加 5。t%也是一樣,每個值跑1萬遍,得出來的結果如圖(4-6)。之後再找到接近極大值的範圍如圖(4-7),得到 d%=95% , t%=28% , score=96.0959539%。

這個數據只是大約的數值,還要再找一天再更精細的跑下去。

結果就大概是這樣拉~


上一篇
14 柏拉圖問題 Wwwwwwwwww~~~~
下一篇
16 柏拉圖問題 小結~
系列文
從科展學寫程式43

尚未有邦友留言

立即登入留言