fib再び

ひとつ前のエントリ(id:Nobuhisa:20081016:1224157485)へのレスポンス

C++

USKさん作

@nobuhisa_k fibonacci数列書いたよ!まずある程度ライブラリを作ったり拾ってきたりしないと何も書く気が起こらない言語それがC++

http://twitter.com/uskz/statuses/963205037

ありがとうございまーす!
これがそれ。

ovn::any_range<int const&, boost::forward_traversal_tag> fib =
    ovn::initial_values(1, 1)
        |ovn::jointed(boost::fusion::make_tuple(ovn::recursion(fib), ovn::recursion(fib)|ovn::dropped(1))|ovn::zipped_with(egg::plus))
        |ovn::memoized(t);
http://d.hatena.ne.jp/uskz/20081017/p2

独習C++の最初の方しか読んだことのない僕からすると「C++ってこんな人でしたっけ?」状態です。
こんなこともできるのかぁ。。。

C#

コメント欄でid:NyaRuRuさんに頂いたコード。
リスト内包版をC#で書いてくださいました。
ありがとうございまーす!
コメント欄に埋めておくのはもったいないので引っ張り出してきました(問題あったら言ってください><)。

using System;
using System.Collections.Generic;
using System.Linq;

public struct Tuple<T1, T2>
{
  public readonly T1 Item1;
  public readonly T2 Item2;
  public Tuple(T1 item1, T2 item2)
  {
    this.Item1 = item1;
    this.Item2 = item2;
  }
}
public static class Make
{
  public static IEnumerable<T> Unfold<T>(this Func<T, T> func, T seed)
  {
    while (true)
    {
      yield return seed;
      seed = func(seed);
    }
  }
  public static Tuple<T1, T2> Tuple<T1, T2>(T1 item1, T2 item2)
  {
    return new Tuple<T1, T2>(item1, item2);
  }
  public static Func<T1, TResult> Func<T1, TResult>(Func<T1, TResult> func)
  {
    return func;
  }
}
static class Program
{
  static void Main(string[] args)
  {
    var fib = Make.Func((Tuple<int,int> tuple) =>
      Make.Tuple(tuple.Item2, tuple.Item1 + tuple.Item2))
          .Unfold(Make.Tuple(1, 1))
          .Select(tuple => tuple.Item1);

    foreach (var item in fib.Take(20))
    {
      Console.WriteLine(item);
    }
  }
}
http://d.hatena.ne.jp/Nobuhisa/20081016/1224157485#c1224217062

う〜ん。自分じゃこれを1から書ける気がしない。笑
勉強させていただきます!

追記

taguoさんにもコメントいただきました。
勉強材料にしたいので転載させていただきます。

public static IEnumerable<TResult> ZipWith<T1, T2, TResult>( this IEnumerable<T1> source1, IEnumerable<T2> source2, Func<T1, T2, TResult> selector )
{
   using( var e1 = source1.GetEnumerator() )
   using( var e2 = source2.GetEnumerator() )
       while( e1.MoveNext() && e2.MoveNext() )
           yield return selector( e1.Current, e2.Current );
}
static IEnumerable<int> Fib()
{
   yield return 1;
   yield return 1;
   foreach( var i in Fib().ZipWith( Fib().Skip( 1 ), ( j, k ) => j + k ) )
       yield return i;
}

1行では書けませんが、似た感じになるでしょうか。

あとNyaRuRuさんのを参考に(Unfoldの引数が逆です)、匿名型とstructの違いを気にしなければ、

public static IEnumerable<T> Unfold<T>( this T t, Func<T, T> converter )
{
   while( true )
   {
       yield return t;
       t = converter( t );
   }
}
static IEnumerable<int> Fib2()
{
   return new { q = 1, w = 1 }
       .Unfold( a => new { q = a.w, w = a.q + a.w } )
       .Select( a => a.q );
}
http://d.hatena.ne.jp/Nobuhisa/20081016/1224157485#c1224262203


自分もC#を操れるようになりたいです。。