Java 8, score 26412641 2681
When just a few tiles are left, the remaining letters are combined with the two blanks for the final word.
When just a few tiles are left, the remaining letters are combined with the two blanks for the final word. Update
I increased the threshold to the 50 best words. Also, each combination only adds words that are less than those already present. This prevents multiple permutations of the same group.
PHOTOXYLOGRAPHYOXYPHENBUTAZONE: 585615
VENTRILOQUIZINGMICROEARTHQUAKE: 555525
NONOBJECTIVISMSINTERSUBJECTIVE: 465435
ACKNOWLEDGEABLEDAFFADOWNDILLY: 420406
DEDIFFERENTIATEPREINTERVIEWING: 345360
EUDIOMETRIESAUTOALLOGAMIES: 180238
WAURGOODSIRES: 2899
?A?ASAURA: 633 (MAIASAURAZAX)
---
Total: 26412681
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Scrabble {
static final int[] scores = new int[]{1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10, 0};
static final int[] freqs = new int[]{9, 2, 2, 4, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1, 2};
static final int MAX = 40;50;
public static void main(String[] args) throws IOException {
List<String> words = Files.readAllLines(new File("C:/Users/Ypnypn/scrabble.txt").toPath());
words.sort((s, t) -> score(t) - score(s));
words.removeIf(w -> !works(w));
List<List<String>> last = words.stream().map(Arrays::asList).collect(Collectors.toList()),
finalList = new ArrayList();
for (int i = 0; i < 10; i++) {
List<List<String>> next = new ArrayList();
for (int j = 0; j < MAX && j < last.size(); j++) {
List<String> group = last.get(j);
Object[] thirds = words.stream().filter(word -> workTogether(group, word) && least(word, group)).toArray();
for (int k = 0; k < MAX && k < thirds.length; k++) {
List<String> newList = new ArrayList(group);
newList.add((String) thirds[k]);
next.add(newList);
}
}
last = next;
last.sort((s, t) -> t.stream().mapToInt(Scrabble::score).sum()
- s.stream().mapToInt(Scrabble::score).sum());
for (List<String> l : last) {
if (l.stream().mapToInt(String::length).sum() > 90) {
finalList.add(l);
}
}
}
finalList.forEach(g -> {
List<Integer> chars = new ArrayList();
int[] counts = new int[26];
g.forEach(str -> str.chars().forEach(c -> counts[c - 'A']++));
for (int i = 0; i < 26; i++) {
while (counts[i] < freqs[i]) {
chars.add('A' + i);
counts[i]++;
}
}
String end = words.stream()
.filter(w -> w.length() == chars.size() + 2)
.filter(w -> g.stream().noneMatch(s -> s.charAt(0) == w.charAt(0)))
.filter(w -> {
List<Integer> copy = new ArrayList(chars);
int _1 = 0, _2 = 0;
for (char c : w.toCharArray()) {
if (copy.contains((int) c)) {
copy.remove((Integer) (int) c);
} else if (_1 == 0) {
_1 = c;
} else if (_2 == 0) {
_2 = c;
} else {
return false;
}
}
return true;
}).findAny().orElse("");
if (end.equals("")) {
return;
}
char[] arr = end.toCharArray();
for (int i = 0; i < arr.length; i++) {
if (chars.contains((int) arr[i])) {
chars.remove((Integer) (int) arr[i]);
} else {
arr[i] = '?';
}
}
g.add(new String(arr));
});
finalList.removeIf(g -> g.stream().mapToInt(String::length).sum() < 100);
finalList.sort((s, t) -> t.stream().mapToInt(Scrabble::score).sum()
- s.stream().mapToInt(Scrabble::score).sum());
List<String> answer = finalList.get(0);
for (String str : answer) {
System.out.print(str + ": " + score(str));
if (str.contains("?")) {
String actual = words.stream().filter(s -> s.matches("^" + str.replace('?', '.') + "$")).findAny().get();
System.out.print(" (" + actual + ")");
}
System.out.println();
}
System.out.println("---");
System.out.println("Total: " + answer.stream().mapToInt(Scrabble::score).sum());
}
static boolean works(String str) {
int[] counts = new int[26];
for (char c : str.toCharArray()) {
counts[c - 'A']++;
}
for (int i = 0; i < 26; i++) {
if (counts[i] > freqs[i]) {
return false;
}
}
return true;
}
static boolean workTogether(List<String> strs, String str) {
if (strs.stream().anyMatch(s -> s.charAt(0) == str.charAt(0))) {
return false;
}
int[] counts = new int[26];
strs.stream().forEach(s -> s.chars().forEach(c -> counts[c - 'A']++));
str.chars().forEach(c -> counts[c - 'A']++);
for (int i = 0; i < 26; i++) {
if (counts[i] > freqs[i]) {
return false;
}
}
return true;
}
static boolean least(String str, List<String> strs) {
int score = score(str);
return strs.stream().allMatch(s -> score(s) >= score);
}
static int score(String word) {
int score = 0;
for (char c : word.toCharArray()) {
if (c != '?') {
score += scores[c - 'A'];
}
}
return score * word.length();
}
}