Hudson勉強会
本日Hudson勉強会で発表した資料をアップします。
無線ルータ導入
WEPの無線LANを使い続けるのは危険だと思っていたので、マルチSSIDに対応した無線LANが欲しいと思っていたのですが、新宿のヤマダ電機にて6000円で売っていたので、ついに購入に踏み切りました。
BUFFALO Air Station NFINITI HighPower Giga 11n/g/b対応 無線LANアクセスポイント WZR-HP-G300NH
- 出版社/メーカー: バッファロー
- 発売日: 2009/04/01
- メディア: Personal Computers
- 購入: 6人 クリック: 330回
- この商品を含むブログ (49件) を見る
ひかりONEで、既に提供されていたルータの代わりに利用出来るか不安だったのですが、一工夫することで無事に接続もでき、自宅内回線をWPA2/TKIP+AES、DS用にインターネット接続限定のWEPの2つを設定して、無事に運用出来ています。
残念なことは、今まで使っていた無線LANは超強力でかなり遠隔でも無線が使えていたのが使えなくなったことでしょうか。今はワンルームなので、無意味に強力な無線LANを使うことに意味はないのですが。
あなたのスキルで飯は食えるか 史上最大のコーディングスキル判定
あなたのスキルで飯は食えるか 史上最大のコーディングスキル判定
http://www.itmedia.co.jp/enterprise/articles/1004/03/news002.html
この手の問題を解くのはCマガ電脳倶楽部以来だったので、久々に楽しんで解けました。
コーディング完了までは1時間半。テストで九蓮宝燈が正しく出力されないところで、ようやく実装ミスに気づきましたorz トータルタイム 2時間半。40分で解くってやっぱり凄いな……。
特に工夫点はないのですが、九蓮宝燈が正しく判定されない地点では刻子/順子判定は最初に見つかったものをreturnする実装になっていたのですが、それだと特定パターンしか見つけられないことに気づいたため、offsetでズラして探していくようにして、その過程で見つかったものをyieldで返すようにしておきました。おかげで、修正点は少なくて済んだのがよかった。
とりあえず、九蓮宝燈の結果だけ掲載しておきます。
/home/kirika/ruby% ruby marjang.rb 1112345678999
(111)(234)(567)(999)[8]
(111)(234)(678)(999)[5]
(111)(345)(678)(999)[2]
(111)(234)(567)(99)[89]
(111)(234)(789)(99)[56]
(111)(456)(789)(99)[23]
(11)(123)(456)(999)[78]
(11)(123)(678)(999)[45]
(11)(345)(678)(999)[12]
(11)(123)(456)(789)[99]
(123)(456)(789)(99)[11]
#!/usr/bin/ruby class Marjang # 与えられた配牌から初めに見つかった刻子を取り出す # 見つかったらyieldで返す def kohtsu!(haipai) haipai_bak = haipai.dup offset = 0 # 刻子判定用配列とそれ以外の牌を格納する配列 k = [] l = [] while !haipai.empty? pai = haipai.shift if k.empty? # 刻子判定用配列が空なら、無条件で追加 k.push(pai) elsif k[0] == pai # 刻子判定用配列に入っている値と同じなら、追加 # 判定用配列の長さが3になった地点で、値を戻す k.push(pai) if k.length == 3 haipai.each{|p| l.push(p) } yield k, l haipai = haipai_bak.dup k = [] l = [] offset = offset + 1 offset.times{|n| l.push(haipai.shift) } end else # 上記以外の場合は、刻子ではないため、 # 刻子判定用配列を含めて元に戻す k.each{|p| l.push(p) } k = [] k.push(pai) end end end # 与えられた配牌から初めに見つかった順子を取り出す # 見つかったものはyieldで返す def syuntsu!(haipai) # 順子判定用配列と、それ以外の配列 haipai_bak = haipai.dup offset = 0 s = [] l = [] while !haipai.empty? pai = haipai.shift if s.empty? # 順子判定用配列が空なら、無条件で追加 s.push(pai) elsif s[-1] + 1 > pai # 順子判定用配列に入っている末尾の値 + 1より小さい場合は # 次の牌を読む l.push(pai) elsif s[-1] + 1 == pai # 順子判定用配列に入っている末尾の値 + 1と等しい場合は # 順子判定を継続する。判定配列の長さが3になったら、 # 順子判定用配列と残りを返す s.push(pai) if s.length == 3 haipai.each{|p| l.push(p) } yield s, l # 配牌を元に戻して、offsetをずらす haipai = haipai_bak.dup s = [] l = [] offset = offset + 1 offset.times{|n| l.push(haipai.shift) } end else # 上記以外の場合は、順子ではないため、 # 順子判定用配列を含めて元に戻して新しい値をセットする haipai.unshift(pai) l.push(s.shift) end end end # 与えられた配牌から初めに見つかった対子を取り出す,なければnilを返す def toitsu!(haipai) # 対子判定用配列と、それ以外を格納する配列 t = [] l = [] while !haipai.empty? pai = haipai.shift if t.empty? # 対子用判定配列が空なら無条件に追加 t.push(pai) elsif t[0] == pai # 対子判定配列と同じ値が入って入れば対子確定 t.push(pai) haipai.each{|p| l.push(p) } return t, l else # それ以外の値の場合は対子ではないので判定配列を # 空にして新しい値をセットする t.each{|p| l.push(p) } t = [] t.push(pai) end end # 何も見つからない場合はnilと配牌をreturnする return nil, haipai end # 待ちを探索する def search_wait_pai(haipai, answer_stack) if haipai.length <= 4 # 配牌4個以下になったら待ちを判定する # 刻子、順子が存在する場合は、単騎待ち kohtsu!(haipai.dup){|group, left| make_answer(answer_stack.dup.push(group), [left]) } syuntsu!(haipai.dup){|group, left| make_answer(answer_stack.dup.push(group), [left]) } # 対子が存在する場合 # カンチャン/リャンメン/ペンチャン待ち # もしくはシャンポン待ちが存在すればよい group, left = toitsu!(haipai.dup) unless group.nil? if left[0] == left[-1] #シャンポン待ちのため、groupおよびleftが待ち make_answer(answer_stack.dup.push(group), left) make_answer(answer_stack.dup.push(left), group) elsif left[0] + 1 == left[1] || left[0] + 2 == left[1] # カンチャン/リャンメン待ち make_answer(answer_stack.push(group), left) end end else # それ以外の場合は、順子、刻子のどれかがないかを探す kohtsu!(haipai.dup){|group, left| search_wait_pai(left.dup, answer_stack.dup.push(group)) } syuntsu!(haipai.dup){|group, left| search_wait_pai(left.dup, answer_stack.dup.push(group)) } end end def make_answer(answer_stack, wait_group) if @answer[answer_stack.sort] == true return else @answer[answer_stack.sort] = true end answer_stack.sort.each{|group| print "(#{group})" } print "[#{wait_group}]\n" end def initialize @answer = {} end end def main mj = Marjang.new haipai = ARGV[0] haipai_array = [] for i in 0...haipai.length haipai_array.push(haipai[i].chr.to_i) end mj.search_wait_pai(haipai_array.sort.dup, []) end main()
初めてTwitterで自分の発言がBuzzった日
Twitterを始めて一年半。
フォローもフォロワーも130人程度。Tweet数は3500程度。
ようやく脱初心者レベルのTwitterユーザになれたかなというこの頃になって、ついに自分の発言がBuzzるという貴重な出来事がありましたので、その時の気持ちを忘れないようにブログに記しておきます。
- 元の発言
元の発言はこの発言。
http://twitter.com/Kirika_K2/status/11587927238
勉強会会場のバーはホワイトボード、無線LAN、プロジェクタ+飲み放題+食事で一人当り4000円という価格で素敵なんだけど、穴場過ぎて潰れそうで怖い。東京で10人前後で勉強会企画してる人は利用してあげてください。 http://bit.ly/btQ6wa なるべくRTお願いします。
- 経緯
発端は私が中心メンバーとなって主催している勉強会があって、10名程度でやっていたのですが、勉強会の主催はとにかく場所の確保が大変で、場所がなくて苦労していました。あまりにも勉強会の場所探しが大変なので、Plaggerで勉強会の候補地を自動巡回するスクリプトを組んで、候補になりそうな場所を半自動的に探させる始末。発言の中のURLはそんな過程で偶然見つかった場所の一つでした。
値段も書いてなかったので、高いんだろうなぁ……ととりあえずダメ元で電話して恐る恐る聞いてみたところ、意外なほど安い値段。昨年末ぐらいからですが、月1回利用させてもらうことにしました。10人程度ちょっとしか入らない小さい会場ですが、ホワイトボード、無線LAN、プロジェクターと勉強会に必要な3種が揃っていて、ささやかながら食事と、ドリンクも飲み放題というサービスで半年ぐらい満足して使わせて貰っていました。
半年間満足に使わせてもらっていたのですが、最近になって食事の量が少しずつ減っているのを感じ、土曜日でも自分達以外に、お客さんが入っていることをあまり見ないので、いつまでも自分達だけの秘密の勉強会会場として使いたかったのですが、バーの存続のためにTwitterに情報を流すことを決めました。
- 発言直後
自分のように小規模な勉強会を開催したくても場所がなくて困ってる人は多いだろうなぁ、と思っていたので、多少のRTはあると思っていたのですが、発言書き込み直後から徐々にRTが増え始め、30分後には1分間に一回RTが増え、5分間で1人がフォローしてくれるという状態。最終的にRTしてくれた人は200人を超え、favorite 約60、私のFollowerが1発言で30人増えました。RTしてくれた人は大抵100人以上Followerがついてた人が殆どだったので、延べで10000人以上。勉強会に興味のある人最低1000人以上には情報が伝わったと思います。自分のTweetが私からしかフォローしていない著名な人のRTを介して自分のTLに返ってくるという貴重な経験もさせてもらいました。
元々店のクオリティが高く、紹介されるに十分な価値を持っていたのですが、改めてTwitterの凄さを感じた瞬間でした。
そんなわけで、今日は人気店になる前に最後かもしれないまったりとした時間を過ごすためにバーに行ったのでした。
紹介してくださった方々、本当にありがとうございます。
http://twitter.com/#search?q=http%3A%2F%2Fbit.ly%2FbtQ6wa
ブックマークしてくれた方々
http://b.hatena.ne.jp/entry/www.bar-cuore.jp/
- RTの凄いところと問題点
元々Twitterは140文字の制限があります。
で、元の発言は140文字ギリギリに情報を詰めて流しました。投稿前はもっと長くて140文字ギリギリに収めるのに苦労しました。
RTをすると私の発言の140文字の何かを削って、コメントを追加しなければいけません。
皆さん色々工夫して私のコメントを編集して、自分のコメントを追加しているようで見ていて面白かったです。文章をどうやって短くするのか、とても勉強になりました。
ですが、その過程で重要な情報が欠落し、意図しない結果になっているものもありました。
例えば、元の発言では「10人程度で」という情報があったのですが、RTされたものには、この部分が欠落したRTもありました。本日丁度バーに居るときにかかってきた問い合わせでは4人で勉強会をしたいというものがあり、バーのマスターも良い方なので紹介した値段で承諾していたのですが、これでは人がいないよりは良いと思いますが、ペイしないと思います。
勉強会と店とがお互いにメリットがあるよう、なるべく皆さんのご協力をお願いします。
- 最後に
もう自分だけの勉強会場所ではなくなってしまいましたが、これからは遊びに行けば、もしかしたらギークな人とも会える機会が増えるのかな?と思うと、ちょっと楽しみです。リナカフェみたいに、ギークが集まる場所になって、そこでお互いが刺激しあえる場になると、それは凄く素敵なことだと思います。
飲み放題のつく勉強会では、シェイクカクテルなどの手間のかかる飲み物は飲めないのですが、お酒もとても美味しいバーなので、できれば勉強会以外の場でも使って頂けると、とても嬉しいです。
FizzBuzz問題 あれから半年。
Rubyをメインとする仕事を始めて、まもなく半年になります。
当時書いたFizzBuzzと比べて、今書いたらどんなFizzBuzzが書けるか、ちょっとやってみました。
偶然にもちょうど今日から半年前でした。
http://d.hatena.ne.jp/Kirika/20090922
p (1..100).map{|x| a = (x % 3 == 0 ? "Fizz" : "") + (x % 5 == 0 ? "Buzz" : "") x = a == "" ? x : a }
変わったところ
- eachからmapに変更して、配列に展開してから処理するようにした。
ブロックの中にpを埋め込まなくていいので、汎用性が上がる。
- if-elseから三項演算子に切り替え。
演算子としてif文を使用出来るのは、便利。
ただし演算子の結合順序が % > + > ?:の順番なので、括弧で囲む必要がある。
- ブロック変数の有効活用
ブロック変数を書き換えるとyieldで渡された配列の中の変数に影響を与えることが出来る。
当時はこの規則を知らなかったので、冗長な書き方になっていた。