パソコン甲子園2
今日は2006年のパソコン甲子園の本選の問題(PDF)の9問目。9でぐるぐるという、なにか作為的なものを感じるけど*1、そうだとしたら記号は#じゃなくて@じゃないと*2。
問題の概略は、
「与えられた大きさのぐるぐるを表示するプログラムをつくれ」
というもの。これ、2の時どうしようか。
## ##
とするか、
## #
とするか。ぐるぐるの条件は、
- 1辺の長さがnの場合、n行n列の文字列として表示する。
- 左下隅を基点とし,時計回りに回転する渦状の模様とする。
- 線のある部分は#(半角シャープ)、空白部分は“ ”(半角空白)で表現する。
- 線と線の間は空白を置く。
- nは1以上100以下の整数とする。
となっていて、4番目の「線と線の間は空白を置く」という条件から、下のほうが正しそう。
ってことで、作ってみた。超適当。
import java.io.*; public class Q09 { public static final class Yuyu { private static final class Point { public final int i; public final int j; public Point(int i, int j) { this.i = i; this.j = j; } } public static enum Direction { TOP { Point getStartPos(int size) { return new Point(size - 1, 0); } Direction next() { return RIGHT; } void move(Yuyu yuyu) { yuyu.top(); } Point getNextNext(int i, int j) { return new Point(i-2, j); } }, RIGHT { Point getStartPos(int size) { return new Point(0, 0); } Direction next() { return BOTTOM; } void move(Yuyu yuyu) { yuyu.right(); } Point getNextNext(int i, int j) { return new Point(i, j+2); } }, BOTTOM { Point getStartPos(int size) { return new Point(0, size - 1); } Direction next() { return LEFT; } void move(Yuyu yuyu) { yuyu.bottom(); } Point getNextNext(int i, int j) { return new Point(i+2, j); } }, LEFT { Point getStartPos(int size) { return new Point(size - 1, size - 1); } Direction next() { return TOP; } void move(Yuyu yuyu) { yuyu.left(); } Point getNextNext(int i, int j) { return new Point(i, j-2); } }; abstract Point getStartPos(int size); abstract Direction next(); abstract void move(Yuyu yuyu); abstract Point getNextNext(int i, int j); } private final char ch; private final int size; private int crntI; private int crntJ; private char[][] field; private Direction dir; public Yuyu(char ch, int size, Direction dir) { this.ch = ch; this.size = size; this.dir = dir; initField(); } private void initField() { field = new char[size][size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { field[i][j] = ' '; } } Point startPos = dir.getStartPos(size); crntI = startPos.i; crntJ = startPos.j; } private char getNextNext() { Point crnt = dir.getNextNext(crntI, crntJ); int i = crnt.i, j = crnt.j; // フィールドの外は空白として考える if (i == -1 || j == -1 || i == size || j == size) return ' '; // フィールドの外の外はchとして考える if (i == -2 || j == -2 || i == size+1 || j == size+1) return ch; return field[crnt.i][crnt.j]; } public String createYuyu() { boolean isFinish = false; while (true) { field[crntI][crntJ] = ch; if (getNextNext() == ' ') { dir.move(this); isFinish = false; } else { dir = dir.next(); // 方向がすぐに変わってしまうか、行き場所がなければ終了 if (isFinish || getNextNext() == ch) break; dir.move(this); isFinish = true; } } StringBuilder result = new StringBuilder(size * size + size); for (char[] line : field) result.append(line).append('\n'); result.deleteCharAt(result.length() - 1); return result.toString(); } private void top() { crntI--; } private void right() { crntJ++; } private void bottom() { crntI++; } private void left() { crntJ--; } } public static String createYuyu(int size) { // return new Yuyu('#', size, Yuyu.Direction.TOP).createYuyu(); return new Yuyu('@', size, Yuyu.Direction.LEFT).createYuyu(); } public static void main(String[] args) throws IOException { BufferedReader in = null; try { in = new BufferedReader( new InputStreamReader(System.in)); int size = Integer.parseInt(in.readLine()); System.out.println(createYuyu(size)); } finally { if (in != null) in.close(); } } }
つか、本当の大会ならこんな悠長なプログラム書いてられないよなぁ。是非どんなコードを書いているのか見てみたい。
あと問題自体には関係ないけど、private staticなclassのメソッドにpublicとか書いてしまうのはもはや癖。