トップページ⇒tech
523コメント255KB

■■C++で大きな数を作るスレ■■

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2009/03/24(火) 20:27:50
C++ で大きな数を返すプログラムを作るスレです。
以下のプロトタイプの関数の戻り値で出来るだけ大きな数を返すものを作りましょう。

int main();

●ルール
最大でも1スレに収まる範囲とし、
1スレで完結したプログラムとしてください。
文字数も書いてください

●言語仕様
言語は C++ 2003 準拠とします
int と float は十分な精度があるとします
メモリは十分にあるとします
実行時間は問わないこととします

機種依存、コンパイラ依存の値が返るプログラムは不可
プリプロセッサ、ライブラリの使用は不可

●文字数カウントルール
動作上不要なコメント、スペース、タブ、改行は文字数に含めない
言語上必要なスペース、タブ、改行はカウントする(改行は1文字とする)
0197デフォルトの名無しさん2009/04/18(土) 01:13:49
せこい改変ですが。
// 80文字
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}
int main(){return a(a(9));}
0198デフォルトの名無しさん2009/04/18(土) 02:36:49
195と混ぜてみた
int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}
int x,y[9]={9},*z=y+9;
int main(){for(;z>y;--*--z<0?*z=x=a(x,9):*(z=y+9));return x;}
//135B
0199デフォルトの名無しさん2009/04/18(土) 12:43:43
>>196
そうですよ。

同じ数をより少ない文字で表現しているものがあったり、
同じ文字数以下でより大きな値を返すものがあれば
記録に掲載はされません。
同じ文字数、同じ大きさなら原則先に掲載された方としますが、
考え方が大きく異なるなら両方載せるかもしれません。

>>197
その手があったか。
現状80文字以下最大。
0200デフォルトの名無しさん2009/04/18(土) 13:02:28
>>198

残念ながら、
>>195より
>>193の77文字の方が1文字少ないので、
>>197 と >>193の77文字を合わせるより、
>>193の77文字を2個合わせた方が微妙に文字数が少なく作れてしまう。

// 131文字
int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}
int A(int b,int c){return b*c?A(b-1,A(b,c-1)):a(c,c);}
int main(){return A(9,9);}

aとAはほとんど表現が似てるので、
引数を追加してくっつけると、

// 100文字
int a(int n,int b,int c){return b*c?a(n,b-1,a(n,b,c-1)):n?a(0,c,c):c+9;}
int main(){return a(1,9,9);}

これを同じ文字数で微妙に値を大きくしたのが、

>>193 の 100文字
0201デフォルトの名無しさん2009/04/18(土) 20:14:27
>>200 ダウト。かな。

9をxに修正。8重ループ相当。

int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}
int x,y[9]={9},*z=y+9;
int main(){for(;z>y;--*--z<0?*z=x=a(x,x):*(z=y+9));return x;}
//135B

