Search code examples
javascriptalgorithmwordle-game

Can i make this code more efficient / shorter to run?


So Im pretty new to javascript and coding in general. Im making a Wordle algorithm just for fun to build my skills in coding. and while making this algorithm i realized that i was going to have to kind of recreate Wordle. so i looked online for wordle recreations in java script, and all the ones I found I saw one flaw that I didn't want to have.

The flaw that I saw was in the IF statement for checking a letter in the wordle answer. Specifically when the letter is in the word but not in the right spot. The recreations that i saw had an IF statement that looked something like this.

IF (answerWord.includes(guessLetter[i])) {
        guessLetter[i] = color.(yellow)
}

(this isnt exactly how they wrote it, but its the main idea)

My main focus is on the .includes. This would not work because say our guess word is "agree" and the answer word "ready". the 2 E's in "agree" would be yellow, and we dont want that because their is is only 1 E in "ready. So we only want the first E in "agree" to be yellow and not the second E.

So i decided to figure it out on my own, and i was able to come up with this and it works. At least Im pretty sure it works, base on the the many words i tested it on.

So my question is, since Im making an algorithm im going to be making alot of calculations, is this the most efficient i could write this or can i make it better?

let guessWord = "agree"; // the first word thats inputed
let answerWord = "ready"; // the answer to the wordle

/* 
  'letterCheck' is an array that tells what condition each letter in 'startLetter' is, based on the answer word
    2 = the letter is in the word and in the correct place (GREEN)
    1 = the letter is in the word but not in the correct place (YELLOW)
    0 = the letter in not in the word (GREY)
*/
var letterCheck = ["0", "0", "0", "0", "0"];
var guessLetter = ["A", "A", "A", "A", "A"]; // the separated letters of 'startword' in a array
var answerLetter = ["A", "A", "A", "A", "A"]; // the separated letters of 'answord' in a array

//adds the start word and the answer world to the arrays
for (var i = 0; i < 5; i++) {
  guessLetter[i] = guessWord.substring(i, i + 1);
  answerLetter[i] = answerWord.substring(i, i + 1);
}

console.log(guessLetter);
console.log(letterCheck);
console.log(answerLetter);

//this loops goes though every letter one by one 
for (var i = 0; i < 5; i++) {
  //checks if the letter is in the right spot
  if (guessLetter[i] == answerLetter[i]) {
    letterCheck[i] = "2";
    console.log(guessLetter[i]);
    console.log(letterCheck);
  } else if (answerWord.includes(guessLetter[i])) {
    //checks if there is more than one letter in start word or its the first letter
    if (guessWord.split(guessLetter[i]).length - 1 == 1 || i == 0) {
      letterCheck[i] = "1";
      console.log(guessLetter[i]);
      console.log(letterCheck);
      //checks if the the amount of same letters in start words is equel to the amount of same letters in answer word
    } else if (guessWord.split(guessLetter[i]).length - 1 == answerWord.split(guessLetter[i]).length - 1) {
      letterCheck[i] = "1";
      console.log(guessLetter[i]);
      console.log(letterCheck);
      //opposite of above
    } else if (guessWord.split(guessLetter[i]).length - 1 != answerWord.split(guessLetter[i]).length - 1) {
      letterCheck[i] = "1";
      console.log(guessLetter[i]);
      console.log(letterCheck);
      // checks if any of the letters infront of it are the same as it
      for (var j = 0; j < i; j++) {
        if (guessLetter[i] == guessLetter[j]) {
          letterCheck[i] = "0";
          console.log(guessLetter[i]);
          console.log(letterCheck);
        }
      }
    }
  } else {
    letterCheck[i] = "0";
    console.log(guessLetter[i]);
    console.log(letterCheck);
  }
}
console.log(guessLetter);
console.log(letterCheck);
console.log(answerLetter);
( I will remove the console.log's later they just helped my to debug.)

Sorry if my code might be confusing, im not the best at keeping my code clean. if you have any confusion or questions, I'll try my best in clear up any confusion.


Solution

  • To get all of the states (in precedence order: correct, wrong-position, incorrect), you should check in that precedence order, and remove letters from contention once the state in that letter's position has been set.

    function check(guess, targetWord) {
        const checkStates = new Array(5).fill("incorrect");
        const letters = guess.split('');
        const targetLetters = targetWord.split('');
        for (let i=0; i<5; i++) {
          if (targetLetters[i] === letters[i]) {
            checkStates[i] = "correct";
            targetLetters[i] = '';
            letters[i] = '';
          }
        }
        for (let i=0; i<5; i++) {
          if (!letters[i]) continue;
          let fi = targetLetters.findIndex(t => t===letters[i]);
          if (fi > -1) {
            checkStates[i] = "contains";
            targetLetters[fi] = '';
          }
        }
        return checkStates;
    }
    
    let solution = "ready"
    console.log(`solution is ${solution}`);
    
    let guess = "agree";
    console.log(`checking ${guess}... ${check(guess, solution)}`);
    
    guess = "roars";
    console.log(`checking ${guess}... ${check(guess, solution)}`);
    
    guess = "boars";
    console.log(`checking ${guess}... ${check(guess, solution)}`);
    
    solution = "beast"
    console.log(`\nsolution is ${solution}`);
    
    guess = "treat";
    console.log(`checking ${guess}... ${check(guess, solution)}`);