give IT a try

プログラミング、リモートワーク、田舎暮らし、音楽、etc.

CodeIQに「カラオケマシン問題」を出題しました。みんなチャレンジしてね!

お知らせ

またもやお知らせです。
タイトルにあるとおり、CodeIQにプログラマの向けの問題を出題しました。


https://codeiq.jp/ace/ito_junichi/q923
f:id:JunichiIto:20140606103810p:plain:w450


先着20名様40名様に限り、みなさんが書いてくれたコードを僕が直接採点いたします!
また、ソニックガーデンの社長、倉貫さんが6月12日に発売する新刊『「納品」をなくせばうまくいく ソフトウェア業界の“常識"を変えるビジネスモデル』も抽選で3名様にプレゼントします!(倉貫さんのサイン入りらしいですよ)


みなさん、ぜひ奮ってご応募ください!


問題: Rubyで「カラオケマシン」を作ってみよう!

出題したのは「カラオケマシン問題」です。
とは言っても、実際に音を鳴らしたりマイクをつないだりするわけではありません。
カラオケで歌うときによく使う、「キーの上げ下げ」をプログラム上でシミュレートしてみましょうという簡単な文字列処理問題です。


問題はブログで公開してもOKとのことだったので、以下に載せますね。


【イントロダクション】

カラオケにはキーを変える機能があります。
+1するとキーが1つ上がります。
-1するとキーが1つ下がります。


たとえば「ドレミファソ」というメロディのキーを2つ上げると「レミファ#ソラ」になります。


「ド」が「レ」に変わった理由はピアノの鍵盤を見るとわかります。


f:id:JunichiIto:20180715103552j:plain
http://mids-player.net/_src/sc219/7208CAE94D589B98AK955C.jpg