ちなみにこれはa(a(a(…の個数どころかa(が増殖していく速度がアッカーマン級
という感じなので、>>193の100文字なんかよりはるかに大きいはず。
たとえば>>200の式でA(3,3)を定義したとすると
aと(と)と,の4つの記号と数字があれば表記できてしまう程度だろうけど、
上の式の9を3に変えても別の記号を使わなければ表記不可能な程度には
大きいと思う。

0202デフォルトの名無しさん2009/04/19(日) 01:53:15
>>192(>>195)
aへの代入が消えてるからグローバル変数の初期値に依存するってことで>>1を満たしてないことない?
0203デフォルトの名無しさん2009/04/19(日) 08:07:11
>>201
> たとえば>>200の式でA(3,3)を定義したとすると
> aと(と)と,の4つの記号と数字があれば表記できてしまう程度だろうけど、

>>201 のと同程度に表記不可能
(もし可能だと言うなら A(2,2) でも良いのでやってみてください)
A(n,x) でn重ループ相当ですよ


>>202
それは大丈夫。
初期値無しのグローバル変数は必ず0に初期化される。
0204デフォルトの名無しさん2009/04/19(日) 14:22:12
>>203
thx。やっと理解したw。A(n,x)はn重ループと本質的には変わらないのか。
なんだアッカーマン最強じゃないか。
02052042009/04/19(日) 14:54:11
>>203
アッカーマン最強なら、こんな感じでどうよ
// 102文字
int a(int n,int b,int c){return b*c?a(n,b-1,a(n,b,c-1)):n?a(n-1,c,c):c+9;}
int main(){return a(9,9,9);}
02062042009/04/19(日) 15:10:28
結局これでも同じかな?
// 100文字
int a(int b,int c,int d){return b*c*d?a(b-1,c,a(b,c-1,a(b,c,d-1))):d+9;}
int main(){return a(9,9,9);}
0207デフォルトの名無しさん2009/04/19(日) 19:45:28
>>205 は大きいけど、
>>206 は77文字のと同じくらいじゃいか?
0208デフォルトの名無しさん2009/04/19(日) 21:57:59
>>207 77文字の関数のa(9,9)は、>>206の関数で表すとa(1,9,9)のつもりです。

でも206より↓のがずっと大きいことに気づく。

// 84文字
int a(int b,int c){for(c*b)c=a(b-1,a(b,c-1));return c+9;}int main(){return a(9,9);}
0209デフォルトの名無しさん2009/04/19(日) 22:01:00
おっと訂正

// 86文字
int a(int b,int c){for(c*b--)c=a(b,a(b+1,c-1));return c+9;}int main(){return a(9,9);}
0210デフォルトの名無しさん2009/04/19(日) 22:19:44
誰かグッドスタイン数列ベースのやつも頼む
0211デフォルトの名無しさん2009/04/19(日) 22:36:35
for(;c*b--;)だった。88文字か。

グッドスタイン数列をググってみたけどちっちゃいな
0212デフォルトの名無しさん2009/04/19(日) 22:47:49
Ackに比べたらちっちゃいけど、1変数だから対角化したら結構でかくならんかな
文字数を考えるとAckを強化してったほうがでかいだろうけどね
0213デフォルトの名無しさん2009/04/20(月) 22:16:21
しかし>>47どうも納得いかないなあ。
上のほうは大きいけど、下の方a(9,0)=9だし、a(99,9)は9の(99の9乗)乗とかそのくらいにしかみえない。
誰か数学詳しい人どのくらいの値なのか教えてくれ。

// 89文字
int a(int b,int c){for(;b--;)c=a(b,c?a(b+1,c-1):9);return c+9;}int main(){return a(9,9);}
0214デフォルトの名無しさん2009/04/20(月) 22:35:26
>>213
9の(99の9乗)乗程度の小さな数だったら確実にA(5,3)よりは小さい
ここを見たらA(99,9)がどれだけとんでもないかわかると思う
ttp://en.wikipedia.org/wiki/Ackermann_function
0215デフォルトの名無しさん2009/04/21(火) 00:09:01
>>213 それではなく>>47の下の方の、偽アッカーマン関数の話です。

上の方は、a(99,2)=a(98,a(99,1))=a(98,a(98,2))=a(98,…,a(5,a(4,a(3,2))))…)
下の方は、a(99,2)=a(98,a(99,1))=a(98,a(98,a(99,0)))=a(98,a(98,99))

同じように見えて、展開と評価を繰り返していくとありえないくらいの
2が沸いてくるわけで全然違うようにみえませんか
一見、下の方が大きく見えるのは錯覚じゃないと

1以外の数字の扱いが同じだからいいじゃないかとか、
文字数が短くなった分、引数に大きな値を入れればいいとか、
そんな次元ではなくて、アッカーマンさんの発明自体が失われていないかな

// 79文字
int a(int b,int c){return b?a(b-1,c?a(b,c-1):9):c+9;}int main(){return a(9,9);}

のほうが実は

// 79文字
int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(999,9);}

より大きいんじゃないの?
0216デフォルトの名無しさん2009/04/21(火) 00:11:38
自分にレスしてしまった; 上は>>214へのレスだす
0217デフォルトの名無しさん2009/04/21(火) 01:41:48
>>209
たぶんあまり大きくない。
少なくともこれよりは小さい。

int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}
int main(){return A(18,9);}

>>209 のbを1個増やす力は、
上のbを2個増やす力よりも小さい。
0218デフォルトの名無しさん2009/04/21(火) 01:52:14
>>213

int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}

a(m,0) = 9
a(0,n) = n+9
a(1,n) は 初期値9 に対し a(0,x) を n 回行った数、9nより大きい数
a(2,n) は 初期値9 に対し a(1,x) を n 回行った数、9のn乗より大きい数
a(3,n) は 初期値9 に対し a(2,x) を n 回行った数、つまり9^9^9^9^...^9 (9がn個) より大きい数
.....
0219デフォルトの名無しさん2009/04/21(火) 02:00:56
int a(int m,int n){return m?n?a(m-1,a(m,n-1)):m:n*9;}

a(m,0) = m
a(0,n) = n*9
a(1,n) は 初期値1 に対し a(0,x) を n 回行った数、9のn乗より大きい数
a(2,n) は 初期値2 に対し a(1,x) を n 回行った数、9^9^9^9^...^9 (9がn個) より大きい数
.....
0220デフォルトの名無しさん2009/04/21(火) 02:13:34
>>213 も >>209 と同じで、
少なくともこれよりは小さい。

