In my algorithm to compare the secret word with the guessed word, I need to manage the duplicated letters. For example,
if the secret word is newly
and the guessed word is newer
, the output of this should be "GGGWW" (G = green(Correct Place), W = White(The Letter isn't in the secret word)),
but instead my algorithm down below outputs "GGGYW" (Y = Yellow(Letter is in the word but not the right place)).
for (int i = 0; i < 5; i ) {
if (secret.charAt(i) == prop.charAt(i)) {
status[i] = LetterStatus.IN;
} else if (secret.contains(Character.toString(prop.charAt(i)))) {
status[i] = LetterStatus.OK;
} else {
status[i] = LetterStatus.NOTIN;
}
}
return status;
secret = secretword, the array status is an enum of (IN, OK, NOTIN)
, so the letter and prop status is the guessed word.
Any ideas on how to modify this code to solve my problem
CodePudding user response:
You have to take the number of occurrences into account. So, process the exact matches first, recording the letters not found so far. For each other occurrence in the guess, remove the letter from the recorded letters, so that you will not match it again. E.g.
ArrayList<Character> missing = new ArrayList<>();
for(int i = 0; i < 5; i ) {
if(secret.charAt(i) == prop.charAt(i)) {
status[i] = LetterStatus.IN;
}
else missing.add(secret.charAt(i));
}
if(!missing.isEmpty()) {
for(int i = 0; i < 5; i ) {
if(secret.charAt(i) != prop.charAt(i)) {
Object ch = prop.charAt(i); // ensure to use remove(Object) not remove(int)
status[i] = missing.remove(ch)? LetterStatus.OK: LetterStatus.NOTIN;
}
}
}
For large data, you’d use something like a Map<Character,Integer>
to record the number of occurrences for each element, but since we have at most five elements here, using an ArrayList
is simpler while providing reasonable performance. It’s just important to keep in mind that this approach would not scale to other problems.
CodePudding user response:
The simplest seems to be just to override matched letter in a secret every time secret
character matches prop
character and then check for the letters whether they're in or not in the word
for (int i = 0; i < 5; i ) {
if (secret.charAt(i) == prop.charAt(i)) {
status[i] = LetterStatus.IN;
secret = secret.substring(0, i) "-" secret.substring(i 1); // or any other invalid character that will not be provided by user
}
}
for (int i = 0; i < 5; i ) {
if(status[i] == null) {
if (secret.contains(Character.toString(prop.charAt(i)))) {
status[i] = LetterStatus.OK;
} else {
status[i] = LetterStatus.NOTIN;
}
}
}
return status;
There is additional question how would you like to treat repeating characters that are yellow (let's say the user provided newee
- should both e
be yellow or only one) and maybe you'd need to tune up a little bit this code