ドの2つ右隣にある鍵盤の音はレになっていますね。(ド → ド# → レ)


他の音も同様です。
例えば「ミ」の音が「ファ#」に変わったのも、「ミ → ファ → ファ#」になったためです。(ピンと来ない人は鍵盤をよく見て!)


「ドレミファソ」のようにカタカナだとプログラムで扱いづらいので、英語の読み方、つまりアルファベットに置き換えましょう。


ドレミファソ → CDEFG
レミファ#ソラ → DEF#GA


みなさんに作成してもらうのは、このように元のメロディを自由に上げたり下げたりするプログラムです。

【本題: かえるのうたを自由にキーチェンジ!】

さて、ここからが本題です。
みなさんには、「かえるのうた」を自由自在にキーチェンジするプログラムを作成してもらいます。


かえるのうたのメロディは以下のような文字列で表現されます。

"C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "


縦棒( | )は小節の区切りです。
半角スペースは休符です。
音符と休符が8つ集まると1小節になります。


このメロディ(文字列)を変更するKaraokeMachineというクラスを作ります。
このクラスはインスタンス作成時にメロディを受け取ります。
transposeというメソッドに変化させたいキーの量を渡すと、その分だけキーを上げたり下げたりしたメロディが返却されます。


このクラスの使用例を以下に示します。

melody = "C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "
karaoke = KaraokeMachine.new(melody)
karaoke.transpose(2)
# => "D E F# G |F# E D   |F# G A B |A G F#   |D   D   |D   D   |DDEEF#F#GG|F# E D   "
karaoke.transpose(-1)
# => "B C# D# E |D# C# B   |D# E F# G# |F# E D#   |B   B   |B   B   |BBC#C#D#D#EE|D# C# B   "

# 1オクターブ(12音)以上変えることもできる
karaoke.transpose(12)
# => "C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "
karaoke.transpose(14)
# => "D E F# G |F# E D   |F# G A B |A G F#   |D   D   |D   D   |DDEEF#F#GG|F# E D   "

# ド以外の音から始まるメロディを使う場合もある
melody = "F# G# A# B |A# G# F#   |A# B C# D# |C# B A#   |F#   F#   |F#   F#   |F#F#G#G#A#A#BB|A# G# F#   "
karaoke = KaraokeMachine.new(melody)
karaoke.transpose(6)
# => "C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "
karaoke.transpose(-6)
# => "C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "

さあ、KaraokeMachineクラスを実装してみましょう!


解答方法について

解答の条件は以下の通りです。

解答で使う言語
Ruby 2.0以上
テストフレームワーク
RSpec 2.14以上
解答の提出先
CodeIQ (アカウントの登録が必要です)
解答期限
6月30日(月)AM10:00まで (または解答者が20人に達するまで)

 

解答すると自動的にテスト駆動開発(TDD)も勉強できます!

上の条件を見て「えっ、RSpecを使うの?」って思った人も多いかもしれません。
はい、RSpecを使います。
解答者のみなさんはこちらで想定している仕様が正しく実装されていることを保証するため、RSpecのテストがパスしたコードだけを提出してください。


とはいえ、みなさんの方でRSpecのテストコードを書いてもらう必要はありません。
CodeIQの問題ページに行くと、解答テンプレートのリンクが載っています。
解答テンプレートはこんな感じになっています。

# coding: utf-8
class KaraokeMachine
  def initialize(melody)
  end
  def transpose(amount)
    "" # これは仮実装なので消してください
  end
end
describe KaraokeMachine do
  it "メロディ無し" do
    melody = ""
    answer = melody
    expect(KaraokeMachine.new(melody).transpose(0)).to eq answer
  end
  # ここから下のコメントを外していって、テストを全部パスさせてください!
  # it "変更無し" do
  #   melody = "C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "
  #   answer = melody
  #   expect(KaraokeMachine.new(melody).transpose(0)).to eq answer
  # end
  #
  # it "2上げる" do
  #   melody = "C D E F |E D C   |E F G A |G F E   |C   C   |C   C   |CCDDEEFF|E D C   "
  #   answer = "D E F# G |F# E D   |F# G A B |A G F#   |D   D   |D   D   |DDEEF#F#GG|F# E D   "
  #   expect(KaraokeMachine.new(melody).transpose(2)).to eq answer
  # end
  ... (省略)

このようにテストコードは僕の方ですでに全部書いてあります。
なので、みなさんは「テストのコメントを外す → rspecが失敗する → プログラムを実装する → rspecがパスする」というように解答していけばOKです。


そうです、まさにこれはTDDのプロセス!!
RSpecやTDDにあまり詳しくない人もこの問題を解けば、自動的にRSpecやTDDの雰囲気を学びとることができるはずです。

(2014.06.27追記) 解答テンプレートを公開しました

挑戦受付が終了して解答テンプレートにアクセスできなくなったので、gistに解答テンプレートを公開しました。

https://gist.github.com/JunichiIto/c548e39fed60bf4bd36a

解答してみたい方はここからテンプレートを取得してください!


問題作成の裏話

この問題は完全に僕のオリジナルです。
「どんな問題を作ろうかな~。自分で問題を作るのは結構難しいな~」と思いながら、自宅に置いてるエレキギターを見てるときにこの問題をふと思いつきました。


f:id:JunichiIto:20140606091457j:plain:w400


ギターを弾く人ならわかると思いますが、ギターの音もフレット(ネックに打ち付けてある金属の細い棒)をまたぐと音が半音上がったり下がったりするんですよね。
なので、弾き始めるポジションを変えたりカポタスト(下の写真を参照)を付けたりすることで、曲のキーを自在に変えることができます。


Kapodaster.JPG
"Kapodaster" by Kiko2000 - Transfered from de.wikipedia. Licensed under CC 表示-継承 3.0 via ウィキメディア・コモンズ.


この「キーを上げ下げする」という音の変化をプログラム上で表現できないかと考えたのが、この問題を思いついたきっかけです。


余談: 愛用のエレキギターはフェンダーUSAのストラトです

僕が愛用しているのはフェンダーUSAのストラトです。
父親の友人から譲り受けたので詳しいことはよくわかりませんが、ラージヘッドモデルなのでたぶん70年代に作られたやつじゃないかな~とか思ったりしています。


f:id:JunichiIto:20140606100341j:plain:w400


・・・ってギターに興味のない人にとっては全くどうでもいい情報ですね。
あー、レスポール欲しい。でかいアンプも買いたい。(まず練習しろ)


まとめ: 僕を「ぎゃふん」と言わせたらあなたの勝ち!

というわけで、今回はCodeIQに出題したプログラミング問題の紹介をしてみました。


CodeIQの問題には赤いバクダンマークの付いている「腕試し問題」とオレンジのバクダンマークの付いている「ウチに来ない?問題」の2種類があります。
「ウチに来ない?問題」は転職希望者向けですが、今回僕が出題したのは純粋にプログラマのみなさんに楽しんでもらうための「腕試し問題」です。


今回の問題は自分でも「これはなかなか面白い問題が作れた」と思っている自信作です。
僕はすでに模範解答を作っています。
自分でいうのも何ですが、僕のコードはめっちゃ短くてキレイです!!
解答期限が過ぎたらこのブログで紹介したいと思います。


自分では「これ以上のコードを書いてくる人間はそういないだろう」と思っていますが、こんな僕を「ぎゃふん」と言わせるような素晴らしいコードを送ってきてください。
みなさんの書いた自慢のコードが届くのを楽しみにしています!!


https://codeiq.jp/ace/ito_junichi/q923
f:id:JunichiIto:20140606103810p:plain:w450


あわせて読みたい

https://codeiq.jp/magazine/2014/06/10604/
今回の問題はソニックガーデンで開催しいている「まかないランチ」の記事と連動しています。
こちらの記事もぜひ読んでみてください!


結婚7周年記念にK.Yairiのアコースティックギターを買いました - give IT a try
アコギはK.ヤイリを使ってます。
めっちゃええ音で鳴ります。ヤイリ最高!
・・・ってプログラミングと全く関係ない。