int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}
int main(){return a(18,9);}
0221デフォルトの名無しさん2009/04/21(火) 02:22:17
>>194 の100文字を2文字縮められました。
int a(int b,int c,int d=9){return c*d?a(b,c-1,a(b,c,d-1)):b?a(0,d):d+9;}int main(){return a(1,9);} // 98文字

>>205 の102文字を3文字縮められました。
int a(int b,int c,int d){return b+c&&d?a(b-!c,c?c-1:d,a(b,c,d-1)):d+9;}int main(){return a(9,9,9);} // 99文字
0222デフォルトの名無しさん2009/04/21(火) 12:50:09
>>217-220
わかりやすい説明ありがと。もう工夫する余地はないのか。
>>221
100文字以下になるとは思わなかった。すごい。
0223デフォルトの名無しさん2009/04/21(火) 18:55:52
>>193 の 43文字と77文字を合体
int a(int b,int c){return b*c?a(b-1,a(b,c-1)):c+9;}int b=9;int main(){return a(b--?main():9,9);} //96文字
0224デフォルトの名無しさん2009/04/21(火) 20:42:04
9^9^9ってC++的に一般的な書き方じゃないとおもうけど
9の9の9乗乗=つまり右肩にどんどん小さく乗ってくやつのこと?
それとも9の9乗の9乗=(9^9)^9のこと?
0225デフォルトの名無しさん2009/04/21(火) 20:49:39
xorに決まっておる。
0226デフォルトの名無しさん2009/04/21(火) 22:19:44
>>218 >>219 の ^ はべき乗の意味です。
pow(9,pow(9,pow(9,......pow(9,pow(9,9)))))...) (9がn個)

C++言語のスレなので、今後べき乗の意味で ^ は使わないようにします。
0227デフォルトの名無しさん2009/04/22(水) 07:44:42
int a=9;int main(){return a--?9<<main():9;} // 43
int a=99;int main(){return a--?9<<main():9;} // 44
int a=9e9;int main(){return a--?9<<main():9;} // 45
int a=9e99;int main(){return a--?9<<main():9;} // 46
int a=9e999;int main(){return a--?9<<main():9;} // 47
int a=9e9999;int main(){return a--?9<<main():9;} // 48
int a=9e99999;int main(){return a--?9<<main():9;} // 49
int a=9e999999;int main(){return a--?9<<main():9;} // 50
int a=9e9999999;int main(){return a--?9<<main():9;} // 51
int a=9<<(9<<99);int main(){return a--?9<<main():9;} // 52
int a=9<<(9<<999);int main(){return a--?9<<main():9;} // 53
int a=9<<(9<<9999);int main(){return a--?9<<main():9;} // 54
int a=9<<(9<<99999);int main(){return a--?9<<main():9;} // 55
int a=9<<(9<<999999);int main(){return a--?9<<main():9;} // 56
int a=9<<(9<<(9<<99));int main(){return a--?9<<main():9;} // 57
int a=9<<(9<<(9<<999));int main(){return a--?9<<main():9;} // 58
int a=9<<(9<<(9<<9999));int main(){return a--?9<<main():9;} // 59
int a=9<<(9<<(9<<99999));int main(){return a--?9<<main():9;} // 60
0228デフォルトの名無しさん2009/04/22(水) 07:45:23
int a=9,b,c=a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 61
int a=99,b,c=a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 62
int a=9e9,b,c=a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 63
int a=9e99,b,c=a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 64
int a=9e999,b,c=a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 65
int a=9e9,b,c=a<<a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 66
int a=9e99,b,c=a<<a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 67
int a=9e999,b,c=a<<a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 68
int a=9e9999,b,c=a<<a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 69
int a=9e99999,b,c=a<<a;int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 70
int a=9e9,b,c=a<<(a<<a);int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 71
int a=9e99,b,c=a<<(a<<a);int main(){for(;b?b--:b=a*c--;)a<<=a;return a;} // 72
int a=9,b,c,d=a;int main(){for(;b?b--:c?b=a*c--:c=a*d--;)a<<=a;return a;} // 73
int a=99,b,c,d=a;int main(){for(;b?b--:c?b=a*c--:c=a*d--;)a<<=a;return a;} // 74
int a=9e9,b,c,d=a;int main(){for(;b?b--:c?b=a*c--:c=a*d--;)a<<=a;return a;} // 75
int a=9e99,b,c,d=a;int main(){for(;b?b--:c?b=a*c--:c=a*d--;)a<<=a;return a;} // 76
0229デフォルトの名無しさん2009/04/22(水) 07:46:56
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(9);} // 77
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(99);} // 78
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(9e9);} // 79
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(9));} // 80
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(99));} // 81
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(9e9));} // 82
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(9)));} // 83
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(99)));} // 84
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(9e9)));} // 85
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(9))));} // 86
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(99))));} // 87
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(9e9))));} // 88
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(9)))));} // 89
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(99)))));} // 90
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(9e9)))));} // 91
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(a(9))))));} // 92
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(a(99))))));} // 93
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(a(9e9))))));} // 94
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int main(){return a(a(a(a(a(a(a(9)))))));} // 95
0230デフォルトの名無しさん2009/04/22(水) 07:47:39
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int b=9;int main(){return a(b--?main():9);} // 96
int a(int b,int c=9){return b*c?a(b-1,a(b,c-1)):c+9;}int b=99;int main(){return a(b--?main():9);} // 97
int a(int b,int c=9,int d=9){return c*d?a(b,c-1,a(b,c,d-1)):b?a(0,d):d+9;}int main(){return a(1);} // 98
int a(int b,int c=9,int d=9){return b+c&&d?a(b-!c,c?c-1:d,a(b,c,d-1)):d+9;}int main(){return a(9);} // 99
int a(int b,int c=9,int d=9){return b+c&&d?a(b-!c,c?c-1:d,a(b,c,d-1)):d+9;}int main(){return a(99);} // 100
0231デフォルトの名無しさん2009/04/25(土) 17:22:17
tarai functionとその亜種はどうよ
0232デフォルトの名無しさん2009/04/26(日) 00:41:14
↑
計算量がどのくらいになるかを考えてみたけど、
大きく見積もっても指数関数くらい。
0233デフォルトの名無しさん2009/04/28(火) 04:19:51
ずいぶん夜更かししちまった。
いろいろこねくり回した結果こうなりますた。
ちゃんと停止するかどうかも含めて評価よろしこ。
ところでint型関数がreturn文を持たないのはありなんだっけ?
gccではコンパイル通ったけど。

