eliminationScore = (word) => {
const exclude = new Set(gray);
return (
d3.sum(
answers.map((answer) => {
if (word === answer) return answers.length - 1;
const next = {
exclude: new Set(exclude),
green: green.slice(),
yellow: yellow.slice()
};
for (const l of word) if (!answer.includes(l)) next.exclude.add(l);
for (const [i, [l, a]] of d3.zip(word, answer).entries()) {
if (l === a) next.green[i] = l;
else if (!next.exclude.has(l)) next.yellow[i] += l;
}
if (cache.has(next)) return cache.get(next);
const include = new Set(
next.yellow.concat(next.green).flatMap((l) => Array.from(l))
);
const match = new RegExp(
d3
.zip(next.green, next.yellow)
.map(([g, y]) => (g ? g[0] : y ? `[^${y}]` : "."))
.join("")
);
const delta =
answers.length -
d3.count(
answers,
(w) =>
w.match(match) &&
d3.every(include, (l) => w.includes(l)) &&
d3.every(w, (l) => !exclude.has(l))
);
cache.set(next, delta);
return delta;
})
) /
answers.length /
answers.length
);
}