Skip to content

Instantly share code, notes, and snippets.

@sirhc
Last active January 21, 2022 16:45
Show Gist options
  • Save sirhc/299158b3e3edca0a56576911b8a2b6d3 to your computer and use it in GitHub Desktop.
Save sirhc/299158b3e3edca0a56576911b8a2b6d3 to your computer and use it in GitHub Desktop.
Script to help identify words for Wordle (https://powerlanguage.co.uk/wordle)
#!/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