オフラインでリアルタイムに「どう書く」をやるイベント。
http://atnd.org/events/32191
の参考問題
http://qiita.com/items/9c514267214d3917edf2
の実装例。
Javaで。
Fukashigi.java
import java.util.HashSet;
import java.util.Set;
public class Fukashigi {
static final int SIZE=5;
Set<String> deadEnds;
public Fukashigi(String deadEndsText) {
deadEnds = new HashSet<String>();
for (String deadEnd : deadEndsText.split("\\s+")) {
deadEnds.add(deadEnd);
deadEnds.add(new StringBuilder(deadEnd).reverse().toString());
}
}
int count() {
String attended = "a";
return countPath(attended, 1) + countPath(attended, SIZE);
}
private int countPath(String attended, int dir) {
Character next = calcMoved(last(attended), dir);
if (next == null || !canMove(attended, next)) {
return 0;
}
if (next == 'a'+SIZE*SIZE-1) {
return 1;
}
String newAttended = attended + next;
int sum = 0;
for (int nextDir : new int[]{-1, 1, -SIZE, SIZE}) {
sum += countPath(newAttended, nextDir);
}
return sum;
}
private boolean canMove(String attended, Character next) {
return attended.indexOf(next) < 0
&& !deadEnds.contains("" + last(attended) + next);
}
private static Character calcMoved(char last, int dir) {
int ix0 = last - 'a';
int x0 = ix0 % SIZE;
int y0 = ix0 / SIZE;
int ix1 = ix0 + dir;
int x1 = ix1 % SIZE;
int y1 = ix1 / SIZE;
if (0 <= x1 && x1 < SIZE && 0 <= y1 && y1 < SIZE && (x1 == x0 || y1 == y0)) {
return (char) ('a' + ix1);
} else {
return null;
}
}
private static char last(String s) {
return s.charAt(s.length() - 1);
}
}
RunFukashigi.java
import static org.junit.Assert.assertEquals;
public class RunFukashigi {
static void test(String deadEnds, int expected) {
int actual = new Fukashigi(deadEnds).count();
assertEquals(expected, actual);
System.out.printf("\"%s\" -> %d\n", deadEnds, actual);
}
public static void main(String[] args) {
test("", 8512); //そのまま。これが最大値。
// 略
test("fg gl lm mr rs", 171);
}
}
順当な深さ優先探索というつもり。
Java らしく書こうという努力はしているものの、仕事で使ったことがあまりないのでJavaらしくなっているかどうか、甚だ疑問。