「世界が終わるプログラム」情報局(随時更新)
※最新:2022.2/9更新
全国の不安のみんな、お元気ですか~!世界を終わらせた男、chitoseArkでございます!みんなー!会いたかったよ~!!
意味分かんない前振りはそこらへんに置いといて!
ということで「note創作大賞」応募作品としてエントリーさせていただきました拙著「世界が終わるプログラム」に対し、facebook内で当方も所属しているグループ「IchigoJam-FAN」より識者の皆様のコメントやプログラム、そして画像などの提供をいただきました。この情報局ではそれらを随時紹介していきたいと思います。
さぁ皆様、共に世界を終わらせましょう!
ルールはシンプルで、「6面体のサイコロを10個振って全部1の目を出したら世界が終わる」です。これをコンピューターを使ってどう実現するか。腕と知略の見せどころです。
掲載につきましては許諾もしくはイイネなどを確認したうえで行なっているつもりですが、もし意図せずに掲載されてしまった等や名前をHNにしてほしい等がございましたら、facebook内の久保田裕之宛までメッセージかコメントくださいませ。note会員の方はここにコメントくださってもOKです。
1.IchigoJam-ap(Windowsアプリ)を使用(斎藤さん)
まずは私のnoteに何度かご登場いただいております、十勇士パソコンクラブ(長野県上田市)の斎藤先生からのご提供にてお届けします。
「10個のさいころを振って、全部1になるのは何回目か?」
面白いテーマですね。私もやってみました。
スピード勝負なので、Windows PC上の「IchigoJam-ap」アプリでやってみました。
<IchigoJam ap>
https://15jamrecipe.jimdofree.com/basic/ichigojam-ap/
10個のさいころを振るプログラムは以下のとおりです。
10 '*DICE 1X10
20 CLV
30 X=X+1
40 IF X=10000 X=0:Y=Y+1
50 S=0
60 FOR D=0 TO 9
70 N=RND(6)+1
80 ?N;
90 S=S+N
100 NEXT
110 ?" ";DEC$(Y+10000,4);DEC$(X+10000,4)
120 IF S>10 GOTO 30
130 ?"THE WORLD IS END!"
乱数の条件を揃えるため、アプリ起動直後にプログラムをペーストして、すぐRUNしてみました。
結果は「90,214,825回」と随分遅かったです。計算時間は3時間ほど。
ちなみにPCのCPUは、Core i5-10400(6コア12スレッド、ベース2.9GHz、最大ターボ4.3GHz)です。
CPU-Zで見ていると、プログラム動作中はほぼ4.0GHzで動いていたようです。
斎藤先生の文中にある「IchigoJam-ap」っていうのは2020年4月に発売された「プログラミング教育マスター」という教材を購入すると付いてくるものなのだそうです。
あとGithubから1.4β13のファームウェアをダウンロードする必要があるとのこと(下記サイトよりダウンロードできるようです)。
それにしても私が作ったグチャグチャ無理やりなコードに比べ、斎藤先生のリストのなんと洗練されていることか。FOR文を使った繰り返し処理が見事に決まっています。IchigoJam特有の5ケタ以降ルールについても、DEC$という「数を文字列にする」などを使い解決しています。流石…!
そして、90,214,825回=3時間は凄いです!しれっと言ってますが、これコンピューターがもうちょっとで1億回に届く回数サイコロ振り続けたってことで、世界終わっちゃいますってば本当に!IchigoJam-apに頭が下がります。そして斉藤先生にも頭が下がりますペコペコ。
2.GIGA IchigoDake(IchigoJam R相当)を使用(斎藤さん)
さらに斎藤先生からは以下のようなコメントが。
GIGA IchigoDake(CPUはIchigoJam Rと同じ)で動かしてみましたが、見た感じはIchigoJam-apの10倍以上遅いようです。乱数の確率にもよりますが、もしかすると30時間?
え…。IchigoJam Rってそんな早くないのですか?
従来品の10倍の速度で動けるって話では?
IchigoJam Rは、従来のIchigoJam Sと比べると、計算速度は10倍くらい、画面表示は5倍くらい速いです。
Windowsアプリ版のIchigoJam-apと比べるとさすがに遅いです。
あ、やっぱし10倍くらいにはなってるんですね。
むしろWindows用IchigoJam-apがよく出来過ぎているということか。
今度これ使ってみたいなぁ…。
3.IchigoJam RにIchigoLatte Pythonファームウェア(斎藤さん)
引き続き斎藤先生。次のようなコメントをいただきました。
(重ね重ね本当にありがとうございます!)
IchigoJam RにIchigoLatte Pythonファームウェアを入れて、Pythonで計算してみました。
まだ計算中ですが、Basicの10倍くらいのスピードで、1時間で200万回のペース。機能がシンプルな分、速度は速いのでしょう。
s=0
x=0
while s!=10:
x=x+1
a=rnd(6)+1
b=rnd(6)+1
c=rnd(6)+1
d=rnd(6)+1
e=rnd(6)+1
f=rnd(6)+1
g=rnd(6)+1
h=rnd(6)+1
i=rnd(6)+1
j=rnd(6)+1
print(a,b,c,d,e,f,g,h,i,j," ",x)
s=a+b+c+d+e+f+g+h+i+j
exit(1)
IchigoJam R Pythonは6,177,712回。3時間ほどで終了しました。
あのぅすみません、「IchigoJam RにIchigoLatte Pythonファームウェアを入れて」とかの時点でなに言ってるのかよく分かってないです。というか、Python動いてたらもうそれIchigoJamじゃなくないですか?
…と思って調べてたら、IchigoLatteってJavaScript、Ruby、FORTH、Python、JavaScriptと何でもアリになってるんですね。これ電子工作マガジンに載ってましたっけ?私があんまし理解できてなかったかもです。
でも世界を終了させるのっていろいろな方法があるものですね。いやはや勉強になります。そしてIchigoJamはまだまだ奥が深い!
4.十進BASICを使用(富樫さん)
続いては、IchigoJamではなくWindowsで動く十進BASICなる言語で世界の終わりに挑戦してくださりました、同IchigoJam-FANの富樫さんのコメントをご紹介します。
フリーソフトの十進BASICでPRINT文をなるべく使わないようにした下記のプログラムだと、はやく結果がでます(35792713回目で約8分)。次の実行は乱数を変える必要があります。
またIchigojamの実機のプログラムは計算だとVIDEO 0にすると2倍近くの速さになりますよ。
十進BASIC
10 X=0
15 M=0
20 X=X+1
30 LET A=int(rnd*6)+1
40 LET B=int(rnd*6)+1
50 LET C=int(rnd*6)+1
60 LET D=int(rnd*6)+1
70 LET E=int(rnd*6)+1
80 LET F=int(rnd*6)+1
90 LET G=int(rnd*6)+1
100 LET H=int(rnd*6)+1
110 LET I=int(rnd*6)+1
120 LET J=int(rnd*6)+1
130 IF X=10000 THEN GOTO 180
150 IF A+B+C+D+E+F+G+H+I+J=10 THEN GOTO 160 ELSE GOTO 20
160 PRINT"セカイ ハ オワリマシタ。"
170 goto 170
180 M=M+1
185 X=0
196 PRINT M
190 GOTO 150
200 end
結果は中断を押すと詳しくわかります。
十進BASICというのは初めて伺いました。見たところ文法自体はBASICが多少分かれば違和感なく入れそうですね。35,792,713回目で約8分はすごいです。例の記事ではコンピューターが計算しているビジュアルを出すためにあえてPRINTを使っていますが、確かにPRINTしない方が速いというのはあるかも知れません。
また「Ichigojamの実機のプログラムは計算だとVIDEO 0にすると2倍近くの速さになります」というのも知りませんでした。だとすると私の実験はだいぶ損してたかも知れないですね…。ありがとうございます!
5.c++を使用(菊谷さん)
※2022.2/9
ついに来たるべきものが来たという感じです。おそらく普通にプログラムを組める言語としてはこれが最も速い処理速度を誇るのではないでしょうか。菊谷さんからの投稿をご紹介いたします。
IchigoJamからは外れますが、noteの方でc/c++に言及されていたので、c++で作成したプログラムを投稿いたします。
実行結果は、途中経過を表示しないバージョンで5回ほど実施して、3秒から118秒となりました。(Core i7-8700 3.20GHz)
結構ばらつきがありますね。
ソースコードは、はじめはベタなCのプログラムだったのですが、c++らしく書き直してみました。
IchigoLatteだと、BasicやPython以外にも JavaScript/Ruby/FORTHなどが動くので、それらの言語で書いてみるのも面白いかもしれませんね。
私が書いたC++のソースは次の通りです。
// -----------
// サイコロの目がすべて1になるまで振り続ける
// OnlineGDBにて動作確認
// https://www.onlinegdb.com/online_c++_compiler
// -----------
//
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono> // 時間測定
using namespace std;
//#define DISP_ALLDATA // 途中のデータをすべて表示する
const int dice_num = 10; // サイコロの個数
const int dice_roll_max = 6; // サイコロの目の最大値
// n_cnt回目に振ったすべてのサイコロを表示する(sum=サイコロの目の合計)
void disp_dicedata(int n_cnt, vector<int>dice, int sum) {
cout << n_cnt << ": ";
for_each(dice.begin(), dice.end(), [](int x) { cout << x << " "; });
cout << " sum = " << sum << endl;
}
// メイン
int main()
{
// 乱数発生器初期化
unsigned int seed = (unsigned int)time(NULL);
srand(seed);
// メインループ
int n_cnt = 1;
cout << "start." << endl;
std::chrono::system_clock::time_point start_time, end_time;
start_time = std::chrono::system_clock::now(); // 計測開始
while (1) {
// サイコロを用意する
vector<int> dice(dice_num);
// サイコロを振る
for_each(dice.begin(), dice.end(), [](int& i)
{ i = rand() % dice_roll_max + 1; }
);
// サイコロの目の合計を求める
int sum = 0;
for (size_t i = 0; i < dice.size(); sum += dice[i++]);
#ifdef DISP_ALLDATA
disp_dicedata(n_cnt, dice, sum); // 途中結果(終了時含む)の表示
#endif
// サイコロの目の合計が10(=すべて1)になったらループを抜ける
if (sum == dice.size()) {
#ifndef DISP_ALLDATA
disp_dicedata(n_cnt,dice,sum); // 終了時のサイコロ表示
#endif
break;
}
n_cnt++;
}
end_time = std::chrono::system_clock::now(); // 計測終了時間
double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count(); //処理に要した時間をミリ秒に変換
cout << "completed." << endl;
cout << "elapsed time = " << (double)elapsed/1000.0 << "sec" << endl;
}
// <--ここまで
<実行について>
chromeなどのブラウザで、
https://www.onlinegdb.com/online_c++_compiler
にアクセスすると、エディタみたいな画面が現れるので、そこにソースコードを書き込んで実行します。
初回起動時にはすでにhello,worldプログラムが書き込まれていて、上の方にある"RUN"ボタンで実行できます。
実行結果(振った回数:サイコロの値(1~10) サイコロの目の合計)
1回目
51932777: 1 1 1 1 1 1 1 1 1 1 sum = 10
time: 75.297 sec
2回目
2241207: 1 1 1 1 1 1 1 1 1 1 sum = 10
time: 3.235 sec
3回目
81828861: 1 1 1 1 1 1 1 1 1 1 sum = 10
time:118.188 sec
4回目
80678029: 1 1 1 1 1 1 1 1 1 1 sum = 10
time:116.453 sec
5回目
11873665: 1 1 1 1 1 1 1 1 1 1 sum = 10
time: 17.219 sec
ちなみに、dice_numとdice_roll_maxの値を変えるといろいろなパターンが試せるので、例えば、dice_num=50,dice_roll_max = 2にすると、50個のコイントスができます(^^;)
あと、ソースコード中の12行目辺りに、
//#define DISP_ALLDATA
という定義があると思いますが、先頭の//を取ると、毎回のサイコロの状態が表示されるようになります。
…ということで菊谷さん、ありがとうございました!(ここに至るまでいろいろやりとりしましたが、それらの内容を編集、抜粋して掲載しています)
いやはや、ほぼそのままコピペして実行したとはいえ、これ私にとって人生初めてのC++体験ですよ!コンパイラすら満足に入れられない私がここまでやれたの本当に菊谷さんのおかげです。
そして噂にたがわず早いですこれ。
上の図(菊谷さん提供)だと43,923,614回サイコロ振るのにかかった時間が19.316秒という、F1かっていう話ですよ。
私もやってみようっと。
うわー!!24,067,891回サイコロ振って13.25秒とか、さらにタイム縮まっちゃったよ!!
ただサイコロの出目を表示するバージョンにすると、やっぱりその分は時間かかる模様。それでも早いですよ。実行してまもなく6ケタ到達です。
出目を表示しないと本当に爆速なので、このプログラムをいろいろいじってさらに難しい世界の終わりに挑戦してみるとか楽しめそうです。
ということで「世界が終わるプログラム」情報局、現時点ではここまで。
引き続き新着情報がありましたら随時更新していきたいと思います。
(2022.2/9 Update)
この記事が気に入ったらサポートをしてみませんか?