「第3回 オフラインリアルタイムどう書く」へなちょこ解答(Java)
昨日の夜、「第3回 オフラインリアルタイムどう書く」に参加してきました。
- オフラインリアルタイムどう書くとは?
- 出されたお題を好きなプログラミング言語で解いて遊ぶ集まりです。制限時間は約1時間で、主催の鍋谷さんがお題を作成してくださいます。
解答言語の内訳は、C++ 1人、Haskell 1人、Java 1人、Perl 1人、Ruby 4人でした。
鍋谷さんが、「そのうち問題が溜まって、もし電子書籍にしたら、欲しい人なんていますかね」と懇親会でおっしゃっていました。ゼッタイに売れると思います!!!と答えたのですが、1人じゃアレなので、欲しい方はこの記事のコメント欄にわっふるわっふると(ry
実際、鍋谷さんの問題は、
- 現実に存在する題材(テトリス、ポーカー、野球など)があるとき、そのルールを知らなくても解けるレベルにまで、問題が厳密に仕様定義されている
- 仕事でプログラムを書いている人が複数人集まって挑戦して、制限時間内に解けたり解けなかったりするくらい、需要に対する難易度調整が絶妙
- うれしいことに日本語で提供されている
と、かくも素晴らしいのです。新しい言語を学ぶときのお題にもピッタリですよね。わっふるわっふる
問題
今回は、Y字路巡りです!
下図の通りの地図がある。
BからAへ向かう道の途中からスタート。
Y字路に到達するたびに、入力文字列の指示に従って右折/左折/後戻り のいずれかを選択する。
通過したY字路名前を順に出力せよ。
詳細は、問題ページをご覧ください。
- Y字路巡り 横へな 2012.9.7 http://nabetani.sakura.ne.jp/hena/ord3ynode/
自分の解答
Javaでかきました。
import static org.junit.Assert.assertEquals; import java.util.HashMap; import java.util.Map; import org.junit.Test; public class TripY { Map<String, String> dic; public TripY() { dic = new HashMap<>(); dic.put("BAr", "C"); dic.put("BAl", "D"); dic.put("ABr", "E"); dic.put("ABl", "C"); dic.put("ACr", "B"); dic.put("ACl", "F"); dic.put("CAr", "D"); dic.put("CAl", "B"); dic.put("ADr", "F"); dic.put("ADl", "E"); dic.put("DAr", "B"); dic.put("DAl", "C"); dic.put("BCr", "F"); dic.put("BCl", "A"); dic.put("CBr", "A"); dic.put("CBl", "E"); dic.put("BEr", "D"); dic.put("BEl", "F"); dic.put("EBr", "C"); dic.put("EBl", "A"); dic.put("DEr", "F"); dic.put("DEl", "B"); dic.put("EDr", "A"); dic.put("EDl", "F"); dic.put("CFr", "E"); dic.put("CFl", "D"); dic.put("FCr", "A"); dic.put("FCl", "B"); dic.put("DFr", "C"); dic.put("DFl", "E"); dic.put("FDr", "E"); dic.put("FDl", "A"); dic.put("EFr", "D"); dic.put("EFl", "C"); dic.put("FEr", "B"); dic.put("FEl", "D"); } protected String execute(String input) { String result = "A"; String current = "BA"; for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); if (c == 'b') { result += current.charAt(0); current = String.valueOf(current.charAt(1)) + String.valueOf(current.charAt(0)); } else if (c == 'r' || c == 'l') { String tmp = current + String.valueOf(c); String to = dic.get(tmp); result += to; current = String.valueOf(current.charAt(1)) + to; } } return result; } public static void main(String[] args) { TripY trip = new TripY(); System.out.println(trip.execute("llllllrllrlbrrr")); // ADEBADEFCBADABED } }
- 上のコードとテストコード https://gist.github.com/3665096
考え方のメモ
Mapで辞書を定義します。
- key: "{from}{to}{指示器}"という文字列
- 次の行程を示すr、l、bを指示器と考える
- value: "{from}{to}"のベクトルにいるときに{指示器}を与えられて選択する次の位置
メインの処理であるexecuteメソッドは、解答文字列resultと、現在のベクトルを表わす文字列currentを持ちます。resultには、位置を表わす文字がどんどん継ぎ足されていきます。currentは、指示器を1つ処理するごとに代入で上書きするため、常に1ベクトル("{from}{to}"の2文字)だけ入っています。
b(後戻り)がきたら、元いた場所が次の位置になるので、resultにcurrentの{from}を足します。そして、向きを逆にするため、currentのベクトルの前と後ろを入れ替えます。
r(右折)かl(左折)がきたら、currentの{from}{to}に{指示器}を継ぎ足して、辞書を引き、次の位置を得ます。得た値をresultに足します。currentを{from}{to}から、{to}{得た値}に更新します。
皆さんの解答
- nidoさんのHaskell http://qiita.com/items/1815701039050f42bbc1
- keqさんのHaskell https://gist.github.com/3665334
- hirataraさんのHaskell https://gist.github.com/3665431/9a872a7a9300361f3edf6feb3c38ed20995fd101
- hirataraさんのPerl https://gist.github.com/3665431/33148716120fbdc6420fb6e5d191eb1fa8db0a93
- 鍋谷さんのC++11 http://qiita.com/items/42f04382c095ab52d018
皆さんの解答を集めておけば、参加しなかった方が読んでも面白いかなと思ったのですが、追いきれませんでした。すいません。
というわけで
楽しかったです! 鍋谷さん、参加された皆さん、ありがとうございました。