Why are these two codes in javascript different from each other? This is the first code:
var string = "I am 21 years old. My number is 0799340540"
string += " and I am 19. My number is 0786432560";
var validate = /\d+/g;
var result;
while ((result = validate.exec(string)) != "null") {
document.write(result[0] + "<br>");
}
and this is the second code
var string = "I am 21 years old. My number is 0799340540"
string += " and I am 19. My number is 0786432560";
var validate = /\d+/g;
var result = validate.exec(string);
// while (result != "null") {
// document.write(result[0] + "<br>");
//}
// the commented lines will create an infinite loop
As was stated in some of the comments, the difference essentially comes down to the fact that in the first code snippet, the regular expression is continuously evaluated until it reaches the end of the string, in the second one, it is evaluated once. What this results in your example is that the first one will execute the code in the while loop 4 times, then exit. Whereas the second one will be stuck in an infinite loop. For instance:
while((result = validate.exec(string)) != null){
document.write(result[0] + "<br>");
}
WIll execute validate.exec() for every iteration if the loop, each time it searches the string from where it left off, untill it finally finishes the search and returns null, at this point the while condition is false and therefore it exits the loop.
Now in this code:
var result = validate.exec(string);
while(result != null){
document.write(result[0] + "<br>");
}
validate.exec() is only executed once in the first line, and it returns an array containing information about the search. it is not null. So when your while loop runs, in every iteration of the loop it checks if result != null, and since nowhere in the loop are you updating the value of result, it will never change and so result != null will always evaluate to true, thereby never exiting the loop.
UPDATE
As was pointed out, you also need to correctly check for null, instead of comparing to the string value of "null", you need to compare to the primitive value of null. Updated the snippets above to reflect this.
Related
So i ran the code about 50 times and each time it returned olg / 1 so What is wrong
alert("welcome to word unscrambler undscramble this")
console.log("i am not a distraction")
document.write("i am not a distraction either")
var r = ["pttoao","recme","logd","teey","olg"]
var g=Math.floor(Math.random() *+ 6);
if (g=="0") {select =("pttoao")}
else if(g=="1"){select=("recme")}
else if (g==2){select="logd"}
else if(g==3){select="dre"}
else if(g==4){select="olg"}
if(select=="pttoao"){realword="potato"}
if(select=="recme"){realword="creme"}
if(select=="logd"){realword="gold"}
if(select=="teey"){realword="yeet"}
if(select="olg"){realword="log"}
var awnser= prompt("unscramble "+select)
if(awnser==realword){alert("correct")
}else{
alert("incorrect")}
maybe it is that it cant randomly select words
Here's some code that works for any amount of words.
Notice the structure: array of objects, objects have the real word and the scramble of it.
The random is relative to the amount of words.
I've combined the prompt, the check, and the alert into one line.
"Simplify by complication..." :)
var words=[
{real:"potato", scrambled:"pttoao"},
{real:"creme", scrambled:"recme"},
{real:"gold", scrambled:"logd"},
{real:"yeet", scrambled:"teey"},
{real:"log", scrambled:"olg"}
];
var random=Math.floor(Math.random()*words.length);
alert(
prompt("Unscramble: "+words[random].scrambled)
==
words[random].real?
"Correct":
"Wrong"
);
var g=Math.floor(Math.random() *+ 6 )
should be replaced with following as array elements index starts from
zero and array "r" contains 5 elements
var g=Math.floor(Math.random() * 5);
if(select="olg"){realword="log"}
here, you have assigned "olg" value to select variable. Inside "if" condition assignment is simply returning assigned value which is "olg" that makes it true and executes realword="log"
It should be replaced with
if(select=="olg"){realword="log"}
Hello I'm trying to understand recursion in JavaScript.
So far I have:
function countVowels(string) {
let vowelCount = 0;
// if we're not at the end of the string,
// and if the character in the string is a vowel
if (string.length - 1 >= 0 && charAt(string.length -1) === "aeiouAEIOU") {
//increase vowel count every time we iterate
countVowels(vowelCount++);
}
return vowelCount;
}
First of all, this is giving me issues because charAt is not defined. How else can I say "the character at the current index" while iterating?
I can't use a for-loop - I have to use recursion.
Second of all, am I using recursion correctly here?
countVowels(vowelCount++);
I'm trying to increase the vowel count every time the function is called.
Thanks for your guidance.
If you're interested, here is a version that does not keep track of the index or count, which might illuminate more about how the recursion can be done.
function countVowels(string) {
if (!string.length) return 0;
return (
"aeiou".includes(string.charAt(0).toLowerCase()) +
countVowels(string.substr(1))
);
}
console.log(countVowels("")); // 0
console.log(countVowels("abcde")); // 2
console.log(countVowels("eee")); // 3
// Note that:
console.log('"hello".substr(1)', "hello".substr(1)) // ello
console.log('"hello".charAt(0)', "hello".charAt(0)) // h
console.log('"aeiou".includes("a")', "aeiou".includes("a")) // true
console.log('"a".includes("aeiou")', "a".includes("aeiou")) // false
Our base case is that the string is empty, so we return 0.
Otherwise, we check if the first character in the string is a vowel (true == 1 and false == 0 in javascript) and sum that with counting the next (smaller by one) string.
You are making two mistakes:
You should have three parameters string , count(count of vowels) and current index i.
You should use includes() instead of comparing character with "aeiouAEIOU"
function countVowels(string,count= 0,i=0) {
if(!string[i]) return count
if("aeiou".includes(string[i].toLowerCase())) count++;
return countVowels(string,count,i+1);
}
console.log(countVowels("abcde")) //2
As asked by OP in comments "Can you please explain why it'sif("aeiou".includes(string[i].toLowerCase())) instead of if(string[i].includes("aeiou".toLowerCase()))"
So first we should know what includes does. includes() checks for string if it includes a certain substring passed to it or not. The string on which the method will be used it will be larger string and the value passed to includes() be smaller one.
Wrong one.
"a".includes('aeiou') //checking if 'aeiou' is present in string "a" //false
Correct one.
"aeiou".includes('a') //checking if 'a' is present in string "aeiou" //true
One possible solution would be:
function countVowels(string, number) {
if (!string) return number;
return countVowels(string.slice(1), 'aeiouAEIOU'.includes(string[0])? number + 1 : number);
}
// tests
console.log('abc --> ' + countVowels('abc', 0));
console.log('noor --> ' + countVowels('noor', 0));
console.log('hi --> ' + countVowels('hi', 0));
console.log('xyz --> ' + countVowels('xyz', 0));
and you should call your function like: countVowels('abc', 0)
Notes about your solution:
you always reset vowelCount inside your function, this usually does not work with recursion.
you defined your function to accept a string, but recall it with an integer in countVowels(vowelCount++); this it will misbehave.
always remember that you have to define your base case first thing in your recursion function, to make sure that you will stop sometime and not generate an infinite loop.
Alternative ES6 solution using regex and slice() method. Regex test() method will return true for vowels and as stated in a previous answer JavaScript considers true + true === 2.
const countVowels = str => {
return !str.length ? 0 : /[aeiou]/i.test(str[0]) + countVowels(str.slice(1));
}
Ask user for a number. Determine if the number is even or odd. I have my constants set and using modulo to figure this out. However I am stuck in an infinite loop and can't figure out why. I have my if statement in the loop as well as a break statement to get out, but still in an infinite loop.
HAVE TO USE A WHILE LOOP
// declare constants
const MODULO = 2;
const EVEN = 0;
const ODD = 1;
// declare variables
var enteredNumber;
var result;
// prompt user to enter an even number
enteredNumber = prompt("Enter an even number: ");
// convert user input into a number
enteredNumber = Number(enteredNumber);
// determine result of modulo equation
result = enteredNumber % MODULO;
// while loop to check if enteredNumber is even or odd
while (result === EVEN) {
document.write(enteredNumber + " is an even number <br/>");
enteredNumber = prompt("Enter an even number: ");
enteredNumber = Number(enteredNumber);
result = enteredNumber % MODULO;
if (result === ODD) {
document.write(enteredNumber + " isn't an even number");
break;
}
}
You can essentially one-liner this thing. You're already checking stuff with the while.
document.addEventListener('DOMContentLoaded', () => {
while (!(parseInt(window.prompt('Enter an even number', '2') || '1', 10) % 2)) { };
});
Why this works
Javascript has 'falsy' and 'truthy' values.
window.prompt('Enter an even number', '2')
This code prompts the user for a number. The result is a string (or null, if the user blanks out the prompt).
<a string or null> || '1'
If the user blanked out the prompt, it will return null. In Javascript we can use the or operator to choose between two things. null || '1' reads from left to right. The first thing is falsy so it chooses '1'.
If the user entered a number (like 10), we would get the number they entered as a string.
Then we parse the string to a number with parseInt.
Take that result and use the modulo operator % to divide by the operand and return the remainder. When you divide by 2 the remainder will either be 0 or 1. These are falsy/truthy values.
while(0) evaluates to false and breaks the loop. while(1) evaluates to true and continues the loop.
When I call a recursive on function, where do the results of the call go?
function reverse(str){
if (str.length == 1){
return str;
}
rev = reverse(str.substr(1)) + str.charAt(0);
}
reverse("String");
console.log(rev); // ----> "undefinedS" - Only the last call is saved.
If I just return the value it seems fine. Where is the result getting stored?
function reverse(str){
if (str.length == 1){
return str
}
return reverse(str.substr(1)) + str.charAt(0);
}
reverse("String") // ----> "gnirtS"
Your first version
rev is stored in the global namespace, and is overwritten each time the function reverse is called.
The recursion stops when the string's length is one, after having taken only the last n-1 characters. As a result, the final character is the only character in the string, S, and that is what str.charAt(0) gives.
Since the function reverse does not return a value when str is length 0 (which is what happens with "S".substr(1)) the value of reverse(str.substr(1)) is undefined.
This results in undefinedS.
Your second version
This version creates a call stack whereby the string is slowly taken apart by n-1 (where n is its length) until its length is 1. At that point the stack is unwound, causing each letter from the last to the first to be returned. Each function call as its own Execution context, whereby a Variable Environment is holding the value of each string.
The result of the callstack unwinding is gnirtS.
Cleaner Look code
function reverse(str){
return (str.length == 1)? str : reverse(str.substr(1)) + str.charAt(0);
}
Essentially what this function is supposed to do is take a list of words from input text and set it on a display at a client-chosen interval (WPM) from a drop-down menu.
If a word passed in the function contains a question mark, period, colon, semi-colon, exclamation point or comma, then it is removed, and the chosen interval is doubled. For example, if the delay between words was 117 ms, it would then be 234 ms.
I'm having the most trouble working out the part where you determine whether or not the passed word contains punctuation and removing it.
I'm getting an error:
Uncaught Type Error: Cannot read property 'indexOf' of undefined.
I'm not sure why this is happening since list[index++] is a String and indexOf is a method of Strings in Javascript and not a property.
I'm also not sure how I would implement the delay. Given that I've used setInterval() in this way (and I can only use setInterval for the purposes of this) I'm not sure how I would get it to set the String in the display twice while also including the delay.
function runDisplay(data, id) {
var reader = document.getElementById(id);
var index = 0;
if (timer) {
clearInterval(timer);
}
if (data.length) {
timer = setInterval(function() {
var punctuation = [".", ",", ":", ";", "!", "?"];
var textSpeed = 117; // default
for (var j = 0; j < punctuation.length; j++) {
// remove punctuation if found and double text delay
// if multiple found, remove only one
if (!(data[index++].indexOf(punctuation[j]) === -1)) {
data[index++] = string.replace(punctuation[j], '');
// set data[index++] to display twice to double delay?
}
}
reader.innerHTML = data[index++];
index = index % data.length;
}, textSpeed);
}
}
I'm getting an error: Uncaught Type Error: Cannot read property
'indexOf' of undefined.
I'm not sure why this is happening since list[index++] is a String and
indexOf is a method of Strings in Javascript and not a property.
First, methods are also properties of objects.
Second, the JS engine is telling you that you're calling indexOf on something undefined, so it's not a string. And data[index++] is undefined because index is probably not an index inside the range of the dataarray.
The main problem of the function is that if data is a word array, you don't iterate correctly on it. Here you're incrementing indexeach time you're reading the array, index should be incremented only once for each display.
I'm also not sure how I would implement the delay. Given that I've
used setInterval() in this way (and I can only use setInterval for the
purposes of this) I'm not sure how I would get it to set the String in
the display twice while also including the delay.
If the function has to display all the words in a infinite loop (that's the purpose of index = index % data.length, right ?), clearInterval and another setInterval could be called inside the anonymous function passed to the current setInterval, allowing to compute the textSpeed you want.
index++ will increase index variable every time it is called and you are calling it twice in your loop body.
In if (!(data[index++].indexOf(punctuation[j]) === -1)) {index is lets say i and in data[index++] = string.replace(punctuation[j], ''); it's i+1.
The code is messy but I hope that's what you wanted ...kind of:
var str = "some text with no punctuation. And some;: text. with, punctuation? symbols!!? to print"
var print = function(str) {
var re = /([^ .,:;!?]+)|([.,:;!?]+)/gi
var reSkip = /[.,:;!?]+/gi //remove + to add delay for each punctuation symbol instead of the group of symbols
var substrs = str.match(re)
var delay = 117
var timeToPrint = new Date().getTime() + delay
var i = 0
console.log(substrs.length)
var printWord = function() {
console.log(substrs[i])
if ( new Date().getTime() < timeToPrint ) {
console.log(new Date().getTime() +'<'+timeToPrint)
requestAnimationFrame(printWord)
return
}
if ( reSkip.test(substrs[i]) ) {
i++
timeToPrint += delay*5 //to make delay more obvious
console.log('skip punctuation')
requestAnimationFrame(printWord)
return
}
document.write(substrs[i++] + ' ') //replace this with your code to print where you want
timeToPrint += delay
console.log('written')
if (i < substrs.length)
requestAnimationFrame(printWord)
}
printWord()
}
print(str)
Just paste it to chrome console to test.