Help us understand the problem. What is going on with this article?

[Ruby chan gem] 数学ガールの秘密ノート第104回の縁取りの実装を格好良くした

More than 5 years have passed since last update.

数学ガールの秘密ノート第104回の縁取りについて適当に実装しましたが( http://qiita.com/cielavenir/items/2598ecd6d7edb9900cc1 )、フィルタ関数が受け取るものが画像全体であるという制限がありました。
これを、秘密ノートに書いてあるとおり、1行ずつ読ませるようにしたい。

ここで問題になるのが、filter_downです。これは行を1個読み飛ばす処理が必要となります。
RubyのEnumeratorは値を出力することしかできず、単純なFiberだと親と子の間に値を1個しか溜めておくことができません。
その点、Golangのchanは、値を複数溜めておくことが可能です。
chanの「<-」演算子はちょうど秘密ノートに書いてある「送信」「受信」の概念にピッタリあてはまるということもあります。
https://twitter.com/cielavenir/status/561054114960769024
https://twitter.com/hyuki/status/561054600145293312

Golangでごりごり書けたとして、関数型のようにきれいに書ける気がしないので、この機能をRuby上に実装し、chan gemとしてリリースすることにしました。
https://github.com/cielavenir/ruby-chan

これを用いると、数学ガールの秘密ノート第104回の縁取りはこのように格好良く実装できます。
まず最初に、echo/filter_right/filter_left/filter_up/filter_downフィルタに1行ずつデータを送ります。
続いて、全てのフィルタが準備出来ている間、「filter_right/filter_left/filter_up/filter_downから1行ずつ取ってきてビット積を取り、反転して、echoから1行取ってきたものとビット積を取る」処理を行います。

mathgirls104_chan.rb
#!/usr/bin/ruby
require 'chan'

filter_right=Chan.new{|ch|
    loop{
        ch<<(ch.receive>>1)&0xffff
    }
}
filter_left=Chan.new{|ch|
    loop{
        ch<<(ch.receive<<1)&0xffff
    }
}
filter_up=Chan.new{|ch|
    ch<<0
    loop{
        ch<<ch.receive
    }
}
filter_down=Chan.new{|ch|
    ch.receive
    15.times{
        ch<<ch.receive
    }
    ch<<0
}
echo=Chan.new{|ch|
    loop{
        ch<<ch.receive
    }
}

puts Chan.new{|ch|
    list=[echo,filter_right,filter_left,filter_up,filter_down]
    loop{
        n=ch.receive.to_i(2)
        list.each{|ch|ch<<n}
        while list.all?(&:next?)
            ch<<'%016b'%[echo.receive&([filter_right,filter_left,filter_up,filter_down].map(&:receive).reduce(:&)^0xffff)]
        end
    }
}.gen_enum(DATA.to_enum).to_a

__END__
0000000000000000
0000000000000000
0011111111111100
0011111111111100
0011111111111100
0011100000000000
0011100000000000
0011111111100000
0011111111100000
0011111111100000
0011100000000000
0011100000000000
0011100000000000
0011100000000000
0000000000000000
0000000000000000
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away