【これは酷い】かつて仕事でプログラミングしてたこともある人が数年ぶりに書いたコード

こんちは。

せっかく書いたので、捨てるの勿体ないので。記憶が残ってるうちなら、ちょっと書き換えたら他でも使えそうなので。(にしては再利用を全く考えてないその場しのぎのコード)

あらためまして、こんにちは。

確かに昔プログラミングしてました。ただしUIっていうんですかね。なんか独自のシステムがあってそれの上で動くアプリケーションを作る! みたいなのがほとんどで、数年で事務作業とか会議が多くなりそれすらあんまりやらなくなった。そして、そこから数年どころか下手すれば10年近くかそれ以上。ブランクあります。

で、どうせ時間あるしで思い立って、いまだとWEB上でそのまんま実行できるんですね。昔もあったような気がしないでもないですが。まあそんな感じの浦島太郎です。

【本題】

全15種、1セット5枚入りの生写真。コンプリートするには何セット買えばよいでしょう? 問題。

確率を計算しようと思っても、すごくよくわからなくなるので、実際に引いてみたらいいんじゃない? ってのを、むかし人力検索で習った。
なので実行!

本来であれば、10万セット、計50万枚。15種が均等になっていて、そこから重複なしの5枚組を作っていくというところからスタートすべきですが。
そこは適当に。
とにかく無限にある生写真の中から5枚引いて、重複が無ければ採用するというロジックにしました。(というかそのつもりです)


どうでもいいけど、15種で50万枚だと端数でるんですね。50万10枚使用の10万2セットか、49万9995枚使用の99999セットだと割り切れますか。3と5の公倍数だから。

さらにどうでもいいんですが、気になるのは、余りにも大量にあると何人ぐらいで一人何枚ぐらいで袋詰め作業してるんでしょうね。どうやってシャッフルしてるのか。残りが何枚ぐらいになったら重複しないように気を付けだすんでしょうかね。
破損とかもあるだろうし、ちょっと多めに用意されてて余りは廃棄されたりするんですかね。あとサイン入れるのも数が多いとどうなってんだろう。

ともかく!

当初の予定として、重複しない5枚組の生写真を、任意のセット数購入した時の15種が全部そろう確率を計算っていうかためしてガッテン!

1セット買う時~0%。(5枚で15種集まるわけない)
2セットも同様。
3セットから可能性出てくる。(数%はありそう)
感覚的には、倍の30枚も買えば5割ぐらい揃う気がする。

何も考えずに100セットまで、それぞれ10000回試してみましょう!

ということでプログラム組みました。
厳密にいうとC言語自体は学生の時とかしかやってないはずで、その後はC言語っぽい何かや、C言語のようなC++のような……みたいなのが多くて、まあ基本に立ち返ってC言語だろうと。

で、途中で、なんかデータが設定されなかったり、自分で書いたループが理解不能になったり、いきあたりばったりでそれっぽい数字が出るところまで突貫しました。WEB上で動くやつなので、10000回の試行ではタイムアウトしてしまったり。
通信がタイムアウトしなければセーフだったりするのか? (想像)で、デバッグ用のprintfがあると10000回でも動くけど、そのprintf消したら10000万回は無理で1000回で妥協したりと色々ありましたが。
結局MAX100セット買うという行為が無駄だと気づき、MAXでも30セット(それでだいたい15種揃うので)ということで、10000回試した結果が以下になるらしいです。

適当

ほんまか?

もう一度実行してみる。

適当2

まあムラがあるのはしゃーない。近似値でもなく、10000回の結果であるからして。

凄く直感とずれてるんだが、ほんとうにあっているのだろうか?

まあこれが確かなら、11セット、つまり55枚買うと8割越えの確率で自力コンプができるらしい。ほんまか? 直感的には6セット(30枚)も買えば5割ぐらいコンプできて(シミュレーション結果上は6セットだと2割)、5セット(25枚)でもそこそこ頑張れそう(出力上は10%前後)な気がするんだが。ほんまか?

