東灘.rbでは、youRoom内でいろいろとRubyに関する雑談や情報交換をしています。そんな中で参加メンバーの一人であるShimodaさん(@yuji_shimoda)がこんな問題を出題してきました。次のような形式でカレンダーを表示せよ。30「みなさんならどう解きますか?」と聞かれたので、僕も解答例をちょっと考えてみました。この手の問題はプログラミング初心者時代によく見た気がしますが、最近はご無沙汰していました。「解けなかったらめっちゃカッコ悪いやん!!」と思いつつトライしてみました。今回のエントリでは僕が書いたRubyのコード2種類と、試しにHaskellで書いてみたコードの合計3種類を紹介してみます。あ、ちなみにこのエントリにはコードがたくさん出てくるので、スマホで見るのはちょっとしんどいと思います。できるだけPCの大きな画面で見ることをオススメします〜。初期バージョン最初に「とりあえず動けばOK」なコードとテストコード(RSpec)を書いて、その後どんどんリファクタリングしました。そのコードがこちらになります。endendロジックの説明2013年4月を例に挙げると、まず最初に4月1日から4月30日までのDateオブジェクトを配列に詰めます。Date<4/30>]次にこんな感じの2次元配列を作ります。Date]]その後、各行のデータを整形します。30"]さらに、ヘッダーとボディの配列をくっつけます。30"]で、最後に配列を改行文字でjoinすればできあがり、というロジックです。30"いきなり文字列を切ったり貼ったりするのもいいんですが、いったんModelを作ってから(weeks_in_monthメソッド)、それから見た目(View)を整形する(body_rows→calendar_rows→to_s)というのが、オブジェクト指向っぽいかな〜と思ってこんな実装にしてみました。文字列ぶった切りバージョン次にShimodaさんが「新しいロジックで書き直してみました」と言うのでチェックしたところ、それはそれでなかなか興味深いロジックでした。そこで、そのロジックをベースにこんな感じで書き直してみました。endendロジックの説明2013年4月であれば、まず次のように1から30までの一行の文字列を作ります。各値は3桁右詰めになっています。30"次に最初の週の開始位置をずらすための空白文字列を用意します。3文字の空白を作ります。"上の二つの文字列をつなげて、一行の文字列にします。7日)ずつちょん切っていきます。30"]ここまで来ればあとは最初のロジックと同じで、ヘッダーとボディをつなげてjoinすればおしまいです。このロジックでちょっと気になるのは、カレンダーの左側に空白文字が一つ入ってしまうことです。個人的には無用なインデントが入らない方が好みです。30Haskellバージョンところで、Rubyで書いた2つ目のロジックはなんとなく関数型言語向きな気がする、と思ってHaskellで書いてみることにしました。僕はHaskellは全くの初心者です。「ふつうのHaskellプログラミング」を読んだことはありますが、自分でコードを書いたことはありませんでした。そんな僕が必死こいて書いてみた最初のバージョンがこちら。文字列ぶった切りバージョン」と同じです。body]うーむ、よくわからないけど、なんとなく「イケてない感」がぷんぷんと漂ってきます。いうわけで、本やネットを調べてリファクタリングしたのがこちらです。T.pack関数が分割されて、多少は見やすくなったような気がします。「手続き型脳」を脱しきれていないんじゃない?と思ったりもします。「関数型脳プログラマならこう書くんだ!!」というアドバイスがもしあれば、どうぞご教示くださいませ〜。ちなみにHaskellでコードを書く時もHSpecというRSpecライクなテストツールを使いました。リファクタリングをガンガンやっていくためにはテストツールは必須ですね。カレンダー整形問題は練習問題にちょうどいい!このカレンダー整形問題、プログラミング言語の勉強をするにはいろんな意味でちょうどいい問題かも、と思いました。簡単すぎず、難しすぎずなので、僕がHaskellにチャレンジしたように、新しい言語を習得しようとするときに書いてみると良い勉強になると思います。文字列や日付、リスト(配列)等の処理、関数の分割、テストコードの書き方等々、基本的なことをいろいろとカバーしています。初心者は初心者なりの、上級者は上級者なりの書き方ができるので、FizzBuzz問題にみたいに「誰が書いてもほとんど同じ」という結果にはならないはずです。ロジック自体、いろいろなアプローチがあると思うので、他人のコードを見ると「なるほど、そういう手もあるのか」と勉強になると思います。問題も複雑すぎないので、コードがあまり長くなりません。他の人が書いたコードを読む時も、比較的短時間で読むことができます。そんなわけで、みなさんも是非いろんな言語でカレンダー整形問題を解いてみてください。東灘.rbでは月一回ペースでもくもく会を開催しています。西脇〜神戸近辺でRubyに興味がある方は参加してみてくださーい。Haskellバージョン今回書いたコードはGitHubに置いています。見る今回の問題はこの本の練習問題でした。解答例では「万年カレンダーのロジック」を使って解いています。見る僕が数年前に読んだ本です。今回久しぶりにしっかり読み直しました。try以前、今回と同じように一つの問題をいろいろな言語で解いてみたことがあります。このときに使った関数型言語はHaskellではなく、F#でした。はてなブログPro株式会社ソニックガーデンで働くRubyプログラマ。2017年11月に「プロを目指す人のためのRuby入門」を出版。blog)はてなブログをはじめよう!JunichiItoさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。