0

I'm building a word game. One of the functions I need is a function that receives a word and replaces several words with (_) and gives the incomplete word as output. I want the number of words to be replaced and the location of those words to be chosen randomly. The code I wrote, although it uses for, is only able to replace one word. What changes should I make in the for part of the code that has the ability to move several words? for example : "laptop" => "l_pt_p"

    function wordToIncomplete(word) {
    let randomNumber = Math.floor(Math.random() * 3) + 1
    let _randomNumber = Math.floor(Math.random() * word.length)
    let _word = ""; 
    
    for (let index = 0; index < randomNumber; index++) {
        
        _word = word.replace(word[_randomNumber], '_');
        
    }
    return _word 
   }
4
  • Each time through the loop you're doing the replacement on the original word, not the result of the previous replacement. You should do word = word.replace(...) Commented Mar 26, 2022 at 9:05
  • 3
    It's really confusing that you have two variables with almost identical names: randomNumber and _randomNumber. Give them names that describe what they're used for. Commented Mar 26, 2022 at 9:07
  • dont quiet understand... if you pass in an "aaaaa", the function will returns "_____". is this what you want?.. and what's the loop for? Commented Mar 26, 2022 at 9:08
  • "I want the number of words to be replaced /.../ for example : 'laptop' => 'l_pt_p'" - did you mean letters or actually words? What I quoted contradict each other. Commented Mar 26, 2022 at 10:17

4 Answers 4

1

Yes, as @Barmar mentioned, naming is important.


What changes should I make in the for part of the code that has the ability to move several words

The problem here is that _randomNumber is always same during the loop.

function wordToIncomplete(word) {
  const randomNumberOfCharactersToBeReplaced =
    Math.floor(Math.random() * word.length) + 1;

  let result = word;
  for (let i = 0; i < randomNumberOfCharactersToBeReplaced; i++) {
    // suppose we don't care about whether the character is already replaced or not.
    const randomIndexToBeReplaced = Math.floor(Math.random() * word.length);

    result[randomIndexToBeReplaced] = "_";
  }
  return result;
}
Sign up to request clarification or add additional context in comments.

2 Comments

And what is "second"? If you start your answer with "First, ..." I expect more aspects to be addressed in the subsequent text.
I modified the answer. I'm not good at English sorry...
1

I think your problem is you did not put your _randomNumber in the loop to re-generate your removed character index

function wordToIncomplete(word) {
  let randomNumber = Math.floor(Math.random() * 3) + 1
  let _word = word;

  for (let index = 0; index < randomNumber; index++) {
    let _randomNumber = Math.floor(Math.random() * _word.length)
    _word = _word.replace(_word[_randomNumber], '_');

  }
  return _word
}

const testingWords = "testing words"
console.log(wordToIncomplete(testingWords))

But with this solution, I think it will encounter another problem that it may check the same character which is already replaced earlier

Therefore, I modified your code a bit with while loop

function wordToIncomplete(word) {
  let randomNumber = Math.floor(Math.random() * 3) + 1
  let _word = word;

  let index = 0;
  while (index < randomNumber) {
    let _randomNumber = Math.floor(Math.random() * _word.length)
    if (_word[_randomNumber] === '_') { // we don't need to replace the checked words
      continue;
    }
    _word = _word.replace(_word[_randomNumber], '_');
    index++;
  }
  return _word
}

const testingWords = "testing words"
console.log(wordToIncomplete(testingWords))

By the way, you also did not assign value for _word, so I changed it to

let _word = word

1 Comment

Could you check it again? I tried it here and modified my answer a bit jsfiddle.net/6gnh17a3 @mehrankhalili
1

The example returns an array of letters which is easier to work with, but if for some reason you want a string, do the following to the last line:

return chars.join('');

Note: this example actually adjusts dynamically the number of letters to be replaced which is from 30% to 60% of word.length.

Details are commented in example below

// Utility function
const log = data => console.log(JSON.stringify(data));

// Random integer range function
const randRng = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;

const fragWord = word => {
  /*
  The result of the following expressions is a random number that's 
  within the range of 30% to 60% of total length of >word<
  >word< string is converted into an array of letters called >chars<
  */
  const size = word.length;
  const lo = Math.ceil(0.3 * size);
  const hi = Math.ceil(0.6 * size);
  let qty = randRng(lo, hi);
  let chars = word.split('');

  /*
  At each iteration of >chars< a random index number is generated. 
  If there's a '_' at that index, the current iteration is skipped
  and qty increases by 1 to compensate.
  Otherwise the letter at that index is replaced with a '_'
  */
  skip:
    for (let i = 0; i < qty; i++) {
      let index = randRng(0, size - 1);
      let char = chars.at(index);
      if (char === '_') {
        qty = qty + 1;
        continue skip;
      }
      chars[index] = '_';
    }
  return chars;
};

log(fragWord('fragment'));
log(fragWord('appearance'));
log(fragWord('institutionalization'));
log(fragWord('institutionalization'));

Comments

0

Here is my take on it:

function shfl(array) { // Durstenfeld shuffle, based on Fisher-Yates
  for (let i = array.length - 1; i > 0; i--) {
   const j = Math.floor(Math.random() * (i + 1));
   [array[i],array[j]]=[array[j],array[i]];
  }
  return array;
}
function getWd(word) {
  const n=~~(Math.random()*3)+1, // 1...3
   wa=word.split(""), // word as char-array
   pos=shfl(wa.map((_,i)=>i))     
      .slice(0,n); // 1...3 character positions to be replaced by _
  pos.forEach(p=>wa[p]="_")
  return wa.join("");
}

console.log(
 "And here comes my supercalifragilisticexpialidocious word I want to process".split(" ")
 .map(getWd).join(" ")
);

I use the Durstenfeld shuffle to pick out random character positions of each word.

In getWd() I split the word into an array wa. This array is then the base for finding 1..3 positions (pos) to be replaced by _. After replacing the positions I join("") the characters in wa again and return them as the changed word.

Another expression I'd like to explain is

~~(Math.random()*3)+1

The ~ operator ("bitwise negation") will implicitly convert any number into an integer (similar to Math.floor()). By applying it twice (~~) the actual bitwise negation will be reversed and the result is thus a shorthand for Math.floor().

3 Comments

I liked this solution the best, but you didn't really explain the code so I wont upvote it.
I hope the explanations and comments in my code are sufficient now.
Yeah, it's great. Well done. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.