LoginSignup
2
2

More than 5 years have passed since last update.

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

Posted at

数学ガールの秘密ノート第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
2
2
0

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
2
2