A Wordle clone in 50 lines of Bash
gist.github.com
gist.github.com
In other words, a Yellow result doesn't just mean that letter occurs somewhere. A Black also doesn't mean the letter occurs nowhere.
remaining="" output=""
for ((i = 0; i < ${#actual}; i++)); do
if [[ "${actual:$i:1}" != "${guess:$i:1}" ]]; then
remaining+=${actual:$i:1}
fi
done
for ((i = 0; i < ${#actual}; i++)); do
if [[ "${actual:$i:1}" != "${guess:$i:1}" ]]; then
if [[ "$remaining" == *"${guess:$i:1}"* ]]; then
output+="\033[30;103m ${guess:$i:1} \033[0m"
remaining=${remaining/"${guess:$i:1}"/}
else
output+="\033[30;107m ${guess:$i:1} \033[0m"
fi
else
output+="\033[30;102m ${guess:$i:1} \033[0m"
fi
done
printf "$output\n"
Explanation:The variable `remaining` tracks the letters of `actual` that can contribute toward yellows.
Then the problem at least would have been isolated to that part and the rest of the system in 100% good shape.
You can see this with today's word by guessing MOTTO. The leftmost T will be yellow and the rightmost will be black.
Similarly, if you guess TENET the initial T is black but the final T is green.
Today's word is ZBVFG (rot13).
When building a new word grid game, would you take Wordfeud's rules over Scravble's? I don't think I would.
( My revolt Wordle server: https://app.revolt.chat/invite/2q3NYtM9 )
- One word every day, same word for the whole world.
- You don't get a start letter
- No ballenbak :-( :-(
- No purpose
Note that as a fellow comment suggested, Lingo itself isn't an original show either. I don't know where the idea originated but certainly not on Dutch TV, so Wordle is simply a new iteration of an old idea. The innovation is in the accessibility and the low-key virality, not the game dynamics.
++ [[ false != true ]]
++ guess_count=1
++ [[ 1 -le 6 ]]
++ echo 'Enter your guess (1 / 6):'
Enter your guess (1 / 6):
++ read guess
fooba
+++ echo fooba
+++ tr '[a-z]' '[A-Z]'
++ guess=FOOBA
[... ÉTUDE =~ FOOBA ]]
++ echo 'Please enter a valid word with 5 letters!'
Please enter a valid word with 5 letters!
++ guess_count=0
++ [[ false != true ]]
++ guess_count=1
++ [[ 1 -le 6 ]]
++ echo 'Enter your guess (1 / 6):'
Enter your guess (1 / 6):
++ read guessEasiest is to check /usr/share/dict with `ls -hal`. Do read the README there, before manually flipping symlinks around, though.
On Tumbleweed, I have no /usr/share/dict/words, but /use/share/dict/american. Allowing the user to set would also be useful if multiple languages are installed, and doesn't change the number of lines of code.
I changed the first line to:
words=$(grep -Ex '\w{5}' "/usr/share/dict/${wordlist:=words}" | tr '[a-z]' '[A-Z]')
so I can invoke it wordlist=american wordle.sh
You can also replace it with $1 (or any other positional parameter): words=$(grep -Ex '\w{5}' "/usr/share/dict/${1:=words}" | tr '[a-z]' '[A-Z]')
And invoke it with wordle.sh american
In either case, it defaults to /usr/share/dict/words if no list is given. Personally I'd go with the first as you use $1 for guesses, and higher numbered parameters get messy.That way people can use downloaded files too.
I wish bash would have a nicer way to address a character in a string though. How hard would it be to use the same syntax as for arrays for it?
By the way, this can be expressed simpler:
guess_count=$(( $guess_count - 1 ))
As ((guess_count--))If guess_count is zero before the post-decrement the statement will have an exit code of 1. If you have set -e in effect this will kill your script. Depending on the circumstances it might be better to use pre-decrement.
(( --guess_count ))Yes it would be nicer if ${s[i]} worked, instead of needing ${s:i:1}. But there's a pretty fundamental reason for that: bash doesn't have dynamic types of strings and arrays like Python or JavaScript.
Instead everything is basically one kind of string-or-array value. Roughly speaking, strings are values with one element, and arrays are values with more than one.
And ${array} is equivalent to ${array[0]}, which is very confusing. Conversely, you can do ${s[0]} on anything you declared to be a string, and you'll get the whole value back.
Rather than having types attached to values, bash has weird "flags" on the LOCATION for a value. And even that's not the whole story! Evaluation of a variable in bash depends on three things:
1. the contents of the "cell" / location
2. the flag on the cell (-a -A)
3. the operation, e.g. echo $x or echo foo > $x
I might make a blog post about this.Oil does it more like Python or JavaScript, which is noted here, but this section could use a lot of elaboration:
https://www.oilshell.org/release/0.9.7/doc/known-differences...
ksh did it in the most "backward compatible" way, with the least amount of work, but which leads to very confusing semantics.
They just "extended" every string so it can have an array part, and then changed a FEW parts of the evaluator, not ALL parts of it. So arrays "decay" to strings in most contexts. They didn't have to touch that code.
It's hard to explain but if you write an interpreter you'll get a feel for this O(M x N) explosion between data types and operations. The amount of work explodes as you add more of either, and shell already has a ton of operations. As mentioned, the evaluation rules for the word $x in 'echo $x' and 'echo foo > $x' are completely different.
There are ways to avoid this, like Python has PyObject and a bunch of protocols. Similarly, Clojure has more protocols than Racket, which the Racket authors have noted -- it works on abstractions and not "concretions". As far as I remember, these come directly from Java interfaces. So yes Java actually adds something to Lisp :)
It may be cheating (I think it is) but its a great moment to hone some of your gnutools skills.
Some tricks (shameless self-promotion, sorry) https://twitter.com/berkes/status/1481222011980550146 and https://twitter.com/berkes/status/1486296116899504131
So for example if the target word is QUEEN and you guess EELER (not an accepted guess but let's pretend it is), it would be yellow, black, black, green, black.
[1] https://sonorouschocolate.com/notes/index.php?title=The_best...
With enough determination, anything can be a one liner in bash. /joke
Needs to be microservice-based, obv. A word finder service, a word checker service and a few others for good measure. Reactive architecture, probably Kafka based, for resilience. Also GDPR compliant, CI/CD pipeline, distributed tracing, all major languages covered, dev, staging and production environments.
Bonus points for Java spring, React and Redux.
A little knowledge is a dangerous thing.
¹ Written in Rust here: https://github.com/mTvare6/hello-world.rs