3 minutes
By: Mitch
Optimising Wordle Openings in Python
Like many this holiday season, my family has become hooked on Wordle and my mind immediately turned to what an optimal opening would be…
Initially I started packing vowels into the first word like ALIEN or SAUCE - which is fine but a better strategy would also:
- Provide guidance on the second word (to give you enough to solve in three)
- Cover at least 9 unique letters over the two words
- Provide a weighted score based on the number of Yellows and Greens you could get
Jumping straight to the end, the following are my three favorite openings:
How to Use
Firstly pick one of the purple words as your first word.
If you get a Yellow - use the matching vertical word which moves the letter to a new position and provides four new letters.
If you get nothing on the first - use the backup word at the bottom to give you five new letters.
The Approach & Code
The first step in coming up with these openings is to take a database of all five letter words and give each word that provides 1 point for each yellow it gets on all other words and an additional 2 points if it gets a green.
Tweaking these weights will provide different openings.
wordscores = []
for word in words:
if len({x for x in word}) >= 5: # We only want words that have
score = {'word':word,'yellow':0,'green':0}
for testword in words:
score['yellow'] += sum([1 if x in testword else 0 for x in {x for x in word}])
score['green'] += sum([1 if word[i]==testword[i] else 0 for i in range(0,5)])
score['score'] = score['yellow'] + score['green']*2
wordscores.append(score)
wordscores.sort(key=lambda x: x['score'], reverse=True)
wordscores[:10]
Which provides
[{'word': 'stare', 'yellow': 7295, 'green': 2168, 'score': 11631},
{'word': 'raise', 'yellow': 7331, 'green': 2142, 'score': 11615},
{'word': 'slate', 'yellow': 6973, 'green': 2310, 'score': 11593},
{'word': 'sorel', 'yellow': 6816, 'green': 2363, 'score': 11542},
{'word': 'saute', 'yellow': 6691, 'green': 2414, 'score': 11519},
{'word': 'snare', 'yellow': 7126, 'green': 2195, 'score': 11516},
{'word': 'carse', 'yellow': 6946, 'green': 2272, 'score': 11490},
{'word': 'caret', 'yellow': 6889, 'green': 2291, 'score': 11471},
{'word': 'arise', 'yellow': 7331, 'green': 2052, 'score': 11435},
{'word': 'arose', 'yellow': 7393, 'green': 2015, 'score': 11423}]
Which by themselves are perfectly good opening words, but we also want words that have good follow up options
openings = [{'totalscore':x['score']*6, 'word':x['word']} for x in wordscores]
for firstword in openings:
for word in wordscores:
if (len({y for y in firstword['word']+word['word']})>=10):
firstword['secondword0'] = word['word']
firstword['totalscore'] += word['score']
break
for i in range(0,5):
for word in wordscores:
if (firstword['word'][i] != word['word'][i]) and (firstword['word'][i] in word['word']) and (len({y for y in firstword['word']+word['word']})>=9):
firstword['secondword{}'.format(i+1)] = word['word']
firstword['totalscore'] += word['score']
break
openings.sort(key=lambda x: x['totalscore'], reverse=True)
openings[:5]
Which provides the opening combos:
[{'totalscore': 127190, 'word': 'sorel', 'secondword0': 'canty', 'secondword1': 'tansy', 'secondword2': 'atony', 'secondword3': 'rainy', 'secondword4': 'thane', 'secondword5': 'laity'}
,{'totalscore': 126635, 'word': 'slate', 'secondword0': 'corny', 'secondword1': 'noisy', 'secondword2': 'roily', 'secondword3': 'rainy', 'secondword4': 'court', 'secondword5': 'coney'}
,{'totalscore': 125889, 'word': 'saute', 'secondword0': 'roily', 'secondword1': 'loris', 'secondword2': 'coaly', 'secondword3': 'curly', 'secondword4': 'droit', 'secondword5': 'oriel'}
,{'totalscore': 125667, 'word': 'saint', 'secondword0': 'poler', 'secondword1': 'corse', 'secondword2': 'blare', 'secondword3': 'oiler', 'secondword4': 'coney', 'secondword5': 'route'}
,{'totalscore': 125585, 'word': 'stare', 'secondword0': 'doily', 'secondword1': 'noisy', 'secondword2': 'point', 'secondword3': 'daily', 'secondword4': 'roily', 'secondword5': 'coney'}]