45
29

More than 3 years have passed since last update.

フィボナッチ数列を求めるワンライナー各言語まとめ

Last updated at Posted at 2021-06-15

お遊び記事です.こちらの記事の姉妹版です.いやその,某ラノベ読んでたらとりあえず21番目までのフィボナッチ数列を求める魔術式ワンライナーが書きたくなりましてね,はい.

※なお,ここでいう『ワンライナー(one-liner program)』はシェル芸のようなものとお考えいただけますと幸いです.高い可読性を要する開発現場で混ぜるな危険.

【2021-06-20追加】姉妹版『素数一覧』の続編記事を立ち上げました.こちらと同じスタイルで編集し直しています.

【2021-06-18追加】集まった記述例(2021-06-17更新時点)を動画にしてみました.

制約

フィボナッチ数を求める方法はいろいろありすぎるのと,ワンライナーの趣旨に沿うため,次の制約を設けます.基本的に,REPLを用いて0~21番目の値(0番目は0,1番目は1)を求めるワンライナー実行を想定しています.

  • 一般項による計算は不可
  • フィボナッチ数(列)を求める標準関数・手続き等は使用不可
  • ライブラリやモジュールの追加読み込み不可

こうすると,自ずと関数型プログラミングに近くなるかもしれません.ますます魔(略 気のせいでした.

なお,次は可としています.

  • REPL起動時に自動的に読み込まれるライブラリやモジュール
  • 大域変数代入の複文(セミコロン区切り等)
  • 上限値による処理終了判定(値が10946を超えるまで求める等)

各言語での記述例

最も短いと思われる記述(+筆者が直接確認した実装・バージョン)のみを載せています.より短い表現&他言語版歓迎.

J(9.0.2)
2&(0 1,+/\)~21
Raku(2018.12)
|^2,*+*...*>1e4
APL(Dyalog/TryAPL3.4.5)
{⍵,+/¯2↑⍵}⍣20⊢0 1
dc(1.4.1/GNUbc1.07.1)
1 0[pdsarla+d10947>m]dsmx
Ruby(2.5.5)
([a=-b=1]*22).map{b=a+a=b}
bc(1.07.1)
for(b=1;b+=a<28658;a=b-a)a
Perl(5.30.0)(5.10以降の-Eオプション使用)
say$@=($b+=$@)-$@for++$@..22
Haskell(GHC8.4.4)
let f=0:scanl(+)1f in take 22f
calc(2.12.7.2)
for(b=1;b<2e4;a=(b+=a)-a)print a
Julia(1.0.3)
1|>(a,b=0)->0:21 .|>_->a=(b+=a)-a
PostScript(Ghostscript9.52)
[0 1 20{dup 2 index add}repeat]==
Python3.8(CPython3.9.5)
a=-1;b=1;[b:=a+(a:=b)for _ in'_'*22]
Forth(Gforth0.7.3)
: f 1 0 22 0 do dup . tuck + loop ; f
awk(GNUAwk4.2.1)
BEGIN{for(b=1;b<2e4;b=a+(a=b))print+a}
IchigoJamBASIC(1.4.3web)
A=0:B=1:FORI=0TO21:?A:B=A+B:A=B-A:NEXT
PowerShell(7.1.3)
$x=0;$y=1;0..21|%{$x;$x,$y=$y,($x+$y)}
R(3.5.2)
c(a<-0,b<-1,replicate(20,b<<-a+(a<<-b)))
JavaScript(Node.js10.24.0)
[a=-1,b=1,...Array(20)].map(c=>b=a+(a=b))
Smalltalk(GNUSmalltalk3.2.5)
a:=-1.b:=1.(0to:21)collect:[:n|b:=a+(a:=b)]
Lua(5.3.3)
a=0;b=1;for i=0,21 do print(a);a,b=b,a+b end
Scheme(Gauche0.9.10)
(take((rec(? a b)(lcons a(?(+ a b)a)))0 1)22)
PHP(7.3.27)
$a=0;for($b=1;$b<2e4;$a=($b+=$a)-$a)echo"$a ";
Python2(CPython2.7.17)
reduce(lambda x,_:x+[x[-1]+x[-2]],'_'*20,[0,1])
Python3(CPython3.7.3)
g=lambda*a:len(a)<22and g(*a,a[-1]+a[-2])or a;g(0,1)
Clojure(1.10)
(take 22((fn f[](lazy-cat[0 1](map +(f)(rest(f)))))))
CommonLisp(SBCL2.0.0),Scheme(Gauche0.9.10)
(do((a 0 b)(b 1(+ a b))(l '()`(,@l ,a)))((> b 2e4)l))
Java(JShell11.0.11)
for(int a=0,b=1;b<1e4;System.out.println(b=a-b))a+=b;
Scala(2.11.12/Java11.0.11)
var a=0;var b=1;while(b<1e4){println(a);b=a+b;a=b-a;}
bash(5.0.3)
a=0;b=1;for i in {0..21};do echo $a;t=$((a+b));a=$b;b=$t;done
Kotlin(1.5.20)
fun f(a:Int,b:Int):Int=if(a<1e4){println(a);f(b,a+b)}else a;f(0,1)
LOGO(UCBLogo6.0)
MAKE "A 0 MAKE "B 1 REPEAT 22[PRINT :A MAKE "B :A+:B MAKE "A :B-:A]
Elixir(iex1.12.0)
Enum.reduce(1..20,[0,1],&(&2++[&1-&1+Enum.at(&2,-2)+List.last(&2)]))
EmacsLisp(GNUEmacs26.1)
(let((a 0)(b 1))(while(< b 2e4)(princ a)(princ" ")(setq b(+ a b)a(- b a))))
SQL(SQLite3)
WITH t(a,b)AS(SELECT 0,1 UNION SELECT b,a+b FROM t)SELECT a FROM t LIMIT 22;
Erlang(OTP21)
lists:reverse(lists:foldl(fun(_,A)->[hd(A)+hd(tl(A))|A] end,[1,0],lists:seq(1,20))).
sh(dash0.5.10)
a=0;b=1;while true;do t=$((a+b));echo $a;case $a in(10946)break;;esac;a=$b;b=$t;done
Vim(8.1)(:でコマンドラインモードに入ってから入力)
echo {g->g(g)}({g->{n,r->n<0?r :g(g)(n-1,[{g->g(g)}({g->{n,a,b->n==0?a :g(g)(n-1,b,a+b)}})(n,0,1)]+r)}})(21,[])
Excel(2021-06-25時点ベータ版)
=LAMBDA(g,g(g))(LAMBDA(g,(LAMBDA(n,r,IF(n<0,r,g(g)(n-1,LAMBDA(g,g(g))(LAMBDA(g,LAMBDA(n,a,b,IF(n=0,a,g(g)(n-1,b,a+b)))))(n,0,1)&" "&r))))))(21,"")

各言語での記述例(番外編)

筆者が実行未確認だったり,ワンライナーと呼ぶには微妙な実行方法(シェル経由やGUI操作,基本ライブラリ追加読込等)だったりするものです.進捗(?)によっては本来の記述例に昇格するかも.

Z80(ZK-80webv0.4)
8000 AF 67 6F 11 01 00 F9 E5 19 EB 82 30 FA
x86-64
echo '.globl main;main:mov $0,%ax;mov $1,%dx;lea f(%rip),%rdi;mov $22,%ecx;l:mov %ax,(%rdi);add $2,%rdi;add %dx,%ax;xchg %dx,%ax;loop l;mov $0,%eax;ret;.bss;f:.zero 44'|gcc -x assembler -&&./a.out
C(gcc8.3.0+dash0.5.10)
echo 'a;main(b){for(;b<1e4;printf("%d ",b=a-b))a+=b;}'|gcc -w -x c -&&./a.out
C++(g++9.3.0+dash0.5.10)
printf "#include<iostream>\\nint main(){for(int a=0,b=1;b<1e4;std::cout<<(b=a-b)<<' ')a+=b;}"|g++ -x c++ -&&./a.out
printf '#include<cstdio>\nint a,b=1;int main(){for(;b<1e4;printf("%%d ",b=a-b))a+=b;}'|g++ -x c++ -&&./a.out
Fortran(f778.3.0+dash0.5.10)
echo '      a=0;b=1;doi=0,21;print*,a;b=a+b;a=b-a;enddo;end'|f77 -x f77 -&&./a.out
GNUassembler(2.34+bash5.0.17)
as <<< '.altmacro;.macro p n;.print "\n";.endm;a=0;b=1;.rept 22;p%a;b=a+b;a=b-a;.endr'
Prolog(SWI-Prolog8.0.2+dash0.5.10)
echo 'assert(f(0,A,_,A)). assert((f(N,A,B,R):-X is N-1,Y is A+B,f(X,B,Y,R))). assert(p:-forall(between(0,21,X),(f(X,0,1,R),format(R),nl))). p,halt.'|swipl -q
Go言語(1.16.5/gore0.5.2-autoimport)
a,b:=0,1;for i:=0;i<22;i++{fmt.Println(a);a,b=b,a+b}
Rust(1.47.0+dash0.5.10)
echo 'fn main(){let mut a=0;let mut b=1;while a<10947{println!("{}",a);b=a+b;a=b-a;}}'|rustc -&&./rust_out

備考

記事に関する補足

  • reduceつおい.次々と反復構文に置き換えられてしまった….
  • Jの例はねっとからのぱくりです.独自には記述できなかった….→そしてそのぱくりから更に短く(コメントより).Jにはどうあがいても短さでは勝てなさそう.→Rakuが勝った.→Jが追い上げた

更新履歴

  • 2021-07-25:Jの記述例を変更(コメントより)
  • 2021-07-20:Jの記述例を変更(コメントより)
  • 2021-07-18:Jの記述例を変更(コメントより)
  • 2021-06-26:Kotlinの記述例を変更(コメントより)
  • 2021-06-25:Excel(ベータ版)の記述例を追加
  • 2021-06-23:Python3.8の記述例を変更(コメントより)
  • 2021-06-21:Perlの記述例を変更(コメントより)
  • 2021-06-21:冒頭に『素数一覧』続編記事について記載
  • 2021-06-20:Perlの記述例・実行方法を変更(コメントより)
  • 2021-06-20:C++の記述例(番外編)を変更・追加(コメントより)
  • 2021-06-20:Go言語,Rust,C++の記述例(番外編)を追加
  • 2021-06-19:GNU assemblerの記述例(番外編)を変更(コメントより)
  • 2021-06-19:GNU assemblerの記述例(番外編)を追加(コメントより)
  • 2021-06-19:PHP,bc,calcの記述例を変更(コメントより)
  • 2021-06-19:Vim,bc,calc,APL,Elixirの記述例を追加(コメント等より)
  • 2021-06-18:制約欄を更に整理・書き直し
  • 2021-06-18:Smalltalkの記述例を修正(Twitterより)
  • 2021-06-18:Haskellの記述例を変更(Twitterより)
  • 2021-06-18:冒頭にYouTubeに公開した記述例の動画(2021-06-17更新時点)を追加
  • 2021-06-18:Kotlin,dc,PowerShell,Emacs Lisp,bash,PHP,Scala,LOGOの記述例を追加(コメント等より)
  • 2021-06-17:Fortranの記述例(番外編)を追加(コメントより)
  • 2021-06-17:制約欄を整理・書き直し
  • 2021-06-17:冒頭にワンライナーに関する注意書きを追加
  • 2021-06-17:Z80の記述例(番外編)を変更(コメントより)
  • 2021-06-17:制約欄に『0~21番目の値(0番目は0,1番目は1)を求める』を明記
  • 2021-06-17:IchigoJamBASICの記述例を番外編から移動(コメントより)
  • 2021-06-17:Cの記述例(番外編)を変更(コメントより)
  • 2021-06-17:awk,Haskell,PostScriptの記述例を変更(コメント,Twitterより)
  • 2021-06-17:Java,Scheme(Gauche限定),sh(dash)の記述例を追加
  • 2021-06-16:Cの記述例(番外編)を変更(コメントより)
  • 2021-06-16:各言語での記述例(番外編)の欄を追加(Z80,x86-64,IchigoJamBASIC,C,Prolog)
  • 2021-06-16:下記制約欄記載に基づきScheme/Common Lisp,awkの記述例を変更
  • 2021-06-16:制約欄に『21番目の値を求める』は『値が10946を超えるまで求める』も可の旨記載
  • 2021-06-16:記述例について,最新版での記述の長さ順に整列
  • 2021-06-16:制約欄にREPLを用いたワンライナー実行の想定,副作用OKの旨記載
  • 2021-06-16:JavaScript,Perl,Smalltalk,Python2,Python3,Rubyの記述例を変更(コメントより)
  • 2021-06-16:Forth,R,SQL,Raku,Erlang,awk,Luaの記述例を追加(Twitter,コメント等より)
  • 2021-06-16:確認した実装・バージョンとREPL実行の旨記載
  • 2021-06-15:Ruby,Jの記述例を変更(Twitter,コメントより)
  • 2021-06-15:SchemeとCommon Lispの記述例を変更・統合(Twitterより)
  • 2021-06-15:Haskell,PostScript,Smalltalk,Perl,Clojure,Julia,Python3.8の記述例を追加(Twitter,コメントより)
  • 2021-06-15:初版公開(Scheme,Common Lisp,Python2,Python3,Ruby,JavaScript,J)
45
29
83

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
29