とにかく動けばいいという精神で書きましたが、コンパイル通ってそれなりの結果が出ればとりあえず終了。

昔はもう少しちゃんと綺麗に書いてたし、セルフコードレビューもしてたし、ネストが深くて途中で迷子になることなかったんですよ、それなりに。

 #include  <stdio.h> #include  <time.h> #include  <string.h>

int main(void){
   char fhotoSet[5][100];//生写真5枚入り 最大100セットまで
   char cmpflg[15];//コンプリートチェック用フラグ?
   char dame;
   int cmp_cnt;//コンプリートした回数
   int syutugenritsu[15];
   
   int i,j,k,l,m,n,k2,s;//ループカウンタ
   
   for(s=0;s<15;s++)syutugenritsu[s]=0;
   
   //乱数初期化
   srand((unsigned int)time(NULL));
   
   //試行
   //nというかi+1セット買うを10000回試行してみて結果出力
   for(i=0; i<30; i++){
       //初期化。あってるか不安 ここでよいのか
       memset(cmpflg, 16/**/, 15);//さらに不安
       memset(fhotoSet, 0, 5*100);
       cmp_cnt = 0;

       //printf("●%dセット買った時(現状MAX5)\n",i+1);        
       //1万ケース
       for(j=0; j<10000; j++){
          // printf(" %d回目の試行(現状MAX3)\n",j+1);
  
           //重複が無いように15種から5種をセット

           //最大100セット分抽選処理
           for(k=0; k <= i; k++){
               //printf("  %dセット目のデータ格納処理\n",k+1);
               //力業(重複しなくなるまで回す5枚だし)
               int set_flg=0;//もっと考えよう
               while(!set_flg){
                   
                   int chohukunashi = 1;
                   //セット数i分
                   for(l=0; l<5; l++){
                       //処理めんどいな!
                       fhotoSet[l][k] = rand() % 15;//
                   }
                   
                   //重複チェック
                   for(l=0; l<5;l++){
                       for(m=0; m<5;m++){
                           if(l==m)continue;//自分との重複は見ない
                           if(fhotoSet[l][k]==fhotoSet[m][k]){//重複してたら
                               chohukunashi = 0;
                           }
                       }
                   }
                   set_flg = chohukunashi;
               }
              /*//debug用ダンプ
               int hoge,hoge2;
               printf("   ");
               for(hoge=0;hoge<5;hoge++){
                   printf("%x",fhotoSet[hoge][k]);
               }
               printf("(%dセット目 )\n",k+1);
               //debug用ダンプここまで*/
               
               //重複無しなのでカウント処理(出現枚数検証用)
               for(s=0;s<5;s++){
                   syutugenritsu[fhotoSet[s][k]]++;
               }
           }
           //多分データは取れたので結果チェックしてみる

           memset(cmpflg, 0, 15);//初期化ここか?
           dame = 0;// 
           
           for(k2=0; k2<=k; k2++){//セット数分回す.該当Noを引けてるか設定
               for(l=0;l<5;l++){//lとか使いまわすな
                   cmpflg[fhotoSet[l][k2]] = 1;
               }
           }
           //コンプできてるか?
           for(n=0; n<15; n++){
               if(!cmpflg[n]){
                   dame = 1;
               }
           }
           //駄目が0ならコンプで加算
           if(!dame){
               cmp_cnt++;
           }
       }
       //i+1セット買った場合の結果出力
       printf("%dセット購入:コンプ率%d.%d%\n",i+1,cmp_cnt/100,cmp_cnt%100);
       
       //消したらタイムアウトする?
       for(s=0;s<15;s++){
           //printf(" ");
       }
       
   }//nセット分のループここまで
   //出現率を出力
   for(s=0;s<15;s++){
       printf("No.%d:%d枚\n",s+1,syutugenritsu[s]);
   }
}

この記事が気に入ったらサポートをしてみませんか?