# Highlight a Wordle guess

In Wordle, you try to guess a secret word, and some letters in your guess are highlighted to give you hints.

If you guess a letter which matches the letter in the same position in the secret word, the letter will be highlighted green. For example, if the secret word is LEMON and you guess BEACH, then the E will be highlighted green.

If you guess a letter which is present in the secret word, but not in the correct corresponding position, it will be highlighted yellow.

If a letter appears more times in the guess than it does in the secret word, only upto as many occur in the secret may be highlighted. If any of the occurrences are in the same place, they should be preferentially highlighted green, leaving earlier letters unhighlighted if necessary.

For example, with the secret LEMON and the guess SCOOP, the second O will be green, because it is in the right place, but the first O will be unhighlighted, because there is only one O in the secret, and one O has already been highlighted.

Any of the remaining letters in the secret may be highlighted yellow if they match, as long as the right number are highlighted in total. For example, with the secret LEMON and the guess GOOSE, only one of the Os should be highlighted; it does not matter which.

Given two five-letter strings, a secret and a guess, highlight the letters in the guess according to the rules above.

You can "highlight" the letters using any reasonable output format. For example:

• a length-5 list of highlight values
• a list of 5 pairs of (letter, highlight value)
• a mapping from indices 0-4 or 1-5 to the highlight at that position

You can choose any three distinct values to represent unhighlighted, yellow, and green. (For example, 0/1/-1, or ""/"Y"/"G"...)

## Rules

• You may assume the inputs are both of length 5 and contain only ASCII letters
• You may choose whether to accept input in uppercase or lowercase
• You may take input as a string, a list of character codes, or a list of alphabet indices (in $$\ [0, 25] \$$ or $$\ [1, 26] \$$)
• You may use any standard I/O method
• Standard loopholes are forbidden
• This is , so the shortest code in bytes wins

## Test cases


• SCRAP -> $$\ \qW S \qW C \qW R \qW A \qW P \$$
• HELLO -> $$\ \qG H \qG E \qG L \qG L \qG O \$$
• EPOCH -> $$\ \qY E \qW P \qY O \qW C \qY H \$$
• CIVIL -> $$\ \qW C \qW I \qW V \qW I \qY L \$$
• BELCH -> $$\ \qW B \qG E \qG L \qW C \qY H \$$
• ZOOMS -> $$\ \qW Z \qY O \qW O \qW M \qW S \$$ or $$\ \qW Z \qW O \qY O \qW M \qW S \$$
• LLAMA -> $$\ \qY L \qY L \qW A \qW M \qW A \$$
• EERIE -> $$\ \qW E \qG E \qW R \qW I \qW E \$$
• HALAL -> $$\ \qG H \qW A \qG L \qW A \qY L \$$
• LLLXX -> $$\ \qY L \qW L \qG L \qW X \qW X \$$ or $$\ \qW L \qY L \qG L \qW X \qW X \$$
• LLLLL -> $$\ \qW L \qW L \qG L \qG L \qW L \$$

Copy and paste friendly format

