Lisp vs. Java???
via http://www.kmonos.net/alang/d/2.0/lisp-java-d.html
なんだか、LispがJava や C++ より優れた結果を残しているようなので、自分も挑戦してみました。
とりあえず問題を見て入力をみたり出力を確認したりしながら、1時間半ほどで以下のコードが書けました。空行やコメント、unittest、(Lispと合わせて) 末尾の閉じ括弧 } を除くと、77行でした。Link先のDで書いたほうが短くなってますね。やっていることは単純に、前のほうから一致する単語を探索していくだけです。気をつけるのは、数字は1文字だけならそのまま使っても良い、と言うところくらいですかね?
Javaでもこれくらいはできるぞ、と誰かに言いたくなったのでEntryを起こしちゃいました。
package ch.jpn.taoe.challenge; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import org.junit.Test; public class PhoneToWord { ///// ABCDEFGHIJKLMNOPQRSTUVWXYZ private static final char[] TABLE = "57630499617851881234762239".toCharArray(); private final Map<String, List<String>> dictionary_ = new HashMap<String, List<String>>(); public PhoneToWord() { } public void addWord(String word) { String key = wordToNumber(word); List<String> list = dictionary_.get(key); if (list == null) { list = new ArrayList<String>(); dictionary_.put(key, list); } list.add(word); } public String[] convertToWords(String input) { List<String> search = new ArrayList<String>(); search.add(""); matchWords(wordToNumber(input), 0, false, search); String[] result = new String[search.size()]; for (int index = 0; index < result.length; index++) { result[index] = String.format("%s:%s", input, search.get(index)); } return result; } private boolean matchWords(String input, int offset, boolean useNumber, List<String> result) { //System.out.println("matchWords:" + input + ", offset=" + offset + ", useNum=" + useNumber + ", " + result); if (offset >= input.length()) return true; boolean matched = false; List<String> matchedResult = new ArrayList<String>(); for (String key: dictionary_.keySet()) { if (!input.startsWith(key, offset)) { continue; } List<String> work = new ArrayList<String>(); for (String word: result) { for (String add: dictionary_.get(key)) { work.add(word + " " + add); } } boolean res = matchWords(input, offset + key.length(), false, work); if (res) { matched = true; matchedResult.addAll(work); } } if (!matched && !useNumber) { char c = input.charAt(offset); List<String> work = new ArrayList<String>(); for (String word: result) { work.add(word + " " + c); } boolean res = matchWords(input, offset + 1, true, work); if (res) { matched = true; matchedResult.addAll(work); } } //System.out.println(matched + ", " + matchedResult); result.clear(); result.addAll(matchedResult); return matched; } private String wordToNumber(String word) { StringBuilder builder = new StringBuilder(); for (int index = 0, length = word.length(); index < length; index++) { char c = word.charAt(index); if ('0' <= c && c <= '9') { builder.append(c); } else if ('a' <= c && c <= 'z') { builder.append(TABLE[c - 'a']); } else if ('A' <= c && c <= 'Z') { builder.append(TABLE[c - 'A']); } } return builder.toString(); } @Test public void testCheckLetter() { assertEquals("", wordToNumber("")); assertEquals("01112223334455666777888999", wordToNumber("e | j n q | r w x | d s y | f t | a m | c i v | b k u | l o p | g h z")); assertEquals("01112223334455666777888999", wordToNumber("E | J N Q | R W X | D S Y | F T | A M | C I V | B K U | L O P | G H Z")); assertEquals("0123456789", wordToNumber("0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9")); } @Test public void testAddData() { PhoneToWord test = new PhoneToWord(); for (String word: new String[] {"an", "blau", "Bo\"", "Boot", "bo\"s", "da", "Fee", "fern", "Fest", "fort", "je", "jemand", "mir", "Mix", "Mixer", "Name", "neu", "o\"d", "Ort", "so", "Tor", "Torf", "Wasser"}) { test.addWord(word); } List<String> list = test.dictionary_.get("51"); assertNotNull(list); assertEquals(1, list.size()); assertEquals("an", list.get(0)); list = test.dictionary_.get("562"); assertEquals(2, list.size()); assertEquals("mir", list.get(0)); assertEquals("Mix", list.get(1)); } @Test public void testConvertToWords() { PhoneToWord test = new PhoneToWord(); for (String word: new String[] {"an", "blau", "Bo\"", "Boot", "bo\"s", "da", "Fee", "fern", "Fest", "fort", "je", "jemand", "mir", "Mix", "Mixer", "Name", "neu", "o\"d", "Ort", "so", "Tor", "Torf", "Wasser"}) { test.addWord(word); } assertArrayEquals(new String[] { }, test.convertToWords("112")); assertArrayEquals(new String[] { "5624-82: mir Tor", "5624-82: Mix Tor" }, test.convertToWords("5624-82")); assertArrayEquals(new String[] { "4824: fort", "4824: Torf", "4824: Tor 4", }, test.convertToWords("4824")); assertArrayEquals(new String[] { }, test.convertToWords("0721/608-4067")); assertArrayEquals(new String[] { "10/783--5: je Bo\" da", "10/783--5: je bo\"s 5", "10/783--5: neu o\"d 5", }, test.convertToWords("10/783--5")); assertArrayEquals(new String[] { }, test.convertToWords("1078-913-5")); assertArrayEquals(new String[] { "381482: so 1 Tor" }, test.convertToWords("381482")); assertArrayEquals(new String[] { "04824: 0 fort", "04824: 0 Torf", "04824: 0 Tor 4", }, test.convertToWords("04824")); } public static void main(String[] args) throws Exception { PhoneToWord test = new PhoneToWord(); Scanner dict = new Scanner(new File("dictionary.txt")); while (dict.hasNext()) { test.addWord(dict.nextLine()); } Scanner input = new Scanner(new File("input.txt")); while (input.hasNext()) { String[] result = test.convertToWords(input.nextLine()); for (String s: result) { System.out.println(s); } } } }