Java,249700点(在我的测试中击败了中国人Perl Goth)
更新的排名列表:
4 5 6 7 8 9 10 11 12 13总计
perl chinese_perl_goth.pl 6700 12300 16900 19200 23000 26100 28500 29600 32100 33900 228300
Java Lingo 9400 14700 18900 21000 26300 28700 30300 32400 33800 34200 249700
这是使用的旧排名列表pit.rb
:
4 5 6 7 8 9 10 11 12 13总计
ruby player-example.rb 2004004005001800 1400 1700 1600 3200 4400 15600
ruby player-example2.rb 2700 3200 2500 4300 7300 6300 8200 10400 13300 15000 73200
ruby player-example3.rb 4500 7400 9900 13700 15400 19000 19600 22300 24600 27300 163700
perl chinese_perl_goth.pl 6400 14600 16500 21000 22500 26000 27200 30600 32500 33800 231100
Java Lingo 4800 13100 16500 21400 27200 29200 30600 32400 33700 36100 245000
**排名**
1:Java Lingo(245000)
2:perl chinese_perl_goth.pl(231100)
3:ruby player-example3.rb(163700)
4:ruby player-example2.rb(73200)
5:ruby player-example.rb(15600)
与@chineseperlgoth相比,我输了较短的单词(<6个字符),但我输了较长的单词(> = 6个字符)。
这个想法类似于@chineseperlgoth,只是我的主要想法是找到猜测(可以是相同长度的任何单词,不一定是剩余的可能性之一),它可以为下一次猜测提供最多的信息。
目前,我仍在使用公式,但是对于上面的记分板,我选择的单词将产生以下最小值:
-num_confusion *熵
最新版本使用不同的评分来找到下一个最佳猜测,这是在当前猜测之后最大化“单一可能性”的数量。通过对所有可能的候选词尝试修剪后的词表中的所有词(以节省时间),并查看哪个猜测更有可能产生“单一可能性”(也就是说,在此猜测之后将只有一个可能的答案)来完成此操作下一个猜测。
因此,例如此运行:
开始新的一轮,话是福音
得到了:seora
发送:?XOXX
得到了:topsl
发送:XOX?X
得到:和尚
发送:XO?XO
得了:bewig
发送:OXXXX
得到了:恩赐
发送:OOOOO
回合以100分获胜
从前三个猜测中,我们已经在某个地方带有“ n”的“ * oo * s”,我们仍然需要找出另外一个字母。现在,该算法的优点在于,它不用猜测与该形式相似的单词,而是猜测与先前的猜测完全无关的单词,从而尝试给出更多字母,并希望揭示出丢失的字母。在这种情况下,它碰巧也正确地获得了丢失的“ b”的位置,并以正确的最终猜测“恩赐”结束。
这是代码:
import java.util.*;
import java.io.*;
class Lingo{
public static String[] guessBestList = new String[]{
"",
"a",
"sa",
"tea",
"orae",
"seora", // 5
"ariose",
"erasion",
"serotina",
"tensorial",
"psalterion", // 10
"ulcerations",
"culteranismo",
"persecutional"};
public static HashMap<Integer, ArrayList<String>> wordlist = new HashMap<Integer, ArrayList<String>>();
public static void main(String[] args){
readWordlist("wordlist.txt");
Scanner scanner = new Scanner(System.in);
int wordlen = Integer.parseInt(args[0]);
int roundNum = 5;
ArrayList<String> candidates = new ArrayList<String>();
candidates.addAll(wordlist.get(wordlen));
String guess = "";
while(roundNum-- > 0){
guess = guessBest(candidates, roundNum==4, roundNum==0);
System.out.println(guess);
String response = scanner.nextLine();
if(isAllO(response)){
break;
}
updateCandidates(candidates, guess, response);
//print(candidates);
}
}
public static void print(ArrayList<String> candidates){
for(String str: candidates){
System.err.println(str);
}
System.err.println();
}
public static void readWordlist(String path){
try{
BufferedReader reader = new BufferedReader(new FileReader(path));
while(reader.ready()){
String word = reader.readLine();
if(!wordlist.containsKey(word.length())){
wordlist.put(word.length(), new ArrayList<String>());
}
wordlist.get(word.length()).add(word);
}
} catch (Exception e){
System.exit(1);
}
}
public static boolean isAllO(String response){
for(int i=0; i<response.length(); i++){
if(response.charAt(i) != 'O') return false;
}
return true;
}
public static String getResponse(String word, String guess){
char[] wordChar = word.toCharArray();
char[] result = new char[word.length()];
Arrays.fill(result, 'X');
for(int i=0; i<guess.length(); i++){
if(guess.charAt(i) == wordChar[i]){
result[i] = 'O';
wordChar[i] = '_';
}
}
for(int i=0; i<guess.length(); i++){
if(result[i] == 'O') continue;
for(int j=0; j<wordChar.length; j++){
if(result[j] == 'O') continue;
if(wordChar[j] == guess.charAt(i)){
result[i] = '?';
wordChar[j] = '_';
break;
}
}
}
return String.valueOf(result);
}
public static void updateCandidates(ArrayList<String> candidates, String guess, String response){
for(int i=candidates.size()-1; i>=0; i--){
String candidate = candidates.get(i);
if(!response.equals(getResponse(candidate, guess))){
candidates.remove(i);
}
}
}
public static int countMatchingCandidates(ArrayList<String> candidates, String guess, String response){
int result = 0;
for(String candidate: candidates){
if(response.equals(getResponse(candidate, guess))){
result++;
}
}
return result;
}
public static String[] getSample(ArrayList<String> words, int size){
String[] result = new String[size];
int[] indices = new int[words.size()];
for(int i=0; i<words.size(); i++){
indices[i] = i;
}
Random rand = new Random(System.currentTimeMillis());
for(int i=0; i<size; i++){
int take = rand.nextInt(indices.length-i);
result[i] = words.get(indices[take]);
indices[take] = indices[indices.length-i-1];
}
return result;
}
public static String guessBest(ArrayList<String> candidates, boolean firstGuess, boolean lastGuess){
if(candidates.size() == 1){
return candidates.get(0);
}
String minGuess = candidates.get(0);
int wordlen = minGuess.length();
if(firstGuess && guessBestList[wordlen].length()==wordlen){
return guessBestList[wordlen];
}
int minMatches = Integer.MAX_VALUE;
String[] words;
if(lastGuess){
words = candidates.toArray(new String[0]);
} else if (candidates.size()>10){
words = bestWords(wordlist.get(wordlen), candidates, 25);
} else {
words = wordlist.get(wordlen).toArray(new String[0]);
}
for(String guess: words){
double sumMatches = 0;
for(String word: candidates){
int matches = countMatchingCandidates(candidates, guess, getResponse(word, guess));
if(matches == 0) matches = candidates.size();
sumMatches += (matches-1)*(matches-1);
}
if(sumMatches < minMatches){
minGuess = guess;
minMatches = sumMatches;
}
}
return minGuess;
}
public static String[] bestWords(ArrayList<String> words, ArrayList<String> candidates, int size){
int[] charCount = new int[123];
for(String candidate: candidates){
for(int i=0; i<candidate.length(); i++){
charCount[(int)candidate.charAt(i)]++;
}
}
String[] tmp = (String[])words.toArray(new String[0]);
Arrays.sort(tmp, new WordComparator(charCount));
String[] result = new String[size+Math.min(size, candidates.size())];
String[] sampled = getSample(candidates, Math.min(size, candidates.size()));
for(int i=0; i<size; i++){
result[i] = tmp[tmp.length-i-1];
if(i < sampled.length){
result[size+i] = sampled[i];
}
}
return result;
}
static class WordComparator implements Comparator<String>{
int[] charCount = null;
public WordComparator(int[] charCount){
this.charCount = charCount;
}
public Integer count(String word){
int result = 0;
int[] multiplier = new int[charCount.length];
Arrays.fill(multiplier, 1);
for(char chr: word.toCharArray()){
result += multiplier[(int)chr]*this.charCount[(int)chr];
multiplier[(int)chr] = 0;
}
return Integer.valueOf(result);
}
public int compare(String s1, String s2){
return count(s1).compareTo(count(s2));
}
}
}