while loop terminating early with nested if statement - javascript

I'm writing a condition check for a simple input via prompt() in JavaScript. The idea is to repeat a prompt until the user supplies a positive integer.
In particular, if I submit a negative integer, it correctly prompts me again via case 3. However, if I answer the second prompt again with a negative integer, the code unexpectedly leaves the while loop.
In the if statement:
Case 1: checks if the user 'cancels' the prompt box (or returns an empty string), in which case I set a variable 'cancelGridCreation' to 'true' to later cancel the encapsulating process (outside of the included code), and then terminate the while loop by setting the variable 'waitingForQualifyingAnswer' to 'false'.
Case 2: checks if the response is an acceptable integer (number, integer, positive), and sets the conditional variable 'false' to terminate the while loop.
Case 3: prompts the user again, with the idea that the newly entered data will be checked again by the same 3 'if' cases.
User inputs matching cases 1 and 2 seem to work fine. However, as mentioned above, entering a negative integer 2 times terminates the while loop. See the console output that I received, entering -10 and then -20. As well, the console.log() outputs don't seem to occur in an order matching their location in the code (perhaps a processing time-lag issue?). You'll see that the console.log() from case 3 outputs before the "initial size entered" console.log(), which is coded before the while loop even starts.
Similar results seem to occur whenever case 3 is followed by another case 3 (regardless whether input is negative integers, decimals, or strings), as well as case 3 followed by case 1 (of course, here case 1 would terminate the loop, but the console log statements still seem to occur out of order).
Link to interactive code at JSBin: https://jsbin.com/koheku/1/edit?js,console
JavaScript Code:
let cancelGridCreation = false;
let waitingForQualifyingAnswer = true;
let answer = prompt('Please enter the number of rows/columns, as a positive integer:', '16');
let gridSize = parseFloat(answer, 10);
console.log('initial size entered: ' + gridSize);
while (waitingForQualifyingAnswer === true) {
console.log('top of while loop');
if (answer == null || answer == "") {
console.log('prompt - canceled');
cancelGridCreation = true;
waitingForQualifyingAnswer = false;
} else if (typeof gridSize === 'number' && gridSize % 1 === 0 && gridSize > 0) {
console.log('prompt - good answer: ' + gridSize);
waitingForQualifyingAnswer = false;
} else {
console.log('prompt - BAD answer: ' + gridSize);
answer = prompt('Incorrect format entered. Please enter the number of rows/columns, as a positive integer:', '16');
gridSize = parseFloat(answer, 10);
console.log('new size entered: ' + gridSize);
}
console.log('end of while loop');
}
console.log('done:');
console.log(gridSize);
Console Output was as follows (having entered -10 at the first prompt, and -20 at the second prompt):
"prompt - BAD answer: -10"
"top of while loop"
"initial size entered: -10"
"new size entered: -20"
"end of while loop"
"done:"
-20
I'm pretty new, and realize there may be more concise ways to accomplish this. I'm interested in suggestions, however, I"m also keen to figure out why the while loop is ending when only case 3 inputs are being submitted.
Please note: The console.log() statements are only of a simple means of debugging. I realize a parseInt() would truncate any decimals, but I chose to allow integers as an acceptable size.
Thank you for any advice you can offer :)

Related

Finding a valid substring

