This doesn't handle Yellow result correctly. Specifically, if there is a repeated letter in the guess but that letter appears once in the actual word, then the second occurrence will get a Black instead of a Yellow.
In other words, a Yellow result doesn't just mean that letter occurs somewhere. A Black also doesn't mean the letter occurs nowhere.
There seems to be a lot of confusion and different opinions around how repeated letters should be treated; we really need FIDW (Fédération Internationale de Wordle) to make a definitive ruling.
It depends on how you look at it. Wordle is just an online implementation of the game "Lingo", after all. You could argue that Lingo is a letter implementation of Mastermind.
When building a new word grid game, would you take Wordfeud's rules over Scravble's? I don't think I would.
I see your point. But calling it a "Wordle clone" implies it follows the same rules. If you want to change the rules, call it "inspired by Wordle" or something similar.
I used to have exactly this bug in my revolt Wordle chatbot. It's especially annoying when one of the duplicates is in the correct position but get's marked as BLACK since a previous repeat has been marked YELLOW.
(I don't think this can be classed as correct behavior)
Here is one way to fix it (but it will push you over 50 lines!)
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.
That isn't a bug. In the original if a guess contains a repeated letter and there is only one occurrence of that letter in the target work then the first (on the left) letter will be yellow and the second black.
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.
Slightly off-topic - I've seen wordle become very popular out of nowhere, and haven't been following it. I'm trying to understand how it would be played. Is this basically Lingo (a gameshow on Dutch TV) but for individuals and as an app?
Fellow Dutchman here, who initially wondered the same. Yes, it's Lingo, but:
- 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.
Not that it matters, but the Dutch Lingo is a local version of an originally US/Canadian game show, filmed in Vancouver but aired in the US, hosted by Ronald Reagan's adopted son. I watched far too many game shows as a child.
I did not know this. I had a look, and I'm surprised that the Dutch version is still running where the British version was only just revived, and the rest aren't running at all.
At this point, I'm actively avoiding finding out what it is to see how long I can remain deliberately out of the loop. For example, I didn't know it was a word game until I read your comment.
I think it's something with the `/usr/share/dict/words` file, I made a comment in the gist to update the code to the actual english dictionary words, could you try that?
Perhaps allowing the user to specify a word list, and defaulting to some value would be better than suggesting symlinks.
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.
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.
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?
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:
Yeah it's definitely a historical thing. Bourne shell / POSIX shell doesn't have arrays, and ksh added arrays and bash adopted the same semantics.
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 :)
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.
The repeated letters handling is subtle. If your guess contains repeats of a letter it will highlight as many of them as there are repeats in the actual word. Any that can be green will be green and other repeats will be marked yellow to make up the numbers (going from left to right). Repeats left over after that are black.
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.
I don’t believe it should show yellow like that when you already have the other letters placed/guessed correctly. Should show black again (or white in this version’s case)..
Web 3.0 Wordle clone, complete with a decentralized score ledger, cryptographicly-signed guess registration, highly anticipated WordCoin ITO, exclusive achievement NFTs, and rug-pull. Bonus if its actually all powered by centralized word database running on Digital Ocean.
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.
It may sound logical, but learning many things without going in deep is dangerous. One reason I can think on top of my head is people will abuse and try to use same techniques in every upcoming projects. One of my friend start Kubernetes in digital ocean for simple website is one anecdote i can remember atm.
Why would they do that when they could Rewrite it in Rust®? Given that it’s ~50× as complex as hello world¹, it should only take about 54,800 dependencies (including 30,000 C binding crates), 1.65 terabytes of disk space for the target folder or even just 190 GB after a clean build, and maybe raise a quad-core CPU to 1567.6°C or a 200 core one to 95.
In other words, a Yellow result doesn't just mean that letter occurs somewhere. A Black also doesn't mean the letter occurs nowhere.