[awk,Ruby,C#,Java]いくつかの言語でフィボナッチ数生成

2016年7月25日月曜日

awk C# Java Ruby

[SQL] SQLの共通表式ではSQLでフィボナッチ数を生成した。
[python] ジェネレータとイテレータでフィボナッチではMizu A.さんにPythonでフィボナッチ数を生成してもらった。
調子に乗って、いくつかの言語の特徴的な機能を使ってフィボナッチ数を生成してみよう。

[awk]
awkは入力データの加工に適しているから自分でループするのではなく、seqの結果を使ってしまおう。

fib.awk
#!/usr/bin/awk -f
BEGIN { f0 = 1; }
{ print f += f0; f0 = f - f0; }
としておくと、以下のコマンドで任意の個数生成できる。

$ seq 10 | ./fib.awk
1
1
2
3
5
8
13
21
34
55

[Ruby]
RubyはEnumeratorのコンストラクタにブロックを渡せるので、この中でループしよう。
特徴的なのは「|y|」「y << f」のところ。<<演算子でyにfが渡される。
こういう役回りのyをYielderって言うよ。Pythonや次に出てくるC#とは呼び出し関係が逆のイメージだね。
#!/usr/bin/ruby

fib = Enumerator.new { |y|
    f = fn = 1
    loop {
        y << f
        f, fn = fn, fn + f
    }
}
fib.take(10).each{ |n| puts n }

[C#]
C#はPythonと似ているね。ただし、yieldだけではなく、yield returnって書く必要があるよ。
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    public static void Main()
    {
        foreach (var i in fib().Take(10))
        {
            Console.WriteLine(i);
        }
    }

    static IEnumerable<int> fib()
    {
        int f = 1, fn = 1;
        while (true)
        {
            yield return f;
            fn += f;
            f = fn - f;
        }
    }
}

[Java]
Streamを使ってやってみたけど、実はSQLの例に近いかも。
int配列ではなく、無名クラスとかでできないかなーとも思ったけど、生成結果がIntStreamで初項が{ 1, 1 }なんだから、int配列で正しい気もする。
どうだろう。

import java.util.stream.IntStream;
import java.util.stream.Stream;

class Fibonacci {
    public static void main(String ... args) {
        IntStream fib = Stream.iterate(new int[] { 1, 1 }, f -> {
                            return new int[] { f[1], f[0] + f[1] };
                        }).mapToInt(f -> f[0]);
        fib.limit(10).forEach(System.out::println);
    }
}