• Sandbox Jan 25 at 7:42
• I assume we're allowed to replace the green/yellow values with a distinct value, and keeping the grey values unchanged (which the Retina answer already does for example)? It isn't specifically mentioned, hence the question. Jan 25 at 9:23
• @KevinCruijssen Actually that was probably me not reading the challenge well enough. I'll update my answer.
– Neil
Jan 25 at 9:48
• @KevinCruijssen Yes, it's fine; I class it as "any reasonable format". Jan 25 at 10:04
• @TobySpeight Yes, it is pretty much the same rules as Mastermind (apart from the restriction that it must be a valid English word, but that doesn't matter for this challenge). We have had some Mastermind-related challenges in the past which may interest you: codegolf.stackexchange.com/search?q=mastermind+is:q Jan 29 at 17:49

# BQN, 27 24 bytesSBCS

Returns 0 for white, 1 for yellow and 2 for green.

+⊸×∘≠⊏2∾(≠/⊣)(⊒<≠∘⊣)≠/⊢


Run online!

This is a golfed version of my Judge function from the Wordle solver challenge, with an improvement suggested by Marshall.
There might another approach more suitable for .

This is a tacit function taking the guess on the right and the secret on the left.
≠/⊢ / ≠/⊣ Remove fully correct letters from the guess / secret.
⊒ Progressive indices of the shortened guess inside the shortened secret. Progressive means that no index is output twice and if a value is not available, the length of the vector is returned.
<≠∘⊣ For each index, is this less than the length of the shortened secret?
2∾ Prepend a 2 to this boolean vector.
+⊸×∘≠ 0s at the green positions, positive integers in increasing order at the other positions.
⊏ Index with that into the vector.

The part +⊸×∘≠⊏2∾ is mostly there to invert the ≠/, it would be nice if ≠/⁼ would work instead.

"HELLO" (≠/⊢) "LLLXX"
# "LLXX"
"HELLO" (≠/⊣) "LLLXX"
# "HELO"
"HELO" (⊒) "LLXX"
# ⟨ 2 4 4 4 ⟩
"HELO" (⊒<≠∘⊣) "LLXX"
# ⟨ 1 0 0 0 ⟩
"HELLO" (+⊸×∘≠) "LLLXX"
# ⟨ 1 2 0 3 4 ⟩
1‿2‿0‿3‿4⊏2∾1‿0‿0‿0
# ⟨ 1 0 2 0 0 ⟩


# Perl 5 + -pF, 57 bytes

Returns 2 for green, 1 for yellow and leaves others as they were.

This example pretty prints using ANSI escape codes!

$_=<>;s/./$F[pos]=~s!$&!#!?2:$&/ge;eval's/$F[$-++]/1/;'x5

Try it online!

Initial (implicit via -p) input (the target word) is stored in $_ and split into @F and the guess is then stored in $_ instead. s///ubstitute each letter with: if s///ubstituting $& (the current match) with # is successful, 2, otherwise itself. Then s///ubstitute each index of @F left in $_ (s/// works on $_ by default) with 1. • Wow, that sandbox is cool! Jan 25 at 12:47 • Heh, thanks! It's no ATO but, as time allows, I'm hoping to add in more WASM wrappers for other langs. Ruby and Python already exist and should be easy enough to use. I've wanted to have a proper shareable terminal without using asciinema for a while so figured I should just do it! :) Jan 25 at 12:51 # 05AB1E, 14 bytes øDÆĀ*ø0Kvy®.;  Input as a list of 1-based alphabet indices; modifies the list to change green to 0 and yellow to -1 (grey values remain the same). Explanation: ø # Zip the two (implicit) input-lists together, creating pairs D # Duplicate this list of pairs Æ # Reduce each inner pair by subtracting Ā # Check for each that it's NOT 0 (0 if 0; 1 otherwise) * # Multiply that to the pairs ø # Zip/transpose; swapping rows/columns  # Pop and push both lists separated to the stack 0K # Remove all 0s from the top list v # Foreach y over the remaining values: y®.; # Replace the first y with -1 in the other list # (after which the result is output implicitly)  • @Shaggy "You may take input as a string, a list of character codes, or a list of alphabet indices (in $[0, 25]$ or $[1, 26]$)." Jan 26 at 4:09 • @Shaggy As mentioned by Makonede above, the third rule states this is an allowed input format. And the output format I'm using is allowed in the comments under the challenge. Jan 26 at 7:31 # R, 84 80 bytes function(s,g){e=s!=g;for(i in 1:5)s[x]=g[i]=1+is.na(x<-which(s*e==g[i])[1]);g*e}  Try it online! My golfing skills are quite rusty after a long break, but here it goes anyway. Takes input as a vector of codepoints, outputs 0 for exact match, 1 for inexact match, 2 - for miss (the reverse of what is given in test cases). • R4.1 now supports short-hand notation for functions, i.e. function(s,g) is equivalent to \(s,g). Jan 27 at 15:22 # Retina 0.8.2, 45 bytes +(\w)(.{5})\1 +$2+
+(\w)(.*,.*)\1
-$2- ,.*  Try it online! Link includes test cases. Takes input as two comma-separated words. Matching letters are changed to + and near-misses are changed to -. Explanation: +(\w)(.{5})\1 +$2+


Change all matching letters to +s (in the secret word too, so that it doesn't match later.)

+(\w)(.*,.*)\1
-$2-  Change all near misses to -s. ,.*  Delete the secret word. # Haskell, 112 bytes import Data.List f(x:y,z)=[0^x|elem x z]:f(y,delete x z) f _=[] x?z|x==z=(0,0)|1>0=(x,z) ((f.unzip).).zipWith(?)  Try it online! Takes input as a list of integers on the range $$\[1,26]\$$. Outputs a list of [] for no match [1] for perfect match and [0] for imperfect match. This feels like it could be shorter. Having to import delete is costly. # Python 3, 113 bytes lambda g,w:[g[i]-w[i]and~((g[:i]+[a-b or b for a,b in zip(w,g)][i:]).count(g[i])<w.count(g[i]))for i in range(5)]  Try it online! Uses -1 for gray, -2 for yellow and 0 for green. A further 3 bytes can be saved if -1 is replaced by False and -2 by True, but I dislike this output format, since False==0. Input is a list of charcodes # JavaScript, 76b 72b 69b Solution found by @subzey and me while golfing the MiniWordle project. Thanks to @emanresu for the further improvements // a is the correct word (array of letters) // b is the guessed word (array of letters) a=>b=>b.map((s,i)=>s==a[i]?a[i]=0:s).map(s=>s?a[x=a.indexOf(s)]=~x:1)  Returns an array of 5 digits. 0 = black, 1 = green, anything else = yellow For example: f([..."TEETH"])([..."EERIE"]) == [-3, 1, 0, 0, 0] • The parentheses around a[x=a.indexOf(s)]=~x are unnecessary. Also, if you take input uppercase, you can replace s<"~" with s<{} for -1, and you can take input curried (a=>b=>...) for another -1. Feb 11 at 6:09 • thanks @emanresu! I'm gonna update my answer :) – xem Feb 11 at 15:45 # Charcoal, 33 bytes ⭆θ⎇⁼ι§ηκ+§.-‹№Ｅ…θκ⁻λ§ημι№Ｅη⁻λ§θμι  Try it online! Link is to verbose version of code. Outputs + for exact match, - for near miss and . for mismatch. Explanation:  θ Guessed word ⭆ Map over letters ι Current letter ⁼ Equal to η Secret word § Indexed by κ Current index ⎇ If true then + Literal string + else .- Literal string .- § Indexed by № Count of ι Current letter in θ Guessed word … Truncated to length κ Current index Ｅ Map over letters λ Inner letter ⁻ Remove match of η Secret word § Indexed by μ Inner index ‹ Is less than № Count of ι Current letter in η Secret word Ｅ Map over letters λ Inner letter ⁻ Remove match of θ Guessed word § Indexed by μ Inner index Implicitly print  # JavaScript (Node.js), 63 bytes s=>g=>g.map((u,i)=>s[i]-u&&s.some((v,j)=>g[j]==v|u-v?0:s[j]=1))  Try it online! Input array of code points, Output array of 0 = Green, true = Yellow, false = Unhighlighted. # C (gcc), 125 122 117 bytes #define F for(i=5;i--;)g[i] i;f(s,g,p)char*s,*g,*p;{F==s[i]?s[i]=1,g[i]=2:0;F,(p=index(g,s[i]))?*p=3:0;F>3?g[i]=4:0;}  Try it online! Saved 5 bytes thanks to tsh!!! Inputs a secret and a guess as two strings. Returns the "highlights" as a list of $$\2\$$s, $$\3\$$s, and $$\4\$$s in the second input string. With $$\2\$$ for green, $$\3\$$ for yellow, and $$\4\$$ for unhighlighted. • A quick and dirty hack: #define F for(i=5;i--;)g[i], i;f(s,g,p)char*s,*g,*p;{F==s[i]?s[i]=1,g[i]=2:0;F,(p=index(g,s[i]))?*p=3:0;F>3?g[i]=4:0;} – tsh Jan 26 at 1:38 • @tsh Quick and dirty does it nicely - thanks! :D Jan 26 at 8:13 # JavaScript (Node.js), 78 bytes a=>b=>b.map(y=(x,i)=>x-(c=a[i])&&(y[c]=-~y[c]*2,x)).map((x,i)=>x&&!(y[x]>>=1))  Try it online! Input charcode/[1,26], output true(no), 0(green), false(yellow) # JavaScript (Node.js), 82 bytes a=>b=>b.map(y=(x,i)=>x!=(c=a[i])&&(y[c]=-~y[c],x)).map((x,i)=>x&&~~y[x]&&!!y[x]--)  Try it online! 0(no match), false(green), true(yellow) • @Shaggy You may take input as a string, a list of character codes, or a list of alphabet indices (in [0,25] or [1,26]) – l4m2 Jan 26 at 4:43 • Hi @l4m2, congrats for your 82b answer, I realized it was better than the one I had implemented in my MiniWordle clone, so I used yours and put your name in the project's credits: xem.github.io/MiniWordle Cheers! – xem Feb 10 at 7:55 # Python 3.8 (pre-release), 92 bytes Returns a list of -1 for Green, False for Yellow and True for not highlighted. lambda*r,c='':[-(a==b)or(c:=c+b).count(b)>sum(y!=x==b for x,y in zip(*r))for a,b in zip(*r)]  Try it online! # Jelly, 18 17 bytes o@= çW;œ-\⁻Ɲʋç@+=  Try it online! -1 because there was a completely extraneous ɗ Target on left, guess on right; 0 for gray, 1 for yellow, 2 for green. Absolutely dreadful... There ought to be some sort of =þ-based solution, but I've had no luck yet. o@= Dyadic helper link: mask out exact matches = For each pair of corresponding elements, are they equal? o@ Replace 0s with elements from the left argument, leaving 1s unchanged. çW;œ-\⁻Ɲʋç@+= Main link ç Mask matches out of the target, ç@ mask matches out of the guess, ʋ and with those on the left and right: W; \ Scan across the guess, starting with the masked target, by œ- multiset difference; Ɲ for each pair of adjacent scan results, ⁻ are they not equal? += Add that to the mask of exact matches.  # Julia 1.6, 72 bytes a\b=(* =.==;c=a*b;b[c]=a[c].=0;c-[sum(b[i]b[1:i])>sum(b[i]a) for i=1:5]) Attempt This Online! Fixed and improved version of mbeltagy's answer Needs version 1.6+ for (*) = (.==). 73 bytes in Julia 1.0 Inputs are vectors of characters, and the output is a vector with 1 for green, 0 for yellow, and -1 for uncolored # Vyxalt, 2423 21 bytes Z⁰¹-ḃ*∩÷$£0o(¥nuøḞ£)¥


Try it Online!

or Run all the test cases (it took me way longer to write the code to run the test cases than the program itself lol)

Port of 05AB1E answer. Can probably be golfed down a ton.

-1 byte thanks to Aaroneous Miller

• 23 bytes Apr 19 at 20:59

# Python 2, 95 bytes

lambda g,t:[not a or a in t and t.remove(a)for a in[a[a==b:]or t.remove(a)for a,b in zip(g,t)]]


Try it online!

Loops over the guess twice, while removing characters from the target. Direct matches are removed in the first loop, indirect matches in the second. Requires two lists as input. Outputs a list containing 5 elements: True for direct match, None for indirect match and False for no match.