「第二回 オフラインリアルタイムどう書く」へなちょこ解答(Java)
昨日の夜、「第二回 オフラインリアルタイムどう書く」に参加してきました。
例によって、鍋谷さんが問題を作ってくださいました。今回は、テトリスです!
正確な問題文が知りたい方は、上のページをご覧ください。
雰囲気をざっくり絵にすると、こんな感じです。
ビット演算で解くとカンタンなのだそうですが、次のように腕力で解きました。
- 1が揃ったかどうかは行を見て判定しますが、入力値は列の形です。そこで、まず転置します。
- 次に、1が揃った行の行番号を調べて、保持します。
- そして、その行番号部分を、せっせと除去します。
- 最後に、出力値を作るために、元の形になるように転置します。
最後の部分は、「転置した配列を元に戻したいときは、3回転置すればいい」と教えていただき、その発想はなかったと思ったので、使ってみました :-P
コードはこんな感じです。
import java.util.*; /** * 問題: http://nabetani.sakura.ne.jp/hena/ord2/ */ public class BitTetris { String execute(String input) { String[] split = input.split("-"); String[] cols = getCols(split); String[] rows = _tr(cols); List<Integer> deleteIndexes = getDeleteIndexes(rows); String[] deleted = getDeleted(rows, deleteIndexes); String[] result = new String[deleted.length]; result = _tr(deleted); result = _tr(result); result = _tr(result); String resultStr = getResultStr(result); return resultStr; } String toData(String hexStr) { String binStr = Integer.toBinaryString(Integer.parseInt(hexStr, 16)); Formatter f = new Formatter(); f.format("%04d", Integer.parseInt(binStr)); return f.toString(); } String[] getDeleted(String[] rows, List<Integer> deleteRowList) { String[] clone = new String[rows.length + 1]; for (int i = 0; i < rows.length; i++) { clone[i] = rows[i]; } clone[clone.length - 1] = "00000000"; String[] tmp = new String[rows.length - deleteRowList.size()]; int cnt = 0; for (int i : deleteRowList) { for (int k = i - cnt; k < rows.length; k++) { clone[k] = clone[k + 1]; } cnt++; } for (int i = 0; i < tmp.length; i++) { tmp[i] = clone[i]; } return tmp; } boolean canDelete(String row) { if (row.indexOf("0") == -1) { return true; } return false; } String getResultStr(String[] result) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < result.length; i++) { Formatter f = new Formatter(); f.format("%08d", Integer.parseInt(result[i])); String string = f.toString(); sb.append(Integer.toHexString(Integer.valueOf( string.substring(0, 4), 2))); sb.append(Integer.toHexString(Integer.valueOf( string.substring(4, 8), 2))); sb.append("-"); } sb.deleteCharAt(sb.length() - 1); return new String(sb); } String[] getCols(String[] split) { String[] result = new String[split.length]; for (int i = 0; i < split.length; i++) { String data = ""; for (int k = 0; k < 2; k++) { data += toData(String.valueOf(split[i].charAt(k))); } result[i] = data; } return result; } List<Integer> getDeleteIndexes(String[] rows) { List<Integer> result = new ArrayList<>(); for (int i = 0; i < rows.length; i++) { if (canDelete(rows[i])) { result.add(i); } } return result; } String[] _tr(String[] str) { String[] result = new String[str[0].length()]; for (int i = 0; i < result.length; i++) { for (int k = 0; k < str.length; k++) { if (result[i] == null) { result[i] = String.valueOf(str[k].charAt(i)); } else { String s = result[i]; result[i] = s + String.valueOf(str[k].charAt(i)); } } } return result; } }
(長すぎる)
- 上のコードとテストコード https://gist.github.com/3194544
ちなみに、またしても時間内に終わりませんでした。が、最後に出力値を16進数に戻す手前まで書けたので、メインロジックに到達すらしなかった前回よりは、機嫌良く家に帰ってきました。
しかし、Rubyを使って10行くらいでさくっと書いている方もいて、ぐぬぬって感じです。
ビット演算を使えるようになって、15分くらいで解けるようになりたいです。
あるいは、Groovyを習得して、15行くらいで書けるようになりたいです。
もちろん、その両方でも素敵ですね!! ……精進します。
最後になりましたが、鍋谷さん、一緒に参加された皆さん、ありがとうございました。またよろしくお願いします。