import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
class MasterMindPP {
public static Set<String> options = new HashSet<>();
// Load up permutations
public static void loadPossibilities() {
for (char c1 = 'a'; c1 <= 'z'; c1++) {
for (char c2 = 'a'; c2 <= 'z'; c2++) {
for (char c3 = 'a'; c3 <= 'z'; c3++) {
for (char c4 = 'a'; c4 <= 'z'; c4++) {
for (char c5 = 'a'; c5 <= 'z'; c5++) {
options.add(c1 + "" + c2 + "" + c3 + "" + c4 + "" + c5);
}
}
}
}
}
System.
out.
println(options.
size()); }
// Remove all entries that do not yield the same score when matched with
// guess / definite wrong anwers.
public static void removeMatch
(String guess,
int score
) { Set<String> remove = new HashSet<>();
for (String entry
: options
) { int match = computeMatch(guess, entry);
if (score != match)
remove.add(entry);
}
options.removeAll(remove);
}
// Given two strings, match them and return score 10*EXACT_MATCH +
// MISMATCHES
private static int computeMatch
(String guess,
String entry
) { int exact = 0;
int mismatch = 0;
for (int i = 0; i < 5; i++) {
if (guess.charAt(i) == entry.charAt(i))
exact++;
}
for (char c : mapG.keySet()) {
mismatch
+= Math.
min(mapG.
getOrDefault(c,
0), mapE.
getOrDefault(c,
0)); }
return exact * 10 + mismatch - exact;
}
// Given string, count chars
Map
<Character, Integer
> map
= new HashMap
<>(); for (int i = 0; i < 5; i++) {
map.put(guess.charAt(i), 1 + map.getOrDefault(guess.charAt(i), 0));
}
return map;
}
public static void main
(String[] args
) { loadPossibilities();
String answer
= getRandomGuess
();
while (options.size() > 1) {
String guess
= getRandomGuess
(); removeMatch(guess, computeMatch(guess, answer));
System.
out.
println(guess
+ ":" + computeMatch
(guess, answer
) + ":" + options.
size());
}
}
// Return one random string from the options
private static String getRandomGuess
() { List<String> asList = new ArrayList<>(options);
return asList.get(0);
}
}
aW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuQ29sbGVjdGlvbnM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5IYXNoU2V0OwppbXBvcnQgamF2YS51dGlsLkxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuTWFwOwppbXBvcnQgamF2YS51dGlsLlNldDsKCiBjbGFzcyBNYXN0ZXJNaW5kUFAgewoKCXB1YmxpYyBzdGF0aWMgU2V0PFN0cmluZz4gb3B0aW9ucyA9IG5ldyBIYXNoU2V0PD4oKTsKCgkvLyBMb2FkIHVwIHBlcm11dGF0aW9ucwoJcHVibGljIHN0YXRpYyB2b2lkIGxvYWRQb3NzaWJpbGl0aWVzKCkgewoJCWZvciAoY2hhciBjMSA9ICdhJzsgYzEgPD0gJ3onOyBjMSsrKSB7CgkJCWZvciAoY2hhciBjMiA9ICdhJzsgYzIgPD0gJ3onOyBjMisrKSB7CgkJCQlmb3IgKGNoYXIgYzMgPSAnYSc7IGMzIDw9ICd6JzsgYzMrKykgewoJCQkJCWZvciAoY2hhciBjNCA9ICdhJzsgYzQgPD0gJ3onOyBjNCsrKSB7CgkJCQkJCWZvciAoY2hhciBjNSA9ICdhJzsgYzUgPD0gJ3onOyBjNSsrKSB7CgkJCQkJCQlvcHRpb25zLmFkZChjMSArICIiICsgYzIgKyAiIiArIGMzICsgIiIgKyBjNCArICIiICsgYzUpOwoJCQkJCQl9CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoJCVN5c3RlbS5vdXQucHJpbnRsbihvcHRpb25zLnNpemUoKSk7Cgl9CgoJLy8gUmVtb3ZlIGFsbCBlbnRyaWVzIHRoYXQgZG8gbm90IHlpZWxkIHRoZSBzYW1lIHNjb3JlIHdoZW4gbWF0Y2hlZCB3aXRoCgkvLyBndWVzcyAvIGRlZmluaXRlIHdyb25nIGFud2Vycy4KCXB1YmxpYyBzdGF0aWMgdm9pZCByZW1vdmVNYXRjaChTdHJpbmcgZ3Vlc3MsIGludCBzY29yZSkgewoJCVNldDxTdHJpbmc+IHJlbW92ZSA9IG5ldyBIYXNoU2V0PD4oKTsKCQlmb3IgKFN0cmluZyBlbnRyeSA6IG9wdGlvbnMpIHsKCQkJaW50IG1hdGNoID0gY29tcHV0ZU1hdGNoKGd1ZXNzLCBlbnRyeSk7CgkJCWlmIChzY29yZSAhPSBtYXRjaCkKCQkJCXJlbW92ZS5hZGQoZW50cnkpOwoJCX0KCQlvcHRpb25zLnJlbW92ZUFsbChyZW1vdmUpOwoJfQoKCS8vIEdpdmVuIHR3byBzdHJpbmdzLCBtYXRjaCB0aGVtIGFuZCByZXR1cm4gc2NvcmUgMTAqRVhBQ1RfTUFUQ0ggKwoJLy8gTUlTTUFUQ0hFUwoJcHJpdmF0ZSBzdGF0aWMgaW50IGNvbXB1dGVNYXRjaChTdHJpbmcgZ3Vlc3MsIFN0cmluZyBlbnRyeSkgewoJCWludCBleGFjdCA9IDA7CgkJaW50IG1pc21hdGNoID0gMDsKCQlmb3IgKGludCBpID0gMDsgaSA8IDU7IGkrKykgewoJCQlpZiAoZ3Vlc3MuY2hhckF0KGkpID09IGVudHJ5LmNoYXJBdChpKSkKCQkJCWV4YWN0Kys7CgkJfQoJCU1hcDxDaGFyYWN0ZXIsIEludGVnZXI+IG1hcEcgPSBtYXBJdChndWVzcyk7CgkJTWFwPENoYXJhY3RlciwgSW50ZWdlcj4gbWFwRSA9IG1hcEl0KGVudHJ5KTsKCQlmb3IgKGNoYXIgYyA6IG1hcEcua2V5U2V0KCkpIHsKCQkJbWlzbWF0Y2ggKz0gTWF0aC5taW4obWFwRy5nZXRPckRlZmF1bHQoYywgMCksIG1hcEUuZ2V0T3JEZWZhdWx0KGMsIDApKTsKCQl9CgoJCXJldHVybiBleGFjdCAqIDEwICsgbWlzbWF0Y2ggLSBleGFjdDsKCX0KCgkvLyBHaXZlbiBzdHJpbmcsIGNvdW50IGNoYXJzCglwcml2YXRlIHN0YXRpYyBNYXA8Q2hhcmFjdGVyLCBJbnRlZ2VyPiBtYXBJdChTdHJpbmcgZ3Vlc3MpIHsKCQlNYXA8Q2hhcmFjdGVyLCBJbnRlZ2VyPiBtYXAgPSBuZXcgSGFzaE1hcDw+KCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCA1OyBpKyspIHsKCQkJbWFwLnB1dChndWVzcy5jaGFyQXQoaSksIDEgKyBtYXAuZ2V0T3JEZWZhdWx0KGd1ZXNzLmNoYXJBdChpKSwgMCkpOwoJCX0KCQlyZXR1cm4gbWFwOwoJfQoKCXB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsKCQlsb2FkUG9zc2liaWxpdGllcygpOwoJCVN0cmluZyBhbnN3ZXIgPSBnZXRSYW5kb21HdWVzcygpOwoKCQl3aGlsZSAob3B0aW9ucy5zaXplKCkgPiAxKSB7CgkJCVN0cmluZyBndWVzcyA9IGdldFJhbmRvbUd1ZXNzKCk7CgkJCXJlbW92ZU1hdGNoKGd1ZXNzLCBjb21wdXRlTWF0Y2goZ3Vlc3MsIGFuc3dlcikpOwoJCQlTeXN0ZW0ub3V0LnByaW50bG4oZ3Vlc3MgKyAiOiIgKyBjb21wdXRlTWF0Y2goZ3Vlc3MsIGFuc3dlcikgKyAiOiIgKyBvcHRpb25zLnNpemUoKSk7CgoJCX0KCgl9CgkKCS8vIFJldHVybiBvbmUgcmFuZG9tIHN0cmluZyBmcm9tIHRoZSBvcHRpb25zCglwcml2YXRlIHN0YXRpYyBTdHJpbmcgZ2V0UmFuZG9tR3Vlc3MoKSB7CgkJTGlzdDxTdHJpbmc+IGFzTGlzdCA9IG5ldyBBcnJheUxpc3Q8PihvcHRpb25zKTsKCQlDb2xsZWN0aW9ucy5zaHVmZmxlKGFzTGlzdCk7CgkJcmV0dXJuIGFzTGlzdC5nZXQoMCk7Cgl9Cgp9Cg==