347文字
typedef int I;
I a=9e99,s=9,*x,*p,*q;
I A(){a<<=(a<<a);}
I B(I (*f)()){I b,c,d;for(d=c=b=a;d;(b--)?0:(c--)?(b=a):(d--)?(c=b=a):0)f();return a;}
I C(){s<<=B(A);x=new I[s+1];for(p=x;p<x+s;p++)*p=B(A);*p=-1;}
I D(){for(;;){for(p=x;!*p;p++);if(*p==-1)return B(A);for(q=x;q<p;q++)*q=B(A);B(A);(*p)--;}}
I E(){C();D();}
I main(){B(E);return a;}
0234デフォルトの名無しさん2009/04/28(火) 19:13:07
>>233
関数Aを3重ループを使って大きい関数Bを作り、
関数Bをn重ループを使ってさらに大きい関数Dを作り、
関数Dを3重ループを使ってさらに大きい関数を作るという感じですか
大きさ的には >>230 の97文字より大きく、98文字より小さい

戻り値のある関数をreturnを省略して抜けると動作不定である為、
A C D E と Bの引数の関数の戻り値はvoidにする必要あり

3重ループのBよりもn重ループのDの方が強いので
Bは無くしてDに引数fを付けた方が良いと思う。こんな感じで。
void D(void f()){......}
void F(){D(A);}
int main(){D(F);return a;}