I am a bit puzzled by one exercise I recently came across with.
It seems like an easy task and I've put my solution but it turned out it didn't pass all the tests :D
In the example, I've found two example substrings:
Input: S = "(()("
Output: 2
Explanation: The longest valid
substring is "()". Length = 2.
and
Input: S = "()(())("
Output: 6
Explanation: The longest valid
substring is "()(())". Length = 6.
at the first glance, everything is clear.
I came up with my solution:
class Solution {
findMaxLen(s) {
if (!s || !s.length) throw new Error('Invalid input value provided')
let openIndex = null
let closingIndex = null
for (let i = 0; i < s.length; i++) {
if (s[i] == '(' && !openIndex) openIndex = i + 1
if (s[i] == ')') closingIndex = i + 1
}
if(!closingIndex || !openIndex) throw new Error('Invalid substring')
return closingIndex - openIndex + 1
}
}
So, my solution should solve the issue of trying to find The longest substring with the opening and closing parentheses.
But it failed the test with an input value: (((()
Where the correct answer is 2 and my output is 5
Is this (((() different from ()(())( one provided in the example?
I suppose I do not wholly understand the idea of what the substring is or something...
This pseudocode should work. Some bugs or edge cases might have loose ends as I just wrote this here on the fly. Feel free to test it and point out the misses.
helper_stack = null
max_valid_len = 0
running_len = 0
for i=0 to input_s.length:
if helper_stack.length == 0:
if input_s[i] == ')':
running_len = 0
continue
else:
helper_stack.push('(')
else:
if input_s[i] == '(':
helper_stack.push('(')
else:
helper_stack.pop()
running_len += 2
if running_len > max_valid_len:
max_valid_len = running_len
EDIT: Explanation
With your logic, you are not keeping track of order of opening and closing of brackets, which is important. If a closing bracket precedes open, string becomes invaid by default. Hence, using stack makes sense here.
If ever we encounter a closing bracket before open, we restart from that point. Hence, we set the running_len = 0. For every encounter of closing bracket, if an open bracket is there to balance it, we just pop it off, and since its a pair (of chars, when we consider length of string), running_len += 2 is done.
With little modification, we can even reproduce max_valid_substring if needed. However, in our case, we could even use just an integer instead of helper_stack. For every push('(') operation, just do var += 1, and var -= 1 for pop and that should also do the trick. Note that here, we are not explicitly using stack, but this is still conceptually LIFO = last in first out which is basically, stack.

In school and trying to create the classic guess a number game. What did I do wrong?

This code is supposed to be a guess the number game. The object is to get JS to display an alert box that asks the user to guess a number. When they guess a number, the code is supposed to return the values of what they have guessed until they get it correct.
When I run the play key, an alert box does pop up, and says:
"Enter a guess between 1 and 100"
After that, even if I enter all 100 numbers, the box re-loads forever.
Here's what I have:
const game = {
title: 'Guess the Number!',
biggestNum: 100,
smallestNum: 1,
playerChoice: null,
secretNum: null,
//1. Add a prevGuesses property to the game object initialized to an empty array.
prevGuesses: [],
//2. Add a getGuess method to game that prompts the player to enter a guess with a message formatted as: Enter a guess between [smallestNum] and [biggestNum]: Hint- Use a template literal for the prompt message.
//3. Ensure that the getGuess method returns a value that is:
//-is a number, not a string
// -is between smallestNum and biggestNum, inclusive
// -Hints: This is a great use case for a while loop. parseInt returns NaN if the string cannot be parsed into a number
getGuess: function() {
while (this.playerChoice !== this.secretNum) {
var playerChoice = prompt(`Enter a guess between ${this.smallestNum} and ${this.biggestNum}: `);
var wholeNumber = parseInt(this.playerChoice);
if (this.wholeNumber > this.biggestNum) {
var wholeNumber = 100;
}
if (this.wholeNumber < this.smallestNum) {
var wholeNumber = 1;
}
if (typeof this.wholeNumber !== "number")) {
var wholeNumber = Math.floor(Math.random() * 100)
}
}
},
//4. From within the play method, invoke the getGuess method and add the new guess to the prevGuesses array
play: function() {
this.secretNum = Math.floor(Math.random() *
(this.biggestNum - this.smallestNum + 1)) + this.smallestNum;
game.getGuess();
this.prevGuesses.push(this.wholeNumber);
//6 the play method should end(return) when the guess matches the secretNum
if (typeof(this.wholeNumber) === "number" && this.wholeNumber !== this.secretNum) {
game.render();
}
},
// 5. Add a render method to game that play will call after a guess has been made that alerts:
// -if the secret has been guessed: "Congrats! you guessed the number in [x] guesses!"
// otherwise
// -"Your guess is too [high|low]"
// "Previous guesses: x, x, x, x"
// Hints: render wont be able to access any of play's local variables, e.g., guess, so be sure to pass render any arguments as needed. Template literals not only have interpolation, they honor whitespace - including line breaks! The list of previous guesses can be generated using the array join method.
render: function() {
if (this.wholeNumber === secretNum) {
alert(`Congrats! You guessed the number in ${game.prevGuesses.length} guesses!
Previous guesses: ${prevGuesses}`);
} else if (this.wholeNumber > this.secretNum) {
alert(`Your guess is too high!
Previous guesses: ${this.prevGuesses}`);
game.guess();
} else if (this.wholeNumber < this.secretNum) {
alert(`Your guess is too low!
Previous guesses: ${this.prevGuesses}`);
game.guess();
}
}
};
game.play();
/*
Allow the player to continually be prompted to enter their guess of what the secret number is until they guess correctly
If the player has an incorrect guess, display an alert message that informs the player:
Whether their guess is too high, or too low, and...
A list of all the previously guessed numbers (without showing the square brackets of an array)
If the player has guessed the secret number:
Display an alert message that congrats the player and informs them of how many guesses they took
End the game play*/
/*
Bonus: when play is run, immediately prompt the player to enter the smallest and biggest numbers instead of having them pre-set*/
The research that I've done: I've googled as many pages as I could find and youtube tutorials on functions, play object, loops within arrays, anything that I could think of that's related to the types of objects in this code.
the comment text is from the assignment. While I was working on it, I put the comments next to the code that I was working on.
I really am only a few weeks into coding and appreciate any feedback.
This is the original code that I was provided:
const game = {
title: 'Guess the Number!',
biggestNum: 100,
smallestNum: 1,
secretNum: null,
play: function() {
this.secretNum = Math.floor(Math.random() *
(this.biggestNum - this.smallestNum + 1)) + this.smallestNum;
}
};
There are several issues with your code:
this.wholeNumber never receives a value, so that will not work. Also, it does not seem the purpose of this exercise to have such a property. You should not have to store the user's guess in a new property this.wholeNumber. See next point:
The goal of getGuess is to return a number, but there is no return statement. You seem to want to store the number in a property, but that is not the assignment.
Related to this: in play you should get the guessed number as a return value from the call to getGuess
The goal of getGuess is not to wait for the user to guess right, only for the user to make a valid guess (within range and not NaN). So the condition of your while loop is not correct.
getGuess does not verify that parseInt returned NaN. Note that the type of NaN is "number", so the last if's condition will never be true. You should use the isNaN function, or better Number.isNaN.
play should always call render, not only when the guess is right.
render should be called by passing it an argument (the guessed number), and thus the render method should define a parameter for it.
The render method should not call game.guess(). That is not its job.
The play method should not put a new value in secret, otherwise the user will be playing against a moving target :) The secret should be set once in the main program
The main program -- where you currently just have game.play() -- should have the looping logic, which you had tried to implement elsewhere. Here is where you should repeat calling game.play() until the guess is right. It is also here where you should display alert messages about guesses that are too low, too high, ...etc.
There is no clear instruction where the main program should get the latest guess from. It can get it from game.prevGuesses, but I would suggest that the play method also returns the latest guess, just like getGuess should do.
Take note of the other instructions that are given in comments for the main program. For instance, when the user has guessed right you should alert after how many attempts they got it right. Think of which property can help you to know this number of attempts. Hint: length.
I will not provide the corrected code here, as I think with the above points you have enough material to bring this exercise to a good end. Happy coding.
Use parentheses to invoke the play function.
game.play();

How do you compare two variables in Javascript?

I am trying to compare two different variables with each other and execute certain code if they match.
The variables are: userInput and commandOne
Firstly, a button is pressed to call myTest().
function myTest() {
userInput = document.getElementById("runBox").value;
testInput();
}
The function gathers text from an input box on my page and stores it in a variable named userInput. It then calls my next function...
function testInput() {
if (userInput = commandOne) {
document.getElementById("demo").innerHTML += "<br>executed!";
}else {
alert("this is an alert message");
}
}
This part is designed to test if userInput matches the variable named commandOne. (commandOne's value is currently set to "ip").
If it does match, it will add text (executed!) to a paragraph with the "demo" ID. If it does not match, it will alert the user in an alert box.
My problem is that the variables do not seem to be comparing. No matter what the user puts into userInput the text (executed!) is always outputted to my paragraph. It appears that the browser thinks they are matching when they are not.
You missed your operator in the if statement.
if (userInput == commandOne)
== compares value
if (userInput === commandOne)
=== compares values and data types.
You had used the wrong operator. You must use == sign instead of a single = sign.
function testInput() {
if (userInput == commandOne) {
document.getElementById("demo").innerHTML += "<br />executed!";
} else {
alert("This is an alert message");
}
}
A single = sign (=) means that the value on the left side of the sign gets the same value as on the right side of the sign.
Double= sign (==) means that two values on the each side of the sign are equal.
Triple = sign (===) means that both the values are equal and of the same type.
Click here for more information.
As mentioned - you have the wrong operator - however i just wanted to show an alternative to the logic: - the ternary operator - makes it much nicer and cleaner to read and reduces the if / else markup.
Incidentally - given the code provided - you don't even need to call teh second function - the entire thing can be done in one function. Also - if the alert is purely to demonstrate the "else" outcome - you should investigae the use of the console.log() - its bettter for debugging.
To explain the ternary operator - the condition to be met is written first (note that there is no "if" preceding it. Following it - use the "?" charcter to give an action if hte comparison is true and use a ":" character for if the outcome is false.
Note that I always write the ternary operators on the three lines as i have done here - I find it easier to read - it can all be written on one line - personal preference.
And last thing - no ";" at the end of the "true" portion of the statemtn - it is all one expression that I happen to have written over three lines.
function testInput() {
userInput == commandOne
? document.getElementById("demo").innerHTML += "<br>executed!"
: alert("this is an alert message");
}

Javascript Random Guess Game

https://jsfiddle.net/andrew_jsfiddle/eyLyqajz/1/
Assignment 1 - Using your JSFiddle account you are going to create a guessing game, only it will be the computer doing the guessing. Here is how it works - the computer will ask you for a number between 1 and 1000, it will check first to make sure your input is within the bounds.
Once you enter the number it will guess the number and do a comparison with the number you entered. It will output the results of the guess and continue to do this until it gets the correct answer. This is what the output of the program will look like (if I enter 329)
For this attempt I did:
var guessnum= new Guessnum(1000);
document.getElementById("click").onclick= function() {
guesslist()};
function guesslist() {
document.getElementById('guessnum').innerHTML= InsertGuess();
}
function InsertGuess() {
for (var a= 0; a < guessnum.length; a++){
guessnum[a] = Math.floor((Math.random() * 1000) + 1);
}
var show_guess="";
for (i=0; i < guessnum.length; i++){
show_array += "You guess" + guessnum[i] + "of " + i + "<br>";
}
return document.getElementById('guess').innerHTML=show_array;
}
Use a listener on the input with a global variable that contains the random number
var myRandomNumber;
input.addEventListener('input', function(){
}
)
You'll need to click first on the button though.
Fiddle
My friend, I think you are really confused. It wouldn't help to just create it for you. Break down the requirements to actionable steps and start from scratch. You want to create a guess game that you set a number. Think it as simply as possible:
Action 1 - Set a number -->
Create the field
Action 2 - Check if number is valid(1-1000) -->
Get the value entered and make the necessary checks
Action 3 - Computer tries to guess by selecting a num up to 1000 -->
Generate random num from 1-1000
Action 4 - Compare number with the one you set before -->
Simple comparison of generated number and the selected one
Action 5 - Proceed as needed -->
If it's the exact number it won and it will stop!
If it's higher then the next guesses should have this number as highest limit.
If it's lower then the next guesses should have this number as lowest limit.
Action 6 - Show guess and result of comparison --> Simply show the results of the previous actions
Action 7 - If not successful guess --> repeat until the number is guessed
Try to apply this kind of logic to all these problems.

JavaScript: an if statement is changing outcomes of a random generator?

Basically I'm creating a program similar to a blackjack program where two cards are dealt according to a random number generator, with the possibility of the same card being dealt twice at the same time (i.e. two Queen of hearts showing up at once) and I want to create a counter of how many times that event occurs, but when I implement an if statement, it affects the outcome so that the two cards are ALWAYS the exact same...can someone tell me what I'm doing wrong here? The code is as follows:
function dealHand() {
var randomCardOne = Math.floor ((Math.random() *13) +2);
var randomCardTwo = Math.floor ((Math.random() *13) +2);
if (randomCardOne = randomCardTwo) {identicalCards()};
}
var identicalPairs = 0;
function identicalCards(){
document.getElementById("identical").value=++identicalPairs;
}
You are assigning the value of one card to another
if (randomCardOne = randomCardTwo) {identicalCards()};
should be
if (randomCardOne == randomCardTwo) {identicalCards()};
In the first case you are simply evaluating if randomCardOne is "truthy" after being asigned the value of randomCardTwo.
Consider if you might want to use === instead of == since
2 == '2' // yields true
2 === '2' // yields false
It's not an issue in this case but it might be in others so it's good to be aware of this. I try to stick with === since it is more strict.
You're using =, that's an assignment operator in JavaScript. You should be using ==
e.g.
if (randomCardOne == randomCardTwo) {identicalCards()};

Categories

Resources