ループなしで1〜100を印字するトリック
「ループ・再帰・gotoを使わずに1から100までを出力するプログラムは書けるか」というパズルに対する、数学的トリックによる解法。
仕掛け
\frac{1000}{999^2} = \frac{1000}{998001} = 0.001002003004005006007008009010011012\ldots
999² = 998001 で割ると、小数展開が3桁ずつ 001, 002, 003, ... と1ずつ増えていく数列になる。これを桁数の大きいところまで計算し、3桁ごとに区切って読めば、1から100(さらにその先)までが順番に出現する。
任意の反復構文を使わず、多倍長の有理数演算(=内部的には多倍長整数の除算)1回だけで「1からNまでの連番」を作り出せる、という点が面白い。
実装(Gauche/Scheme)
Shiro Kawaiのブログ記事で紹介されているGauche実装:
(format #t "~399,'0:d\n" (floor (* (/ 1000 (square 999)) #e1e300)))
1000/999²を有理数のまま10^300倍してからfloorで整数化。formatの~399,'0:dが幅399・ゼロパディング・3桁カンマ区切りを一手に行う。
実装(Raku / mutsu)
自作Rakuインタプリタmutsuで動かしてみた実験では、FatRatすら使わずRaku標準の多倍長Intだけで再現できた。
say sprintf("%0303d", (1000 * 10**303) div 999**2).comb(3).head(100).join(' ');
一般化できる考え方
この手法は「多倍長有理数(または多倍長整数の除算)の小数展開に、意図した数列を桁ごとに埋め込む」というアイデアの一例。分母を工夫すれば連番以外のパターンも原理的には埋め込める。ループ構文を使わない縛りパズルにおける定番の抜け道の一つ。