02352332009/04/28(火) 20:07:41
結構頑張ったのに既存のに負けてるのか。(´・ω・`)
98文字に負けてるってところを詳しく解説してホシス。
02362332009/04/29(水) 10:12:52
若干数学的に。

まず、次のような関数loopとaddを用意する。
int loop(int a,int b,int ((*f)(int,int))){
int result=a;
for(int i=1;i<b;i++) result=f(a,result);
return result;
}
int add(int a,int b){return a+b;}

そうすると掛け算,指数関数は次のように実装できる。
int mul(int a,int b){loop(a,b,add);}
int pow(int a,int b){loop(a,b,mul);}

ここで、掛け算はloopを1回、指数関数はloopを2回,
関数の定義で使用していることがわかる。
そこで、その関数を定義するのに必要なloopの回数を返す関数loop_rankを考える。

loop_rank(add)==0;
loop_rank(mul)==1;
loop_rank(pow)==2;
etc.
02372332009/04/29(水) 10:23:57
あーせっかくここまで考えたのに、
C言語だと関数と関数を合成して新しい関数を返す関数がかけねぇ?
関数ポインタを使えば何とかなるかなぁ…
02382332009/04/29(水) 10:43:35
C++にはテンプレートがあるぢゃまいか。ナイス!

template<int N>
int f(int a,int b)
{
return loop(a,b,f<N-1>);
}

template<>
int f<0>(int a,int b)
{
return add(a,b);
}

だな。
これで大体アッカーマン相当とおもわれ。
0239デフォルトの名無しさん2009/04/29(水) 10:48:13
>>238
コンパイル通るかそれ?
02402332009/04/29(水) 10:51:47
でだ。
要するに生の整数を比べずにループが何重になってるかってことを比べる、
というのをみんなやってたわけだが、loop_rankを厳密に定義しておけば議論がしやすいかなと。
02412332009/04/29(水) 10:54:14
g++では通った。
ほかはしらね。
0242デフォルトの名無しさん2009/04/29(水) 11:01:02
なんというか、大きい数を探すことよりも
「どれが大きいか」を判定することのほうがよっぽど難しいな
02432332009/04/29(水) 11:10:09
実際、2つのプログラムが与えられてどちらが大きい値を返すか判定する
なんてのは計算不能だろな。
与えられたプログラムが停止することが保障されてたとしても、
最終的な値を2進の整数に展開せずににメモリ使用量に制限かけて判定する
なんてことが可能なのかどうか…
02442332009/04/29(水) 11:27:13
さて、>>233のloop_rankがいくつか?というのを知りたいわけだが、
loop_rankじゃ結果が大きくなりすぎてだめだな。
もうすこし上の概念を導入しないと。

02452332009/04/29(水) 11:50:32
とりあえず、考察対象を>>238のfに限るとして、
f<n>とf<m>からf<n+m>を生み出すような操作ってどんなものになるだろう?

02462332009/04/29(水) 11:59:45
うん。あれだ。
今、自分が考えてるのが整数なのか関数なのかテンプレートなのか
わけが解らなくなってきたw
02472332009/04/29(水) 12:11:35
まあ、なんだ。とりあえず>>1さん、
>>233が>>230の98文字より小さいという根拠を聞かせてくれ。
02482332009/04/30(木) 20:41:57
>>1は優雅にバッカンスでもいったのか?
最底辺IT奴隷orひきニートたるべきム板民にあるまじきブルジョアっぷりだな。
まったくもってけしからん。
俺もGWあけたら奴隷生活に戻るんだからはやめに返事クレ。
02492332009/05/01(金) 20:39:27
>>230の98の大きさがよくわからんなぁ。
Aをアッカーマン関数とするとおおむね、
A(1,9,9)=A(A(9,9),A(9,9))
でいいんかな?
025012009/05/02(土) 16:16:35
>>236
クラスや構造体を使えば実装可能です。
struct OPERATOR{
  virtual int operator()(int x,int y) = 0;
};
struct OPERATOR_ADD:OPERATOR{
  virtual int operator()(int x,int y){
    return x+y;
  }
};
struct OPERATOR_LOOP:OPERATOR{
  OPERATOR*a;
  OPERATOR_LOOP(OPERATOR*a_):a(a_){}
  virtual int operator()(int x,int y){
    int r=x;
    for(;--y;)
      r=(*a)(x,r);
    return r;
  }
};
OPERATOR* mul = new OPERATOR_LOOP(new OPERATOR_ADD);
OPERATOR* power = new OPERATOR_LOOP(mul);
OPERATOR* tetration = new OPERATOR_LOOP(power);
025112009/05/02(土) 16:25:48
>>244
loop_rank がnの関数を f[n](x) とした時、
関数 f[x](x) を考えてみる。
この関数は、f[大きな整数](x) よりも増大度が大きく、
x=大きな整数を超える場合は
f[x](x) の方が大きい。
f[x](x) はloop_rank で言うと無限みたいなもの。
0252デフォルトの名無しさん2009/05/02(土) 16:33:39
今度は引数が2個のオペレーターではなくて
引数が1個の関数を考えてみる。

struct function{
  virtual int operator()(int x) = 0;
};
struct function_successor:function{
  virtual int operator()(int x){ return x+1; }
}
struct function_loop:function{
  function*a;
  function_loop(function*a_):a(a_){}
  virtual int operator()(int x){
    int r=x;
    for(;x--;)
      r=(*a)(r);
    return r;
  }
};
struct function_loop2:function{
  function*a;
  function_loop2(function*a_):a(a_){}
  virtual int operator()(int x){
    int r=x;
    for(;x--;)
      r=(*a)(r);
    return r;
  }
};
025312009/05/02(土) 16:39:45
function_successor は単に1を足すだけの簡単な関数。
function_loopは function_loop(ある関数) とすることで
loop_rank を1個増やすことができる。

function_loop2 は引数の数字分function_loopを付け足すものである。

function*a=new function_loop2(new function_successor)
とした時、
(*a)(10) はfunction_successor に対してfunction_loop を10個追加した関数に10を入れたもの
(*a)(100) はfunction_successor に対してfunction_loop を100個追加した関数に10を入れたもの
である。
この時のaのloop_rankを考えると、
function_successor に function_loop を整数個つけたいかなる関数よりも
早く増大することが分かる。
たとえばfunction_loop を100個つけた関数と比べると、
引数が101以上の場合はa の方が値が大きくなる。

025412009/05/02(土) 16:48:24
この時のaのloop_rankを記号ωとあらわすことにする。

>>233 の場合、
関数B(A)はloop_rankが5と6の間くらいの関数。
関数EはB(A)に対し、loop_rankがωのループを行うので、
loop_rankが6+ωくらい。
ここで、253のaを考えてみると、
(*a)(10) に対して(*a)(20) は10 loop_rank が増えた関数に20を代入している。
>>233 の関数Eも
B(A)のloop_rankが小さくても引数をちょっと大きくするだけで追い抜いてしまう。
つまり、関数Eはloop_rankがωである (*a) などとほとんど同じ増大度であるといえる。

最終の関数 B(E) はEにloop_rankを3増加したものとなるので、
loop_rank はω+3くらいである。
つまり、 >>233 は loop_rank が ω+3 程度の関数に 9e99 を入れたものとなる。
025512009/05/02(土) 16:56:08
次に、98文字のものを考えてみる。

再帰定義をよく見てみると、
関数 a(b,c,x) に対して、関数 a(b,c+1,x) はloop_rankが1個増えた関数だということがわかる。

a(0,0,x) はx+9 でloop_rankは0なので、
a(0,c,x) のloop_rank はcになる。

a(1,0,x) = a(0,x,9) なので、
a(1,0,x) はloop_rankが整数であるどんな関数よりも増大度が大きく、
loop_rank は >>253 の(*a) と同じωとなる。

さらに、2番目の引数を9にした a(1,9,x) は
loop_rankがω+9

関数 a(1,x,x) を考えてみると、
loop_rankがω+整数であるどんな関数よりも増大度が大きく、
loop_rankはω+ωになる。
0256デフォルトの名無しさん2009/05/02(土) 16:58:35
>>252 の function_loop2 や、
99文字のbを1増やすのは
loop_rankをω増やす操作となる。

98文字のものは、99文字のものから1文字減らす為に、
bを0と1に制限したもの。
0257デフォルトの名無しさん2009/05/02(土) 17:09:06
>>252
function_loop2 が間違ってました。
こうですね。

virtual int operator()(int x){
  function*f=a;
  for(int i=x;i--;)
    f=new function_loop(f);
  return (*f)(x);
}
02582332009/05/04(月) 07:36:40
>>1
了解。
丁寧な解説ありがとう。
大きな関数を繰り返すことでさらに大きな関数を作る、そしてそれをまた繰り返して…
というのは>>1はもうやり尽くしていて結論が出ている。それを超えるには全く別の発想が必要になる。
ということでよろしいか?


025912009/05/04(月) 11:41:45
大きな関数を作る方法はいろいろあって、
とてもやり尽くせないと思うけど。

とりあえず >>252 の loop, loop2, loop3 を一般化したloop_n 相当を作ってみました。
最適化して解読しにくいと思うので多少説明。
{b,c,d} は関数bにloop_cを(d+1)回行ったもの
{0,0,0} は特別扱いで f(x) = x+9
変数 d は無くても作れるけど、ループより再帰の方が短かったので足しました。
関数は1文字で右から計算を行う operator = で作るのが一番短かったので
みにくいけど = で実装

// 138文字
struct a{
  a*b;
  int c,d;
  int operator=(int f){
    a g={b,c-!d,d?d-1:f},h={&g,c};
    return c+d?*b=(c*d?h:g)=f:f+9;
  }
}b,c={&b,9};
int main(){return c=9;}
0260デフォルトの名無しさん2009/05/31(日) 14:54:05
いいもの見つけた。
反復対数関数lg* n
lg^i n =def
 n (i=1の時)
 lg(lg^(i-1) n) (i>0,lg^(i-1) n>0の時)
 未定義 (i>0,lg^(i-1) n<=0またはlg^(i-1) nが未定義の時)

lg* 2 = 1
lg* 4 = 2
lg* 16= 3
lg* 65536=4
lg* 2^65536=5
と思って調べていたら
逆アッカーマン関数(α)ってのもあるのか
α(m,n)=min{i>=1 : Ack(i,floor(m/n)) >= log2 n}

α(2^(2^(2^65536)) - 3) = 4
0261デフォルトの名無しさん2009/06/04(木) 00:00:36
反復対数関数の逆関数がパワータワー(テトレーション)だよね。
>>91 が43文字で作ってる。

アッカーマンは >>9 が最初で
現在は77文字まで縮まってる。
0262デフォルトの名無しさん2009/07/02(木) 00:25:46
あげ
0263デフォルトの名無しさん2009/07/06(月) 01:25:30
int main()
{
return 1.0/【>>1の人間としての存在価値】;
}
0264デフォルトの名無しさん2009/07/08(水) 20:23:17
このスレではたぶんダントツにでかい。

// 149文字
struct a{
  int b;
  a*c,*d;
  a*e(int f){
    a*g=f?e(f-1):d,h={b-!c,c?c->e(f):g,g};
    return b||c?new a(h):d;
  }
}b,*c=&b;
int main(){
  for(;c=c->e(b.b+=9););
  return b.b;
}
0265デフォルトの名無しさん2009/07/22(水) 19:03:44
de bruijn sequence誰か実装して
B(2,5)=2048
B(2,6)=67108864
B(2,7)=144115188075855872
0266デフォルトの名無しさん2009/07/23(木) 21:55:04
>>265
定義が良くわからないけど、
B(2,n) = 1<<(1<<n-1)-n
なので、

int main(){return 2;} // B(2,3) 21文字
int main(){return 16;} // B(2,4) 22文字
int main(){return 2048;} // B(2,5) 24文字
int main(){return 1<<57;} // B(2,7) 25文字
int main(){return 1<<502;} // B(2,10) 26文字
int main(){return 1<<8178;} // B(2,14) 27文字
int main(){return 1<<65519;} // B(2,17) 28文字
int main(){return 1<<524268;} // B(2,20) 29文字
int main(){return 1<<8388584;} // B(2,24) 30文字
int main(){return 1<<67108837;} // B(2,27) 31文字
int main(){return 1<<536870882;} // B(2,30) 32文字
int main(){return 1<<(1<<98)-99;} // B(2,99) 33文字
int main(){return 1<<(1<<998)-999;} // B(2,999) 35文字
0267デフォルトの名無しさん2009/08/22(土) 08:00:35
あげ
0268デフォルトの名無しさん2009/08/22(土) 08:27:25
いまさらだがどれだけ長い文字列を印字できるかの方が
へんなC++の整数型もどきを使わずに済んでルールが簡明になったな
0269デフォルトの名無しさん2009/08/28(金) 00:45:33
>>268
長い文字列を印字する為に、事実上無制限の状態数が必要。
事実上無制限の状態数を表す為に、事実上無制限のメモリが必要。
事実上無制限のメモリを実装する為に、事実上無制限のポインタサイズが必要。

ということで、
どうせポインタサイズが事実上無制限なら
int のサイズも事実上無制限にしてしまえ!
というのがintサイズ無制限のルールにした理由。

>>267 のルールだと、
 void pchar(void);
を1文字印刷する関数として、
プログラム終了までにこの関数を何回コール出来るか競う感じか。
単純にステップ数を競うのでも良い。(ステップの定義が必要だが)
0270デフォルトの名無しさん2009/08/28(金) 00:51:00
整数型に制限があれば配列のサイズも制限が出てくるので、
多倍長整数の実装を普通の方法で行うことは出来ない。

整数型のサイズに依存しない符号なし無制限整数型の実装を考えてみた。

struct UINT {
  UINT*next;
}
UINT*inc(UINT*a){
  return new UINT(a);
}
UINT*dec(UINT*a){
  return a->next;
}
UINT*add(UINT*a,UINT*b){
  while(a){
    a=dec(a);
    b=inc(b);
  }
  return b;
}
UINT*mul(UINT*a,UINT*b){
  UINT*c=0;
  while(a){
    a=dec(a);
    c=add(b,c);
  }
  return c;
}
....
0271名無しさん@そうだ選挙に行こう2009/08/30(日) 08:16:27
いっそのことBFでステップ数を競うのもありかもね。
http://pc12.2ch.net/test/read.cgi/tech/1231384158/
0272デフォルトの名無しさん2009/09/24(木) 02:19:57
#include <iostream>
main(){for(;;)std::cout<<"9";}
0273デフォルトの名無しさん2009/09/25(金) 20:41:53
>>272
>>2 のダメな例 8個目
0274デフォルトの名無しさん2009/09/26(土) 02:50:03
#include <limits>
int main(){return numeric_limits<int>::max();}

//63文字
0275デフォルトの名無しさん2009/09/26(土) 09:27:16
>>274
多くの場合 >>2 の2個目と同じ値が返る
0276デフォルトの名無しさん2009/09/26(土) 13:27:03
>>40
int main(){int a=1,b=0;for(;a>b;a++,b++);return b;}

こうすれば無限にならないのでは?
0277デフォルトの名無しさん2009/09/26(土) 19:15:26
>>275
だから何?
0278デフォルトの名無しさん2009/09/26(土) 23:02:05
>>276
無限にならなくても環境依存なのでルール違反。

>>277
int の最大値は環境依存なのでルール違反。
0279デフォルトの名無しさん2009/09/26(土) 23:04:53
>>278
>int の最大値は環境依存なのでルール違反。

はぁ?
intの最大値は環境依存だが、>>274のコードは環境依存ではない。
0280デフォルトの名無しさん2009/09/27(日) 02:56:37
>>279
それはないだろ
規約上はオーバーフローした場合の挙動は未定義なんだから
aがオーバーフローしたとき0にするのではなく
非数字やエラーとして扱う処理系を作っても一向にかまわない
a>bが真になったり、システム自体がダウンすることもありうる
結局オーバーフロー依存は環境依存だから禁止なの
0281デフォルトの名無しさん2009/09/27(日) 02:59:49
ごめん。上のは>>276へのレスね。
>>279の方はよくわかんね
0282デフォルトの名無しさん2009/09/27(日) 03:09:01
ってこのスレそもそもインクルード禁止じゃねーかw
なにが、はぁ?だよ
0283デフォルトの名無しさん2009/09/27(日) 03:16:30
int main(){return 32767;}

//25文字
//環境依存がダメなら、intが32768以上の値をとることを期待するのは機種依存だからダメ。
0284デフォルトの名無しさん2009/09/27(日) 07:30:06
>>279
環境によって main が返す値が変わるのだから環境依存。

>>283
「int と float は十分な精度があるとします」
このスレのルールです
意味は >>30-31
0285デフォルトの名無しさん2009/09/27(日) 11:57:39
int f(x){return x?f(9<<f(x-1)):9;}
int main(){return f(9);}

//59文字
0286デフォルトの名無しさん2009/09/27(日) 11:58:37
int f(int x){return x?f(9<<f(x-1)):9;}
int main(){return f(9);}

//63文字
0287デフォルトの名無しさん2009/09/27(日) 14:50:34
int h(int f,int a){return f?a?h(f-1,h(f,a-1)):h(f-1,a):a+9;}
int main(){return h(9);}

//85文字
//結局アッカーマン
0288デフォルトの名無しさん2009/09/27(日) 16:03:36
int h(int f,int a){return f?a?h(f-1,h(f,a-1)):h(f-1,a):a+9;}
int main(){return h(9,9);}

//87文字
//結局アッカーマン

// >>285, >>287 取り消し
0289デフォルトの名無しさん2009/09/27(日) 18:38:14
int h(int f,int a){return f?a?h(f-1,h(f,a-1)):h(f-1,9):a+9;}
int main(){return h(9,9);}

//87文字
//結局アッカーマン

// >>288 取り消し
0290デフォルトの名無しさん2009/09/27(日) 23:49:12
>>285 >>286
main関数だけで再帰呼び出すを行うというスゴイ技を
>>91 さんが見せてくれました。
それを微妙に修正したのが >>96 の 43文字の作品。
>>286 とまったく同じ値となります。

>>289
アッカーマン(相当の)関数は >>9 さんが始めに書いていて、
>>83 で 77文字まで縮まっています。

現状の記録は >>227-230 にあります。
詳しそうなので、ぜひ記録更新に挑戦してみてください。
1レス内文字数無制限での記録もお待ちしております。
0291デフォルトの名無しさん2009/09/28(月) 00:08:24
やはり基本はアッカーマンなんだね。もう少し考えてみる。
0292デフォルトの名無しさん2009/09/28(月) 01:09:31
int main()[int r;for(unsigned i=1;i;i++)r=r<(int)i?i:r;return r;]

未定義動作はないぞ。(unsignedな型の計算はオーバーフローにはならないと書いてある)
0293デフォルトの名無しさん2009/09/28(月) 01:10:39
bracketはbraceの間違い…スマソ
0294デフォルトの名無しさん2009/09/28(月) 16:01:09
プログラムを書くプログラムで大きな数できない?
0295デフォルトの名無しさん2009/09/28(月) 16:19:42
ライブラリ関数を使えないから事実上無理だね。
0296デフォルトの名無しさん2009/09/28(月) 21:23:04
>>292
r が初回不定
i を int にキャストした時点でオーバーフローする
環境依存な値が返る

上2個が解決したとしても
環境依存な値が返るのはこの方法では不可避

ところで、
このスレのルールを守って
(int が十分な精度という条件を除いて)
確実にintの最大値を返すものはいままで上がって無かったと思うけど、
出来るのかな?

>>294 >>295
簡単なインタープリタなら1レスで作れるかも。
でも大きな数を返すプログラムをプログラムで作れるかどうか。
0297デフォルトの名無しさん2009/09/29(火) 01:03:47
おっと。indeterminentの解釈がおかしかった。int r;はmain()の外でないとだめですね。
unsignedからintへのキャストで元の値がintで表現できない場合の変換後の値はimplementation definedですがそれはオーバーフローではないのでは?

環境依存なのはその通り。
■ このスレッドは過去ログ倉庫に格納されています