Last active
January 21, 2022 16:45
-
-
Save sirhc/299158b3e3edca0a56576911b8a2b6d3 to your computer and use it in GitHub Desktop.
Script to help identify words for Wordle (https://powerlanguage.co.uk/wordle)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Usage: wordle [-f <word file>] [-g <green pattern>] [-y <yellow pattern>]... [-x <gray letters>] | |
# | |
# The word file defaults to '/usr/share/dict/words'. | |
# | |
# The green pattern defaults to '.....', which will include all five letter | |
# words from the word file. | |
# | |
# Multiple yellow patterns can be given, typically corresponding to each | |
# occurrence in the game. For example, | |
# | |
# > wordle -y r.pi. -y .i.r. | |
# | |
# Only words containing these letters will be included in the final output. | |
# Words with letters in those positions will be excluded. | |
# | |
# Words containing any of the excluded letters will be excluded from the final | |
# output. | |
set -euo pipefail | |
file='/usr/share/dict/words' | |
green='.....' | |
yellow=() | |
exclude='' | |
while getopts 'f:g:y:x:' opt; do | |
case "$opt" in | |
f) | |
file="$OPTARG" | |
;; | |
g) | |
green="$OPTARG" | |
;; | |
y) | |
yellow+=("$OPTARG") | |
;; | |
x) | |
exclude="$OPTARG" | |
;; | |
*) | |
exit 2 | |
;; | |
esac | |
done | |
filter_green() { | |
grep -E "^${green}$" | |
} | |
filter_yellow_letters() { | |
if [[ ${#yellow[@]} -eq 0 ]]; then | |
cat | |
return | |
fi | |
# Translate the yellow array into a list of unique letters to use for | |
# filtering. For example, if yellow=(r.pi. .i.r.), then letters=(i p r). | |
local IFS= | |
local tmp="${yellow[*]//[^a-z]/}" | |
local -a letters | |
readarray -t letters < <( | |
for (( i=0; i<${#tmp}; i++ )); do | |
printf '%s\n' "${tmp:$i:1}" | |
done | sort -u | |
) | |
# Only pass along words that contain all of the yellow letters. | |
local good | |
while read -r word; do | |
good=1 | |
for i in ${letters[*]}; do | |
if [[ ! $word =~ $i ]]; then | |
good=0 | |
fi | |
done | |
if [[ $good -eq 1 ]]; then | |
echo "$word" | |
fi | |
done | |
} | |
filter_yellow_positions() { | |
if [[ ${#yellow[@]} -eq 0 ]]; then | |
cat | |
return | |
fi | |
# Translate the yellow array into individual letter patterns that can be | |
# applied separately. For example, if yellow=(r.pi. .i.r.), then | |
# patterns=( | |
# r.... | |
# ..... | |
# ..p.. | |
# ...i. | |
# ..... | |
# ..... | |
# .i... | |
# ..... | |
# ...r. | |
# ..... | |
# ). The patterns that are all '.' will be excluded from the final list | |
# used for filtering. | |
local -a patterns | |
local y | |
local i | |
local j | |
readarray -t patterns < <( | |
{ | |
for y in "${yellow[@]}"; do | |
for (( i=0; i<${#y}; i++ )); do | |
for (( j = 0; j < i; j++ )); do | |
printf '.' | |
done | |
printf '%s' "${y:$i:1}" | |
for (( j = i; j < 4; j++ )); do | |
printf '.' | |
done | |
printf '\n' | |
done | |
done | |
} | grep -Fv '.....' | |
) | |
# Exclude words that contain the yellow letters in the yellow position. | |
local IFS='|' | |
grep -Ev "^(${patterns[*]})$" | |
} | |
filter_gray() { | |
if [[ -n $exclude ]]; then | |
grep -Ev "[${exclude}]" | |
else | |
cat | |
fi | |
} | |
filter_alpha() { | |
grep -Ev '[^a-z]' | |
} | |
<"$file" filter_green | filter_gray | filter_yellow_letters | filter_yellow_positions | filter_alpha | wc -l 1>&2 | |
<"$file" filter_green | filter_gray | filter_yellow_letters | filter_yellow_positions | filter_alpha | sort |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment