Language detail: Java
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- 年賀はがきの当せん番号 (Nested Flatten)
- 箱詰めパズルの判定 (Nested Flatten)
- 関数やメソッドのソースの平均行数 (Nested Flatten)
- コレクションの実装 (Nested Flatten)
- 復活 (Nested Flatten)
codes
長くなってしまいましたが、原子毎の連立方程式で整数解を求めました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Term {
private static final Pattern pattern = Pattern.compile("([A-Z][a-z]?)([0-9]+)?");
public static Term create(String str, boolean isLhs) {
Term result = new Term();
Matcher m = pattern.matcher(str);
while (m.find()) {
int count = (m.group(2) != null)? Integer.parseInt(m.group(2)): 1;
result.molecules.add(new Molecule(m.group(1), count));
}
result.isLhs = isLhs;
return result;
}
public final List<Molecule> molecules = new ArrayList<Molecule>();
public boolean isLhs = true;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (Molecule m: molecules) {
builder.append(m.toString());
}
return builder.toString();
}
}
class Molecule {
public final String element;
public final int count;
public Molecule(String e, int c) {
element = e;
count = c;
}
@Override
public String toString() {
return element + toString(count);
}
private String toString(int i) {
return (i > 1)? String.valueOf(i): "";
}
}
public class Sample284 {
public static int gcd(int m, int n) {
if (m < 0 || n < 0) return gcd(Math.abs(m), Math.abs(n));
if (n > m) return gcd(n, m);
int r = m % n;
return (r == 0)? n: gcd(n, r);
}
final List<Term> terms_ = new ArrayList<Term>();
public Sample284(String[] lhs, String[] rhs) {
for (String s: lhs) {
terms_.add(Term.create(s, true));
}
for (String s: rhs) {
terms_.add(Term.create(s, false));
}
}
public String solve() {
int[][] matrix = createMatrix(terms_);
//System.out.println(createString(matrix));
int[] result = solveEquation(matrix);
//System.out.println(createString(matrix));
//System.out.println(Arrays.toString(result));
return createResultString(terms_, result);
}
private int[] solveEquation(int[][] matrix) {
for (int col = 0; col < matrix[0].length - 1; col++) {
int row = searchNotZero(matrix, col, col);
if (row != col) {
swapRows(matrix, row, col);
row = col;
}
for (int r = 0; r < matrix.length; r++) {
if (r == row) continue;
eraceRow(matrix, col, row, r);
}
}
return reduceResult(matrix);
}
int searchNotZero(int[][] matrix, int col, int startRow) {
for (int row = startRow; row < matrix.length; row++) {
if (matrix[row][col] != 0)
return row;
}
throw new IllegalArgumentException(createString(matrix));
}
void swapRows(int[][] matrix, int row1, int row2) {
int[] work = matrix[row1];
matrix[row1] = matrix[row2];
matrix[row2] = work;
}
void eraceRow(int[][] matrix, int baseCol, int baseRow, int row) {
int baseVal = matrix[baseRow][baseCol];
if (baseVal == 0) throw new IllegalArgumentException(createString(matrix));
int eraceVal = matrix[row][baseCol];
if (eraceVal == 0) return;
int m = gcd(baseVal, eraceVal);
for (int col = 0; col < matrix[row].length; col++) {
matrix[row][col] = matrix[row][col] * (baseVal / m) - matrix[baseRow][col] * (eraceVal / m);
}
}
private int[] reduceResult(int[][] matrix) {
int scale = 1;
int col = matrix[0].length - 1;
for (int row = 0; row < matrix.length; row++) {
int m = gcd(matrix[row][row], matrix[row][col]);
scale *= matrix[row][row] / m;
}
int[] result = new int[matrix.length];
for (int row = 0; row < matrix.length; row++) {
result[row] = matrix[row][col] * scale / matrix[row][row];
}
return result;
}
private int[][] createMatrix(List<Term> terms) {
Map<String, Integer> keyMap = createKeyMap(terms);
int rows = keyMap.size() + 1;
int length = terms.size() + 1;
if (rows + 1 != length) {
throw new IllegalArgumentException();
}
int[][] result = new int[rows][];
for (int index = 0; index < result.length; index++) {
result[index] = new int[length];
}
int col = 0;
for (Term term: terms) {
for (Molecule m: term.molecules) {
result[keyMap.get(m.element)][col] = m.count * (term.isLhs? 1: -1);
}
col++;
}
result[keyMap.size()][0] = 1;
result[keyMap.size()][length - 1] = 1;
return result;
}
private Map<String, Integer> createKeyMap(List<Term> list) {
Map<String, Integer> result = new HashMap<String, Integer>();
int index = 0;
for (Term term: list) {
for (Molecule m: term.molecules) {
if (!result.containsKey(m.element)) {
result.put(m.element, index++);
}
}
}
return result;
}
public String createString(int[][] matrix) { // for debug
StringBuilder builder = new StringBuilder();
for (int[] row: matrix) {
for (int col: row) {
builder.append(String.format("%3d ", col));
}
builder.append("\n");
}
return builder.toString();
}
private String createResultString(List<Term> list, int[] factors) {
StringBuilder builder = new StringBuilder();
int index = 0;
boolean isLhs = true;
for (Term term: list) {
if (builder.length() > 0) {
if (isLhs && !term.isLhs) {
builder.append("=");
isLhs = false;
} else {
builder.append("+");
}
}
if (factors[index] > 1) builder.append(factors[index]);
builder.append(term.toString());
index++;
}
return builder.toString();
}
public static void main(String[] args) {
Sample284 solver = new Sample284(new String[] {"Mg", "O2"}, new String[] {"MgO"});
System.out.println(solver.solve()); // 2Mg+O2=2MgO
Sample284 solver2 = new Sample284(new String[] {"C2H2", "O2"}, new String[] {"CO2", "H2O"});
System.out.println(solver2.solve()); // 2C2H2+5O2=4CO2+2H2O
Sample284 solver3 = new Sample284(new String[] {"C2H6O", "O2"}, new String[] {"CO2", "H2O"});
System.out.println(solver3.solve()); // 2C2+2H2+5O2=4CO2+2H2O
}
}
|
実行結果を貼り付けてなかったので、いまさらですが追記。 8 床屋 寝る 1 来店 1 8 床屋、目覚める 8 散髪開始 1 1 来店 2 8 散髪完了 1 8 散髪開始 2 1 来店 3 1 来店 4 1 来店 5 1 満席で立ち去る 5 1 来店 6 1 満席で立ち去る 6 1 来店 7 1 満席で立ち去る 7 8 散髪完了 2 8 散髪開始 3 1 来店 8 8 散髪完了 3 8 散髪開始 4 8 散髪完了 4 8 散髪開始 8 8 散髪完了 8 8 床屋 寝る 1 来店 9 8 床屋、目覚める 8 散髪開始 9 1 来店 10 1 来店 11 8 散髪完了 9 8 散髪開始 10 1 来店 12 1 来店 13 1 満席で立ち去る 13 1 来店 14 1 満席で立ち去る 14 8 散髪完了 10 8 散髪開始 11 1 来店 15 1 来店 16 1 満席で立ち去る 16 8 散髪完了 11 8 散髪開始 12 8 散髪完了 12 8 散髪開始 15 8 散髪完了 15 8 床屋 寝る 16人のうち 10人を散髪
せっかくの同期の問題だったので、java.util.concurrent パッケージのセマフォとBlockingQueueを使って実装してみました。
しかし、これBlockingQueueだけでも実装できるかな?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
public class Sample285 {
private static final int SEAT_COUNT = 3;
private final Semaphore semaphore_ = new Semaphore(SEAT_COUNT, true);
private final BlockingQueue<Runnable> seat_ = new LinkedBlockingQueue<Runnable>();
private int counter_ = 0;
public Sample285() {
new Thread(new Runnable() {
public void run() {
try {
while (true) {
synchronized (seat_) {
if (seat_.isEmpty()) {
printMessage("床屋 寝る");
while (seat_.isEmpty()) {
seat_.wait();
}
printMessage("床屋、目覚める");
}
}
Runnable runnable = seat_.poll();
if (runnable != null) {
runnable.run();
counter_++;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Sleeping barber").start();
}
public int getCounter() {
return counter_;
}
public void join() throws InterruptedException {
semaphore_.acquire(SEAT_COUNT);
Thread.yield();
semaphore_.release(SEAT_COUNT);
}
public void addGuest(final int id) {
printMessage("来店 " + id);
if (!semaphore_.tryAcquire()) {
printMessage("満席で立ち去る " + id);
return;
}
seat_.offer(new Runnable() {
public void run() {
printMessage("散髪開始 " + id);
try {
Thread.sleep((long) (Math.random() * 300 + 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
printMessage("散髪完了 " + id);
semaphore_.release();
}
});
synchronized (seat_) {
seat_.notifyAll();
}
}
private static void printMessage(String message) {
System.out.format("%d %s%n", Thread.currentThread().getId(), message);
}
public static void main(String[] args) throws Exception {
Sample285 barber = new Sample285();
for (int index = 1; index <= 16; index++) {
Thread.sleep((index == 9)? 1200: (long) (Math.random() * 200));
barber.addGuest(index);
}
barber.join();
System.out.format("%d人のうち %d人を散髪%n", 16, barber.getCounter());
}
}
|
コメントとかは適当です、ごめんなさい。
もっとこうした方がいいよってところがあったら教えて頂けると嬉しいです。
(指摘する箇所多すぎかもしれませんが・・・)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | import java.util.Scanner;
public class Client {
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("Twitter ID : ");
String username = stdIn.nextLine();
System.out.print("Twitter PASSWORD : ");
String password = stdIn.nextLine();
System.out.print("POST Message : ");
String message = stdIn.nextLine();
Updater up = new Updater(username, password);
up.post(message);
}
}
-----------------------------------------------------------------------------
import java.io.OutputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.net.HttpURLConnection;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class Updater {
private final String updateURL = "http://twitter.com/statuses/update.xml";
/**
* コンストラクタでユーザ名とパスワードを受け取り、その認証を登録する。
* @param username ユーザ名
* @param password パスワード
*/
public Updater(String username, String password) {
HttpAuthenticator auth = new HttpAuthenticator(username, password);
Authenticator.setDefault(auth);
}
/**
* 引数で受け取った文字列をPOSTする。
* @param message POSTするメッセージ
*/
public void post(String message) {
try {
//UpdateURLへのHttpURLConnectionを生成し、POSTメソッドの為の設定をする。
HttpURLConnection con = (HttpURLConnection)(new URL(updateURL).openConnection());
con.setRequestMethod("POST");
con.setDoOutput(true);
//通信リンクを確立する。
con.connect();
//出力ストリームを取得し、メッセージをURLエンコードして書き込み。
OutputStream os = con.getOutputStream();
os.write(("status=" + URLEncoder.encode(message, "UTF-8")).getBytes());
os.flush();
os.close();
//通信が正常に行なわれたかどうかのチェック。
if (con.getResponseCode() != HttpURLConnection.HTTP_OK)
System.out.println("ERROR! HTTP Response Status : " + con.getResponseCode());
//通信リンクを破棄。
con.disconnect();
} catch (Exception e) {
//例外は握りつぶしてます。ごめんなさい。
e.printStackTrace();
}
}
/**
* BASIC認証用クラス
*/
class HttpAuthenticator extends Authenticator {
private PasswordAuthentication passAuth;
public HttpAuthenticator(String username, String password) {
passAuth = new PasswordAuthentication(username, password.toCharArray());
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return passAuth;
}
}
}
|
で、こちらは擬似乱数のシードを固定し、RandomPrint を数回実行し、常に同じ結果が出力されることを確認するテストケースです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import static jp.co.dgic.testing.common.virtualmock.MockObjectManager.*;
import static org.junit.Assert.*;
import java.util.*;
import jp.co.dgic.testing.common.virtualmock.*;
import org.junit.*;
public class RandomPrintTest implements IReturnValueProvider {
private int seed;
@Before
public void setUp() {
seed = new Random().nextInt();
}
@Test
public void testMain() {
// 擬似乱数のシードを固定する
setReturnValueAtAllTimes("java.util.Random", "<init>", this);
// 数回実行する
final int count = 10;
for (int i = 0; i < count; i++) {
RandomPrint.main(null);
}
// 常に同じ結果が出力されることを確認する
String arg1 = (String) getArgument("PrintStream", "println", 0, 0);
assertNotNull(arg1);
for (int i = 1; i < count; i++) {
String arg2 = (String) getArgument("PrintStream", "println", i, 0);
assertEquals(arg1, arg2);
}
}
@Override
public Object createReturnValue(Object[] arg0) {
return new Random(seed);
}
}
|
ちょっと遊んでみました。こちらのコードは擬似乱数を10個出力します。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import java.util.Random;
public class RandomPrint {
public static void main(String[] args) {
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append(random.nextInt());
sb.append(" ");
}
System.out.println(sb.toString());
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import java.util.Arrays;
import java.util.Random;
public class RandomWithSeed {
public static void main(String[] args) {
final long seed = 1234567890L;
final int count = 10;
System.out.println(Arrays.toString(getRandomValuesWithSeed(seed, count)));
System.out.println(Arrays.toString(getRandomValuesWithSeed(seed, count)));
System.out.println(Arrays.toString(getRandomValuesWithSeed(seed, count)));
}
private static int[] getRandomValuesWithSeed(
final long seed, final int count) {
Random random = new Random(seed);
int[] randomValues = new int[count];
for (int i = 0; i < randomValues.length; i++) {
randomValues[i] = random.nextInt();
}
return randomValues;
}
}
|
見つけた最長のしりとりは624語 (ホロバシャ, ヤスヤド, ドクダミ, … 略 … , ツノブエ, エスプリ, リンカン) でした。
しりとりは、文字と文字をつなぐ有向グラフと考えられるので、グラフ理論を応用すればもっと良い解法が得られるのではないかと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | import java.io.InputStreamReader;
import java.util.*;
public class Shiritori3 {
public static void main(String[] args) throws Exception {
long startTime = System.nanoTime();
final Scanner scanner = new Scanner(new InputStreamReader(
Shiritori.class.getResourceAsStream("Words_jp.txt"), "UTF-8"));
new Shiritori3(scanner).analyze();
System.out.printf("%f [sec]%n", ((double)System.nanoTime() - startTime) / 100000000);
}
Map<Character, Node> nodes;
public Shiritori3(Scanner scanner) {
nodes = new HashMap<Character, Node>();
init(scanner);
}
private void init(Scanner scanner) {
while (scanner.hasNext()) {
String edge = scanner.next();
char head = headChar(edge);
char tail = tailChar(edge);
if (!nodes.containsKey(head)) nodes.put(head, new Node(head));
if (!nodes.containsKey(tail)) nodes.put(tail, new Node(tail));
nodes.get(head).addGoOutEdge(edge);
nodes.get(tail).addCominEdge(edge);
}
scanner.close();
}
public void analyze() {
Set<Node> noflows = new HashSet<Node>();
Set<Node> flows = new HashSet<Node>();
for (Node node : nodes.values())
if (node.hasCapacity()) flows.add(node);
List<LinkedList<String>> pathList = new ArrayList<LinkedList<String>>();
while (!flows.isEmpty()) {
// 初期ノードの選択により、結果が変化する
Node head = flows.toArray(new Node[0])[new java.util.Random().nextInt(flows.size())];
Node tail = head;
LinkedList<String> path = new LinkedList<String>();
pathList.add(path);
while (head.hasCapacity() || tail.hasCapacity()) {
if (!head.inEdges.isEmpty()) {
String newHead = popInEdge(head);
path.addFirst(newHead);
if (!head.hasCapacity()) flows.remove(head);
head = nodes.get(headChar(newHead));
}
if (!tail.outEdges.isEmpty()) {
String newTail = popOutEdge(tail);
path.addLast(newTail);
if (!tail.hasCapacity()) flows.remove(tail);
tail = nodes.get(tailChar(newTail));
}
}
}
for (int i = 0, n = pathList.size(); i < n; i++) {
LinkedList<String> pathA = pathList.get(i);
if (pathA.size() <= 2) break;
for (int j = i + 1; j < n; j++) {
LinkedList<String> pathB = pathList.get(j);
if (pathB.size() <= 2) break;
cross(pathA, pathB);
}
}
Collections.sort(pathList, new Comparator<List<?>>() {
public int compare(List<?> o1, List<?> o2) {
return o1.size() - o2.size(); }});
for (LinkedList<String> path : pathList) {
System.out.printf("%d, %s%n", path.size(), path);
}
}
void cross(LinkedList<String> pathA, LinkedList<String> pathB) {
int ma = -1, mb = -1;
int ac = pathA.size(), bc = pathB.size();
int max = Math.max(ac, bc);
int a = 0;
for (String aw : pathA) {
int b = 0;
for (String bw : pathB) {
if (tailChar(aw) == headChar(bw)) {
int nmax = Math.max(a + (bc - b) + 1, (ac - a) + b - 1);
if (max < nmax) {
ma = a;
mb = b;
max = nmax;
}
}
b++;
}
a++;
}
if (ma != -1) {
LinkedList<String> old1 = new LinkedList<String>(pathA);
LinkedList<String> old2 = new LinkedList<String>(pathB);
pathA.clear();
pathB.clear();
pathA.addAll(old1.subList(0, ma + 1));
pathA.addAll(old2.subList(mb, bc));
pathB.addAll(old2.subList(0, mb));
pathB.addAll(old1.subList(ma + 1, ac));
cross(pathA, pathB);
}
}
String popInEdge(Node node) {
int max = -1;
String next = null;
for (String s : node.inEdges) {
Node nextHead = nodes.get(headChar(s));
if (max < nextHead.flowCapacity()) {
max = nextHead.flowCapacity();
next = s;
}
}
node.inEdges.remove(next);
return next;
}
String popOutEdge(Node node) {
int max = -1;
String next = null;
for (String s : node.outEdges) {
Node nextTail = nodes.get(tailChar(s));
if (max < nextTail.flowCapacity()) {
max = nextTail.flowCapacity();
next = s;
}
}
node.outEdges.remove(next);
return next;
}
static char tailChar(String edge) {
return toShiritoriChar(edge.charAt(edge.length() - 1));
}
static char headChar(String edge) {
return toShiritoriChar(edge.charAt(0));
}
static final String YOUON = "ァィゥェォヵヶッャュョヮ";
static final String SEION = "アイウエオカケツヤユヨワ";
static char toShiritoriChar(final char c) {
if (YOUON.indexOf(c) == -1)
return c;
else
return SEION.charAt(YOUON.indexOf(c));
}
static class Node {
final LinkedList<String> inEdges = new LinkedList<String>();
final LinkedList<String> outEdges = new LinkedList<String>();
final Character c;
int lilmit;
public Node(Character c) {
this.c = c;
}
void addCominEdge(String e) {
inEdges.add(e);
}
void addGoOutEdge(String e) {
outEdges.add(e);
}
int flowCapacity() {
return Math.min(inEdges.size(), outEdges.size());
}
boolean hasCapacity() {
return flowCapacity() > 0;
}
}
}
|
お題から少しずれますが、元ネタがウィジェットだそうなので、Java Swing です。 フォントによってしまいますが、見た目が面白いものとして"i/!"にしました。 "Q/O"でも分かりにくくて良いですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class SeventeenBarsClock extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
SeventeenBarsClock clock = new SeventeenBarsClock();
clock.pack();
clock.setLocationRelativeTo(null);
clock.setVisible(true);
clock.start();
}
});
}
private BynaryLabel hourLabel, minuteLabel, secondLabel;
private javax.swing.Timer timer;
SeventeenBarsClock() {
super("17BarsClock");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
hourLabel = new BynaryLabel(5);
minuteLabel = new BynaryLabel(6);
secondLabel = new BynaryLabel(6);
setLayout(new FlowLayout());
add(hourLabel);
add(minuteLabel);
add(secondLabel);
timer = new javax.swing.Timer(0, this);
timer.setDelay(1000);
}
public void start() { timer.start(); }
public void stop() { timer.stop(); }
@Override
public void actionPerformed(ActionEvent e) {
Calendar cal = new GregorianCalendar();
hourLabel.setValue(cal.get(Calendar.HOUR_OF_DAY));
minuteLabel.setValue(cal.get(Calendar.MINUTE));
secondLabel.setValue(cal.get(Calendar.SECOND));
}
private static class BynaryLabel extends JLabel {
private static final long serialVersionUID = 1L;
BynaryLabel(int length) {
this.length = length;
setValue(0);
}
private int length;
void setValue(int value) {
StringBuilder sb = new StringBuilder(length);
for(int m=1<<(length-1); m>0; m>>=1) sb.append((value & m) != 0 ? "i" : "!");
setText(sb.toString());
}
}
}
|
促音・拗音は、前の単語と合わせてキーとするようにしたり、ひらがな→カタカナに変換して同一視したりしてみました。
ただ、全単語を単純に探索しているので計算量が爆発してました。160単語程度なら、すぐに結果が返ってくる程度です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | import java.io.*;
import java.util.*;
public class Sample277 {
static class Word {
/// キーは全てカタカナに正規化
public static String convertHiraganaToKatakana(String s) {
StringBuilder builder = new StringBuilder(s);
for (int index = 0; index < builder.length(); index++) {
char c = builder.charAt(index);
if ('ぁ' <= c && c <= 'ん') {
builder.setCharAt(index, (char)(c - 'ぁ' + 'ァ'));
}
}
return builder.toString();
}
/// 拗音・促音・濁点などのリスト
private static final Set<Character> anomalyLetters_ = new HashSet<Character>();
{
anomalyLetters_.add('ぁ');
anomalyLetters_.add('ぃ');
anomalyLetters_.add('ぅ');
anomalyLetters_.add('ぇ');
anomalyLetters_.add('ぉ');
anomalyLetters_.add('っ');
anomalyLetters_.add('ゃ');
anomalyLetters_.add('ゅ');
anomalyLetters_.add('ょ');
anomalyLetters_.add('ァ');
anomalyLetters_.add('ィ');
anomalyLetters_.add('ゥ');
anomalyLetters_.add('ェ');
anomalyLetters_.add('ォ');
anomalyLetters_.add('ッ');
anomalyLetters_.add('ャ');
anomalyLetters_.add('ュ');
anomalyLetters_.add('ョ');
anomalyLetters_.add('゛');
anomalyLetters_.add('゜');
}
public final String s;
public final String first;
public final String last;
private boolean used_ = false;
public Word(String s) {
this.s = s;
first = convertHiraganaToKatakana(getFirstLetter(s));
last = convertHiraganaToKatakana(getLastLetter(s));
}
// しりとりのキーとしての最初の音
private String getFirstLetter(String s) {
if (anomalyLetters_.contains(s.charAt(1))) {
return s.substring(0, 2);
}
return s.substring(0, 1);
}
// しりとりのキーとしての最後の音
private String getLastLetter(String s) {
int lastStartIndex = s.length() - 1;
int lastEndIndex = s.length();
char c = s.charAt(lastStartIndex);
if (c == 'ー' || c == 'ー') {
lastStartIndex--;
lastEndIndex--;
c = s.charAt(lastStartIndex);
}
if (anomalyLetters_.contains(c)) {
lastStartIndex--;
}
return s.substring(lastStartIndex, lastEndIndex);
}
public boolean isUsed() {
return used_;
}
public void setUsed(boolean used) {
used_ = used;
}
@Override
public boolean equals(Object obj) {
if (!this.getClass().equals(obj.getClass())) {
return false;
}
Word other = (Word) obj;
return this.s.equals(other.s);
}
@Override
public int hashCode() {
return s.hashCode();
}
}
private final Map<String, Set<Word>> wordMap_ = new HashMap<String, Set<Word>>();
public Sample277() {
}
public void addWord(String s) {
Word word = new Word(s);
Set<Word> set = wordMap_.get(word.first);
if (set == null) {
set = new HashSet<Word>();
wordMap_.put(word.first, set);
}
set.add(word);
}
public List<String> getLongest(String start) {
Word w = new Word(start);
return getLongestR(w);
}
public List<String> getLongestR(Word w) {
List<String> result = new LinkedList<String>();
w.used_ = true;
Set<Word> set = wordMap_.get(w.last);
Set<String> firstLetter = new HashSet<String>();
if (set != null) {
for (Word word: set) {
if (word.isUsed()) {
continue;
}
if (firstLetter.contains(word.last)) {
continue;
}
firstLetter.add(word.last);
List<String> list = getLongestR(word);
if (result.size() < list.size()) {
result = list;
}
}
}
w.used_ = false;
result.add(0, w.s);
return result;
}
public static List<String> loadFile(String path) throws FileNotFoundException {
List<String> result = new ArrayList<String>();
Scanner scanner = new Scanner(new File(path), "MS932");
while (scanner.hasNext()) {
result.add(scanner.next());
}
scanner.close();
return result;
}
public static void main(String[] args) throws IOException {
List<String> strings = loadFile("fam55_10.txt");
System.out.println("input count: " + strings.size());
Sample277 sample = new Sample277();
for (String s: strings) {
sample.addWord(s);
}
long start = System.currentTimeMillis();
List<String> result = sample.getLongest("しりとり");
long elapse = System.currentTimeMillis() - start;
System.out.println("elapse: " + elapse + "(ms)");
System.out.println("max length: " + result.size());
for (String s: result) {
System.out.println(s);
}
}
}
|
Javaで単純に。 単純すぎるため、短時間で結果を出せるのは100単語ぐらいまでのようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | import java.io.*;
import java.util.*;
/**
* いちばん長いしりとり
*/
public class TheLongestSiritori {
// 単語
private static class Word {
String text; // 単語の文字列
boolean used; // 使用中フラグ
}
// 頭文字をキーとする単語の索引。
private static Map<String, List<Word>> index = new HashMap<String, List<Word>>();
/**
* メインルーチン
* @param args 最初の引数は単語ファイルの名前
*/
public static void main( String[] args ) {
////////////////////////////////////////////////////////////
// 引数から単語ファイルの名前を取得する。
////////////////////////////////////////////////////////////
// 引数に単語ファイルの名前が指定されていることを確認する。
if ( args.length < 1 ) {
// 指定されていない
System.err.println( "引数に単語ファイルの名前を指定してください。" );
return;
}
// 引数からファイル名を取得する。
String fileName = args[0];
////////////////////////////////////////////////////////////
// 単語ファイルを読み込み、単語の一覧を作成する。
////////////////////////////////////////////////////////////
List<Word> wordList = new ArrayList<Word>();
BufferedReader reader = null;
try {
// 単語ファイルを開く。
reader = new BufferedReader( new FileReader( fileName ) );
// 単語ファイルの行ごとに以下を繰り返す。
String line;
while ( ( line = reader.readLine() ) != null ) {
// 行が空でないことを確認する。
if ( line.length() > 0 ) {
// 行の内容を単語の一覧に追加する。
Word word = new Word();
word.text = line;
word.used = false;
wordList.add( word );
}
}
} catch ( IOException e ) {
// 入力エラー:
System.err.println( "単語ファイルを正常に読み込めませんでした。ファイル名前=[" + fileName + "]" );
return;
} finally {
if ( reader != null ) {
try {
// 単語ファイルを閉じる。
reader.close();
} catch ( IOException e ) {
/* 無視 */
}
}
}
////////////////////////////////////////////////////////////
// 頭文字をキーとした単語の索引を作成する。
////////////////////////////////////////////////////////////
index = new HashMap<String, List<Word>>();
// 単語の一覧中のすべての単語について、以下を繰り返す。
for ( int i = 0; i < wordList.size(); ++i ) {
Word word = wordList.get( i );
// 単語の頭文字を取得する。
String first = word.text.substring( 0, 1 );
List<Word> container;
// 同一の頭文字の単語が、索引に格納済みであることを確認する。
if ( ! index.containsKey( first ) ) {
// 同一の頭文字の単語が、まだ格納されていない:
// 頭文字に対応する単語格納リストを作成する。
container = new ArrayList<Word>();
index.put( first, container );
} else {
// 頭文字に対応する単語格納リストを作成する。
container = index.get( first );
}
// 単語格納リストに単語を追加する。
container.add( word );
}
////////////////////////////////////////////////////////////
// しりとりをする。
////////////////////////////////////////////////////////////
// 最初の単語をランダムに決める。
int rnd = new Random().nextInt( wordList.size() );
Word start = wordList.get( rnd );
// 最長のしりとり結果(逆順)を取得する。
List<String> longest = getLongest( start );
// しりとり結果を反転する。
Collections.reverse( longest );
////////////////////////////////////////////////////////////
// 結果を表示する。
////////////////////////////////////////////////////////////
for ( int i = 0; i < longest.size(); ++i ) {
System.out.println( ( i + 1 ) + ": " + longest.get( i ) );
}
}
/*
* 最長のしりとり結果(逆順)を取得する。
* @param 単語
* @return 最長のしりとり結果(逆順)
*/
public static List<String> getLongest( Word word ) {
// 単語使用中フラグをオンにする。
word.used = true;
// 単語の末尾の文字を取得する。
String text = word.text;
int length = text.length();
String last = text.substring( length - 1, length );
List<String> longest = new ArrayList<String>();
// 索引に末尾の文字が含まれていることを確認する。
if ( index.containsKey( last ) ) {
////////////////////////////////////////////////////////////
// 末尾の文字の後に続く、最長のしりとり結果を見つける。
////////////////////////////////////////////////////////////
// 末尾の文字から始まるすべての単語について、以下を繰り返す。
List<Word> container = index.get( last );
for ( int i = 0; i < container.size(); ++i ) {
Word nextWord = container.get( i );
// 単語使用中フラグがオフであることを確認する。
if ( ! nextWord.used ) {
// しりとり結果を取得する。
List<String> temp = getLongest( nextWord );
// 最長のしりとり結果を見つける。
if ( temp.size() > longest.size() ) {
longest = temp;
}
}
}
}
// 単語をしりとり結果に追加する。
longest.add( text );
// 単語使用中フラグをオフにする。
word.used = false;
return longest;
}
}
|
Javaでシンプルに。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | public class SubnetMask {
public static void main( String[] args ) {
System.out.println( getMaskLength( "255.255.255.0" ) );
System.out.println( getMaskLength( "255.255.255.128" ) );
System.out.println( getMaskLength( "255.255.255.255" ) );
System.out.println( getMask( 24 ) );
System.out.println( getMask( 25 ) );
System.out.println( getMask( 32 ) );
}
// サブネットマスクの長さを求める。
public static int getMaskLength( String subnetMask ) {
/////////////////////////////////////////////////////////////
// サブネットマスクの妥当性確認
/////////////////////////////////////////////////////////////
// サブネットマスクが「数値.数値.数値.数値」の形式であることを確認する。
if ( ! subnetMask.matches( "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+" ) ) {
throw new RuntimeException( "指定されたサブネットマスクが不正です。" );
}
// サブネットマスクの数値が以下の順に並んでいることを確認する。
// 1. 255が0個以上
// 2. 254と252と248と240と224と192と128のいずれかが0個か1個
// 3. 0が0個以上」
String temp = subnetMask + ".";
if ( ! temp.matches( "(255\\.)*((254|252|248|240|224|192|128)\\.)?(0\\.)*" ) ) {
throw new RuntimeException( "指定されたサブネットマスクが不正です。" );
}
/////////////////////////////////////////////////////////////
// サブネットマスクを長さに変換
/////////////////////////////////////////////////////////////
// サブネットマスクを4つの数値に分割する。
String[] partsStr = subnetMask.split( "\\." );
int[] parts = new int[4];
for ( int i = 0; i < 4; ++i ) {
parts[i] = Integer.parseInt( partsStr[i] );
}
// 各数値のビット数を求め、ビット数を合計して長さを求める。
int result = 0;
for ( int i = 0; i < 4; ++i ) {
switch ( parts[i] ) {
case 255:
result += 8;
break;
case 254:
result += 7;
break;
case 252:
result += 6;
break;
case 248:
result += 5;
break;
case 240:
result += 4;
break;
case 224:
result += 3;
break;
case 192:
result += 2;
break;
case 128:
result += 1;
break;
case 0:
result += 0;
break;
}
}
return result;
}
// 長さからサブネットマスクを求める。
public static String getMask( final int length ) {
/////////////////////////////////////////////////////////////
// 長さの妥当性確認
/////////////////////////////////////////////////////////////
if ( length < 0 || 32 < length ) {
throw new RuntimeException( "指定された長さが不正です。" );
}
/////////////////////////////////////////////////////////////
// 長さをサブネットマスクに変換
/////////////////////////////////////////////////////////////
// サブネットマスクの4つ数値
int[] parts = new int[] { 0, 0, 0, 0 };
// 4つ数値のうち、先頭から「長さを8で割った商」個の数値を255にする。
int q = length / 8;
for ( int i = 0; i < q; ++i ) {
parts[i] = 255;
}
// 「長さを8で割った余り」がある場合、
// 4つの数値のうち、先頭から「長さを8で割った商 + 1」番目の数値を、「余り」から求める。
int r = length % 8;
switch ( r ) {
case 7:
parts[q] = 254;
break;
case 6:
parts[q] = 252;
break;
case 5:
parts[q] = 248;
break;
case 4:
parts[q] = 240;
break;
case 3:
parts[q] = 224;
break;
case 2:
parts[q] = 192;
break;
case 1:
parts[q] = 128;
break;
}
// 4つの数値を連結して、サブネットマスクを作成する。
return parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
}
}
|
JPanelに直接描画してみました。 今時のJVMだと結構早い描画ができると思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Sample276 extends JFrame {
private final LangtonsAntPanel mainPanel_;
private final JButton startButton_ = new JButton(new AbstractAction("start") {
public void actionPerformed(ActionEvent e) {
timer_.start();
changeMode(true);
}
});
private final JButton stopButton_ = new JButton(new AbstractAction("stop") {
public void actionPerformed(ActionEvent e) {
timer_.stop();
changeMode(false);
}
});
private final JButton resetButton_ = new JButton(new AbstractAction("reset") {
public void actionPerformed(ActionEvent e) {
timer_.stop();
changeMode(false);
mainPanel_.reset();
mainPanel_.repaint();
}
});
private final JButton endButton_ = new JButton(new AbstractAction("end") {
public void actionPerformed(ActionEvent e) {
Sample276.this.dispose();
}
});
private final Timer timer_;
public Sample276(int size) {
super("Langton's ant.");
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainPanel_ = new LangtonsAntPanel(size);
JPanel panel = new JPanel(new BorderLayout(3, 3));
panel.add(mainPanel_, BorderLayout.CENTER);
panel.add(createButtonPanel(), BorderLayout.SOUTH);
this.add(panel);
this.pack();
timer_ = new Timer(5, new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean res = mainPanel_.tick();
mainPanel_.repaint();
if (!res) {
timer_.stop();
changeMode(false);
JOptionPane.showMessageDialog(Sample276.this, "Langton's ant is dead.");
}
}
});
}
private JComponent createButtonPanel() {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 3, 3));
panel.add(startButton_);
panel.add(stopButton_);
panel.add(resetButton_);
panel.add(endButton_);
return panel;
}
private void changeMode(boolean isMoving) {
startButton_.setEnabled(!isMoving);
stopButton_.setEnabled(isMoving);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
throw new InternalError(e.toString());
}
Sample276 frame = new Sample276(100);
frame.setVisible(true);
};
});
}
}
class LangtonsAntPanel extends JPanel {
public enum Direction {
N(0, -1),
E(1, 0),
S(0, 1),
W(-1, 0);
public final int dx;
public final int dy;
private Direction(int x, int y) {
dx = x;
dy = y;
}
public Direction turn(boolean isRight) {
int dd = this.ordinal() + (isRight? 1: 3);
return Direction.values()[dd % 4];
}
}
public class Ant {
private int x_;
private int y_;
private Direction d_ = Direction.N;
private int counter_ = 0;
public Ant(int x, int y) {
x_ = x;
y_ = y;
}
public int getX() {
return x_;
}
public int getY() {
return y_;
}
public int getCounter() {
return counter_;
}
public void next(boolean isBlack) {
d_ = d_.turn(isBlack);
x_ += d_.dx;
y_ += d_.dy;
counter_++;
}
}
private static final int ANT_SIZE = 3;
private final int size_;
private final boolean[][] land_;
private Ant ant_;
public LangtonsAntPanel(int size) {
super(true);
size_ = size;
land_ = new boolean[size][];
for (int index = 0; index < land_.length; index++) {
land_[index] = new boolean[size];
}
ant_ = new Ant(size / 2, size / 2);
setBackground(Color.WHITE);
setForeground(Color.BLACK);
setSize(size * ANT_SIZE, size * ANT_SIZE);
setPreferredSize(getSize());
}
public boolean tick() {
int y = ant_.getY();
int x = ant_.getX();
boolean b = land_[y][x];
land_[y][x] = !b;
ant_.next(b);
y = ant_.getY();
if (y < 0 || size_ <= y) {
return false;
}
x = ant_.getX();
if (x < 0 || size_ <= x) {
return false;
}
return true;
}
public void reset() {
for (int y = 0; y < land_.length; y++) {
for (int x = 0; x < land_[y].length; x++) {
land_[y][x] = false;
}
}
ant_ = new Ant(size_ / 2, size_ / 2);
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setBackground(Color.WHITE);
g2d.setColor(Color.BLACK);
g2d.clearRect(0, 0, this.getWidth(), this.getHeight());
for (int y = 0; y < land_.length; y++) {
for (int x = 0; x < land_[y].length; x++) {
if (land_[y][x]) {
g2d.fillRoundRect(x * ANT_SIZE, y * ANT_SIZE, ANT_SIZE, ANT_SIZE, 1, 1);
}
}
}
g2d.drawString(String.format("turn: %d", ant_.getCounter()), 2, 12);
}
}
|
Threadにて実装。
Pentium M 1.30 GHzで、1000ノード1000周を実行したところ、約30,000msかかりました。
Threadで実装したせいか、時間がかかりすぎています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | import java.util.Date;
public class RingNodeBenchMark {
public static void main( String[] args ) {
int n = 1000; // ノードの数
int m = 1000; // 処理回数
///////////////////////////////////////////////////////////////////////
// 前処理
///////////////////////////////////////////////////////////////////////
// ノードを作成する。
Node[] nodes = new Node[n];
for ( int i = 0; i < nodes.length; ++i ) {
nodes[i] = new Node();
}
// ノードをリング上に繋げる。
nodes[nodes.length-1].nextNode = nodes[0];
for ( int i = 0; i < nodes.length-1; ++i ) {
nodes[i].nextNode = nodes[i+1];
}
// 各ノードのスレッドを開始する。
for ( int i = 0; i < nodes.length; ++i ) {
nodes[i].start();
}
// 処理回数を先頭のノードに指定する。
nodes[0].max = 1000;
///////////////////////////////////////////////////////////////////////
// 主処理
///////////////////////////////////////////////////////////////////////
// 開始時刻を取得する。
Date startTime = new Date();
// 先頭のノードにメッセージを送信する。
nodes[0].interrupt();
// 先頭ノードが終了するまで待機する。
// なお、先頭ノードは、一定回数処理を実行した時点で終了する。
try {
nodes[0].join();
} catch ( InterruptedException e ) {}
// 終了時刻を取得する。
Date endTime = new Date();
///////////////////////////////////////////////////////////////////////
// 後処理
///////////////////////////////////////////////////////////////////////
// 経過時間を計算する。
long result = endTime.getTime() - startTime.getTime();
// 経過時間を表示する。
System.out.println( result + " ms" );
}
// ノード
// スレッドで実装する。
private static class Node extends Thread {
Node nextNode; // 次のノード
int max = -1; // 処理回数
public Node() {
// ノードのスレッドはデーモンスレッドにする。
// この結果、メインスレッドが終了すると、ノードのスレッドは自動的に終了する。
setDaemon( true );
}
public void run() {
int count = 0; // 処理回数のカウンタ。先頭ノードでのみ使用する。
while ( true ) {
// メッセージを受信するまで待機する。
try {
while ( true ) {
Thread.sleep( 1000 );
}
} catch ( InterruptedException e ) {
}
// 先頭ノードの場合、処理回数をカウントする。
if ( max >= 0 ) {
if ( count >= max ) {
// 処理回数が一定の回数を超えた:
// 先頭ノードのスレッドを終了する。
return;
}
count = count + 1;
}
// 次のノードにメッセージを送信する。
nextNode.interrupt();
}
}
}
}
|
先に投稿した#9342を一部変更。
二進数を表示文字列に変換する処理(binToDispStrメソッド)を、文字列置換による実装に変更した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import java.util.Calendar;
import java.util.GregorianCalendar;
public class BinaryClock2 {
public static void main( String[] args ) {
// 現在時刻を取得する。
Calendar cal = new GregorianCalendar();
// 現在時刻から時・分を取得する。
int hour = cal.get( Calendar.HOUR_OF_DAY );
int min = cal.get( Calendar.MINUTE );
// 時・分を二進数に変換する。
String binHour = Integer.toString( hour, 2 );
String binMin = Integer.toString( min, 2 );
// 二進数を表示用文字列に変換する。
String dispStrHour = binToDispStr( binHour );
String dispStrMin = binToDispStr( binMin );
// 表示用文字列を出力する。
System.out.println( dispStrHour );
System.out.println( dispStrMin );
}
// 二進数を表示用文字列に変換する。
// ※文字列置換による実装
private static String binToDispStr( String bin ) {
return bin.replaceAll( "0", "□" )
.replaceAll( "1", "■" );
}
}
|
ごくシンプルに。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import java.util.Calendar;
import java.util.GregorianCalendar;
public class BinaryClock {
public static void main( String[] args ) {
// 現在時刻を取得する。
Calendar cal = new GregorianCalendar();
// 現在時刻から時・分を取得する。
int hour = cal.get( Calendar.HOUR_OF_DAY );
int min = cal.get( Calendar.MINUTE );
// 時・分を二進数に変換する。
String binHour = Integer.toString( hour, 2 );
String binMin = Integer.toString( min, 2 );
// 二進数を表示用文字列に変換する。
String dispStrHour = binToDispStr( binHour );
String dispStrMin = binToDispStr( binMin );
// 表示用文字列を出力する。
System.out.println( dispStrHour );
System.out.println( dispStrMin );
}
// 二進数を表示用文字列に変換する。
private static String binToDispStr( String bin ) {
String bak = "";
for ( int i = 0; i < bin.length(); ++i ) {
if ( bin.charAt( i ) == '0' ) {
bak += "□";
} else {
bak += "■";
}
}
return bak;
}
}
|
あくまでも書式の変換と考えて実装してみました。Cのprintf()関数ファミリーの書式をjava.util.Formatterの書式に変換します。C99の書式を受け付けるようにしましたが、Javaでは意味を持たないp, m変換には対応していません。書式の変換だけでは実現不可能な "*" による幅、精度の指定とn変換にも対応していません。
その代わり、"$" による引数の指定には対応しています。
対応しない書式を指定された場合でも例外にはしていません。java.util.Formatterは厳密に書式のチェックを行っているため、Formatterのチェックに任せたほうが得策と判断したためです。
#結果として、「長さ修飾子」を削っているだけです。:-)
尚、逆変換は行いません。引数の「長さ」によってCの書式は変わりますが、java.util.Formatterの書式は引数の長さに依存しません。従って引数の型が決まらなければCの書式は決まらないからです(そもそも、Cの型システムに強く依存したprintfファミリーの書式に変換する事は無意味と考えます)。
厳密な意味での変換を考えるのであれば、言語のトランスレータを作らなければ不可能でしょう。実用性を考えるなら対応する書式を制限するか、逆に必要性を充分満たすよう定義した書式を処理する独自Formatterを作るべきだと考えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import java.util.regex.*;
public class Sample {
static final Pattern CFORMAT = Pattern.compile(
"(%\\P{Alpha}*)([hlLqjzt]*)([diouxXeEfFgGaAcCsS])");
public static String c2java(String fmt) {
return CFORMAT.matcher(fmt).replaceAll("$1$3");
}
public static void main(String[] args) {
System.out.println(c2java("%s: %#llX%%"));
System.out.println(c2java("%1$s, %3$d. %2$s, %4$d:%5$.2d"));
System.out.println(c2java("pi = %.5f"));
}
|
Mac OS X 10.4.11 の java 1.5.0_19 で実行した結果は以下です。
com.sun.corba.se.impl.logging.ORBUtilSystemException -> 1248
com.sun.corba.se.impl.logging.OMGSystemException -> 524
com.sun.corba.se.impl.logging.POASystemException -> 284
java.awt.Component -> 277
org.w3c.dom.css.CSS2Properties -> 244
com.sun.rowset.CachedRowSetImpl -> 211
com.sun.rowset.internal.SyncResolverImpl -> 206
com.sun.tools.example.debug.expr.ExpressionParser -> 206
com.sun.org.apache.bcel.internal.generic.EmptyVisitor -> 180
com.sun.org.apache.bcel.internal.generic.Visitor -> 180
ちなみに、static メソッドのみを取り出した場合は以下です。
java.util.Arrays static -> 114
java.nio.Bits static -> 114
apple.laf.AquaImageFactory static -> 98
java.lang.Character static -> 80
sun.awt.FontConfiguration static -> 79
com.sun.security.sasl.digest.DigestMD5Base static -> 70
com.sun.org.apache.xalan.internal.xsltc.runtime.BasisLibrary static -> 69
java.net.URI static -> 66
apple.laf.AquaSliderUI static -> 65
com.sun.tools.corba.se.idl.ParseException static -> 63
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | import java.io.*;
import java.lang.reflect.*;
import java.util.Map.Entry;
import java.util.jar.*;
import java.util.*;
public class Sample {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Map<String, Integer> classMap = new HashMap<String, Integer>();
for (String jarName : System.getProperty("sun.boot.class.path").split(System.getProperty("path.separator"))) {
File jar = new File(jarName);
if (jar.isFile()) {
JarFile jf = new JarFile(jar);
for (Enumeration<JarEntry> i = jf.entries(); i.hasMoreElements();) {
String entry = i.nextElement().getName();
if (entry.endsWith(".class")) {
String className = entry.substring(0, entry.length() - 6).replaceAll("/", ".");
Class<?> cc = Class.forName(className, false, null);
int staticCount = 0, memberCount = 0;
for (Method m : cc.getDeclaredMethods()) {
if ((m.getModifiers() & Modifier.STATIC) != 0)
staticCount++;
else
memberCount++;
}
classMap.put(className, memberCount);
classMap.put(className + " static", staticCount);
}
}
}
}
Map.Entry<String, Integer>[] a = classMap.entrySet().toArray(new Map.Entry[0]);
Arrays.sort(a, new Comparator<Map.Entry<String, Integer>> () {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return -o1.getValue().compareTo(o2.getValue());
}
});
for (int i = 0; i < 10; i++) {
System.out.printf("%s -> %d%n", a[i].getKey(), a[i].getValue());
}
}
}
|
メソッド数はそのクラスが持つpublicメソッドの数で、継承されたものを含みます。
結果は以下の通り
javax.swing.JMenuItem : 407
javax.swing.JPasswordField : 407
javax.swing.text.html.FrameView$FrameEditorPane : 408
javax.swing.JEditorPane : 408
javax.swing.JCheckBoxMenuItem : 409
javax.swing.JFormattedTextField : 412
javax.swing.JTextPane : 422
javax.swing.JMenu : 433
javax.swing.JTree : 437
javax.swing.JTable : 456
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | package doukaku;
import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.*;
public class HugeClasses {
public static void main(String[] args) throws Exception {
final File rt = new File(System.getProperty("java.home"), "lib/rt.jar");
if (!rt.exists()) {
System.err.println("rt.jarが見つかりません。");
return;
}
final int topN = 10;
NavigableSet<ClassHolder> sortSet = new TreeSet<ClassHolder>();
for (JarEntry entry : Collections.list(new JarFile(rt).entries())) {
String name = entry.getName();
if ((name.startsWith("java/") || name.startsWith("javax/"))
&& name.endsWith(".class")) {
String className = name.substring(0, name.length() - 6)
.replace('/', '.');
Class<?> clazz = Class.forName(className);
sortSet.add(new ClassHolder(clazz));
if (sortSet.size() > topN) sortSet.pollFirst();
}
}
for (ClassHolder classHolder : sortSet) {
System.out.printf("%-60s: %d%n", classHolder.className,
classHolder.methodCount);
}
}
private static class ClassHolder implements Comparable<ClassHolder> {
private static final AtomicInteger idCounter = new AtomicInteger(0);
private String className;
private int methodCount;
private int id;
ClassHolder(Class<?> clazz) {
id = idCounter.getAndIncrement();
className = clazz.getName();
methodCount = clazz.getMethods().length;
}
@Override
public int compareTo(ClassHolder o) {
return methodCount != o.methodCount ?
methodCount - o.methodCount
: id - o.id;
}
}
}
|





匿名
#10085()
[
Java
]
Rating0/0=0.00
Rating0/0=0.00-0+
[ reply ]