返回
Wordle破译利器——遗传算法
人工智能
2023-09-24 11:05:53
遗传算法:Wordle破译利器
在智力游戏中,"Wordle"无疑是风靡全球的佼佼者。这款每日文字谜题考验着我们的词汇量和逻辑推理能力,引无数玩家竞折腰。而如果你厌倦了常规猜谜,不妨尝试运用遗传算法,让它成为你的"作弊神器"。
遗传算法简介
遗传算法是一种受生物进化启发的优化算法。它通过模拟自然选择和遗传变异,不断迭代更新候选解,逐步逼近最优解。
遗传算法在Wordle中的应用
将遗传算法应用于Wordle,其基本原理如下:
-
初始化种群: 生成随机猜测单词,作为初始候选解种群。
-
计算适应度: 评估每个猜测单词与正确单词的相似度,以此作为适应度。
-
选择: 根据适应度,选择最相似的单词作为亲代。
-
交叉: 通过交换亲代基因(字母),生成新的后代单词。
-
变异: 随机改变后代单词的某个字母,引入多样性。
-
迭代: 重复上述步骤,直至找到最优解(正确单词)或达到最大迭代次数。
Java实现示例
以下是用Java实现的遗传算法代码示例:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class WordleSolver {
private static final List<String> WORD_LIST = new ArrayList<>(); // 单词库
private String targetWord; // 目标单词
private int populationSize; // 种群大小
private int maxIterations; // 最大迭代次数
private double crossoverProbability; // 交叉概率
private double mutationProbability; // 变异概率
public WordleSolver(String targetWord, int populationSize, int maxIterations, double crossoverProbability, double mutationProbability) {
this.targetWord = targetWord;
this.populationSize = populationSize;
this.maxIterations = maxIterations;
this.crossoverProbability = crossoverProbability;
this.mutationProbability = mutationProbability;
}
public String solve() {
// 初始化种群
List<String> population = generateInitialPopulation();
// 迭代直到找到目标单词或达到最大迭代次数
for (int i = 0; i < maxIterations; i++) {
// 计算每个个体的适应度
List<Double> fitnesses = calculateFitnesses(population);
// 根据适应度选择亲代
List<String> parents = selectParents(population, fitnesses);
// 交叉和变异生成后代
List<String> offspring = crossoverAndMutate(parents);
// 替换旧种群
population = offspring;
// 检查是否找到目标单词
if (population.contains(targetWord)) {
return targetWord;
}
}
// 如果未找到目标单词,返回最优猜测
return Collections.max(population, (s1, s2) -> calculateFitness(s1) - calculateFitness(s2));
}
// 初始化种群
private List<String> generateInitialPopulation() {
List<String> population = new ArrayList<>();
for (int i = 0; i < populationSize; i++) {
population.add(generateRandomWord());
}
return population;
}
// 生成随机单词
private String generateRandomWord() {
Random random = new Random();
int index = random.nextInt(WORD_LIST.size());
return WORD_LIST.get(index);
}
// 计算每个个体的适应度
private List<Double> calculateFitnesses(List<String> population) {
List<Double> fitnesses = new ArrayList<>();
for (String word : population) {
fitnesses.add(calculateFitness(word));
}
return fitnesses;
}
// 计算单个个体的适应度
private double calculateFitness(String word) {
int numCorrectLetters = 0;
int numCorrectPositions = 0;
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == targetWord.charAt(i)) {
numCorrectPositions++;
} else if (targetWord.contains(word.charAt(i))) {
numCorrectLetters++;
}
}
return numCorrectPositions * 10 + numCorrectLetters;
}
// 根据适应度选择亲代
private List<String> selectParents(List<String> population, List<Double> fitnesses) {
List<String> parents = new ArrayList<>();
for (int i = 0; i < populationSize; i++) {
int index1 = rouletteWheelSelection(fitnesses);
int index2 = rouletteWheelSelection(fitnesses);
parents.add(population.get(index1));
parents.add(population.get(index2));
}
return parents;
}
// 轮盘赌选择
private int rouletteWheelSelection(List<Double> fitnesses) {
double totalFitness = 0;
for (double fitness : fitnesses) {
totalFitness += fitness;
}
Random random = new Random();
double randomValue = random.nextDouble() * totalFitness;
double currentFitness = 0;
int index = 0;
for (int i = 0; i < fitnesses.size(); i++) {
currentFitness += fitnesses.get(i);
if (currentFitness >= randomValue) {
index = i;
break;
}
}
return index;
}
// 交叉和变异生成后代
private List<String> crossoverAndMutate(List<String> parents) {
List<String> offspring = new ArrayList<>();
for (int i = 0; i < parents.size(); i += 2) {
String parent1 = parents.get(i);
String parent2 = parents.get(i + 1);
// 交叉
if (Math.random() < crossoverProbability) {
int crossoverPoint = random