why is the for loop not running? - javascript

I'm supposed to create a function that will continue to double the first argument until it is greater than or equal to the 2nd argument. Every time it doubles, I add 20 to a counter.
However, for whatever reason, it doesn't seem to be adding 20 to the counter as it always returns 0 and does not print the console.log I included for each loop, which makes me think it's not running the loop.
Why isn't it running the loop and what am I doing wrong?
function bacteriaTime(currentNum, targetNum) {
let counter = 0
for (let i = currentNum; i >= targetNum; i *= 2) {
counter += 20;
console.log('bacteria count is ' + i + ' and ' + counter + ' have passed.')
}
return counter;
console.log(counter);
}

You might wanna check if your condition wasn't already met, and therefore, the code has returned. Also your condition is backwards. It should be: for (let i = currentNum; i <= targetNum; i *= 2) {

Seems like you've mixed up your comparison. In your for loop you had i >= targetNum which with your inputs would almost always be false. Simply switch the operator to <= as below and you should be good. This will mean i is less than targetNum.
function bacteriaTime (currentNum,targetNum){
let counter = 0
for (let i = currentNum; i <= targetNum; i *= 2){
counter += 20;
console.log ('bacteria count is ' + i + ' and ' + counter+ ' have passed.')
}
console.log(counter);
return counter;
}
Hope that works. It was probably just a simple mix up.

Related

How to properly print out list of scores in order from highest to lowest in code.org/javascript?

I have function of "endgame" and here's how the function goes
function endgame() {
setScreen("scorescreen");
ismytimergoing = false;
appendItem(scorelist, score);
for (var i = 0; i < scorelist.length; i++) {
if (scorelist[i] > scorelist[i +1]) {
highestnumber = scorelist[i];
} else if ((scorelist[i] == scorelist[i + 1])) {
highestnumber = scorelist[i];
} else {
highestnumber = scorelist[i + 1];
}
}
setText("scoretext", (scorelist + " ") + namelist);
}
This is a fairly simple click button game and I have a loop which increases the score after each click, different amounts depending on how much the score currently is.
onEvent("clickbutton", "click", function( ) {
setProperty("gamescreen", "background-color", rgb(randomNumber(1, 250), randomNumber(1, 250), randomNumber(1, 250), 0.5));
if (score < 10) {
level = 1;
setText("levelbutton", "level " + level );
score += 1;
setText("scorecounter", "Score = " + score);
changebutton("clickbutton");
changebutton("dontclickbutton");
}
else if ((score >= 10)) {
level = 2;
setText("levelbutton", "level " + level );
score += 2;
setText("scorecounter", "Score = " + score);
changebutton("clickbutton");
changebutton("dontclickbutton");
}
else if ((score >= 50)) {
level = 3;
setText("levelbutton", "level " + level );
score += 3;
setText("scorecounter", "Score = " + score);
changebutton("clickbutton");
changebutton("dontclickbutton");
}
});
The changebutton is a function that changes the background color and text color of whatever "button" is through in the parameter, but that's not the main point here. The function of "Endgame" is what I'm expereincing difficulties with, so here we go. "endgame" is called at least when the wrong button is clicked and when the time runs out, which ever happens during the game. And in my endgame function I have
setText("scoretext", (scorelist + " ") + namelist);
But what is displayed is a whole bunch of numbers, but what I want to be displayed is the list of scores from highest to lowest with the respective names lined up from the namelist. As a side point my start button takes the user input, sets it as a variable called "name" and appends to my namelist. This is an example of the results, I put in meir for name and that displayed ok, but my score was 5 and it showed up as
0,0,0,0,1,2,2,3,3,4,
4,5,5,5 meir
even though the only that should be in my scorelist is 5, so it shouldn't print out all the other stuff. So if I could get any help on to properly sort the scorelist, and have it only print out the scores, and not whole bunch of numbers that would be great, and preferably have it print out the names in order with the scores from highest scoring names to lowest scoring names, that would be great. Thanks in advance.
Someone saw my code and pointed out at least part of the issue. One of the ways the "endgame" function starts is when the time == 0, and I have in my "endgame" function the following.
ismytimergoing = false;
appendItem(scorelist, score);
so I think
ismytimergoing = false;
stops the timer, but that happens when the timer == 0 so the endgame function is keep on happening constantly increasing the scorelist size making it print out a lot of numbers. so I changed the endgame function to be the following.
function endgame() {
setScreen("scorescreen");
ismytimergoing = false;
seconds = 60;
appendItem(scorelist, score);
for (var i = 0; i < scorelist.length; i++) {
if (scorelist[i] > scorelist[i +1]) {
highestnumber = scorelist[i];
} else if ((scorelist[i] == scorelist[i + 1])) {
highestnumber = scorelist[i];
} else {
highestnumber = scorelist[i + 1];
}
}
setText("scoretext", (scorelist + " ") + namelist);
}
I changed the endgame function, so now even if it happens because of the timer turning to zero, the seconds are reset and it's only run once, thus making the scorelist a much easier thing to deal with.

is ++ = +1 in JavaScript?

Why when I use the following codes in JS it works properly ?:
let counter = 5;
while (counter < 10) {
console.log(counter);
counter ++;
}
But when I try the following codes it doesn't?
let counter = 5;
while (counter < 10) {
console.log(counter);
counter + 1;
}
You're missing an assignment there.
counter++ directly increases the counter itself by one.
counter + 1 just returns the value of counter plus one.
Solutions might be:
counter += 1;
counter = counter + 1;
This happens because on the second example, you are summing 1 to counter value, but it's not using this sum to nothing.
Let me exemplify:
let c = 0;
console.log(c + 1); // outputs 1
console.log(c); outputs 0, since in the last statement you didn't changed the original value, just used it.
console.log(c++); // will output c then increment c. So it prints the old value: 0
console log(c); will output 1 (result of previous increment)
console.log(++c); // will increment c and then output it new value: 2
Keep in mind that
c++;
Is the same that:
c = c + 1
The increment operator will increment a value and return a value that differs depending on whether it is used in a prefix or postfix position.
In postfix position it returns the original value:
let x = 0
console.log(x++) // 0 (!!)
console.log(x) // 1
In prefix position it returns the new value:
let x = 0
console.log(++x) // 1
console.log(x) // 1
You can type it out long hand if you want, using the addition and assignment operators separately:
let x = 0
console.log(x = x + 1) // 1
console.log(x) // 1
There is another operator too: the addition assignment operator:
let x = 0
console.log(x += 1) // 1
console.log(x) // 1

JS - Prevent long loop javascript from "crash" browser implementation

I have a long loop that takes maybe 10 mins or more, and I want to set always a new time to avoid it to continue. But it dosen't works.
function problem3(){
var img = document.getElementById('p_3');
img.style.display = img.style.display === 'block' ? 'none' : 'block';
var number=600851475143;
var t = new Date();
for(var i=3;i*i<=number;i+=2){
if(isPrime(i) && number%i==0){
var maxPrime = i;
}
setInterval(function(){time(t)},5000);
}
document.getElementById("p3").innerHTML = 'Il più grande divisiore primo di <span>'+number+"</span> è <span>" + maxPrime+"</span>";
}
function time(t){
return console.log(Date() - t);
}
If I put console.log(Date() - t);in the problem3() function it works, but I can't do Date()-t every 5 seconds, something like setInterval(Date()-t,5000)
This is a case where you might consider using the workers API. Instead of freezing the browser, let the job be done in the background and call back to the main thread when it's done.
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
JavaScript is not multithreaded. So we think of setInterval() as running a piece of code every n ms (5000 in your example). But that's not quite true. If there's already script running when the interval elapses, the best that can happen is the bit of code gets added to a queue to be executed - but nothing from that queue is going to run until the already-running script finishes.
So in rough terms that's why it's not working, but what to do? Well, if you want anything to happen before problem3() returns, then problem3() is going to have to make it happen in a synchronous way.
For example, you could create a lastOutputTime variable, initialize it to the current time, and on each iteration through the for loop compare the current time to the stored value. If 5 seconds have passed, output to console and update lastOutputTime.
Your algorithm should be improved to something like this:
function maxPrimeFactor(number) {
if (number == 0 || !Number.isInteger(number) ||
number > Number.MAX_SAFE_INTEGER) return NaN;
number = Math.abs(number);
while(number % 2 == 0) number /= 2;
for (var i = 3; i * i <= number; i += 2) {
while(number % i == 0) number /= i;
}
return number;
}
var number = 600851475143;
console.log('maxPrimeFactor(' + number + ') == ' + maxPrimeFactor(number));
If for some numbers you need too much time, then break the loop into smaller chunks and asynchronize. But never use setInterval for this, and especially never use setInterval inside a long loop. setInterval schedules some task to run every n milliseconds, so if you use it in a loop, after i iterations, the task will run i every n milliseconds! And setInterval is so problematic because it can freeze the browser if the task takes more than n milliseconds. You should use setTimeout instead.
However, this would be useless in this case. The algorithm above can detect that 304250263527209 (15 digits) is a prime almost instantly. Given that the maximum safe integer is 9007199254740991 (16 digits), I don't think you will have problems for any number.
If you say the algorithm takes so long, it may be because you are trying it with bigger numbers. But be aware JS numbers are 64-bit floating point numbers, and thus integers can't be represented accurately above Number.MAX_SAFE_INTEGER. You will get a wrong result anyways, so do not even try to calculate that.
In the case of the Project Euler #551, a brute-force approach would be
function sumOfDigits(n) {
var sum = 0;
while(n != 0) {
sum += n % 10;
n = Math.floor(n/10);
}
return sum;
}
function sumDigitsSeq(n) {
return new Promise(function(resolve) {
var i = 1;
var chunkSize = 1e5;
var sum = 1;
(function chunk() {
chunkSize = Math.min(chunkSize, n-i);
for (var j=0; j<chunkSize; ++j, ++i) {
sum += sumOfDigits(sum);
}
if (i >= n) return resolve(sum);
console.log('Please wait. sumDigitsSeq(' + i + ') == ' + sum);
setTimeout(chunk, 60);
})();
});
}
var number = 1e6;
sumDigitsSeq(number).then(function(result) {
console.log('Done! sumDigitsSeq(' + number + ') == ' + result);
});
Of course brute-force is not the appropriate way to solve the problem.

Using Recursion for Additive Persistence

I'm trying to solve a Coderbyte challenge, and I'm still trying to fully understand recursion.
Here's the problem: Using the JavaScript language, have the function AdditivePersistence(num) take the num parameter being passed which will always be a positive integer and return its additive persistence which is the number of times you must add the digits in num until you reach a single digit. For example: if num is 2718 then your program should return 2 because 2 + 7 + 1 + 8 = 18 and 1 + 8 = 9 and you stop at 9.
Here's the solution I put into jsfiddle.net to try out:
function AdditivePersistence(num) {
var count=0;
var sum=0;
var x = num.toString().split('');
for(var i=0; i<x.length; i++) {
sum += parseInt(x[i]);
}
if(sum.length == 1) {
return sum;
}
else {
return AdditivePersistence(sum);
}
}
alert(AdditivePersistence(19));
It tells me that there's too much recursion. Is there another "else" I could put that would basically just re-run the function until the sum was one digit?
One of the problems is that your if statement will never evaluate as 'true'. The reason being is that the sum variable is holding a number, and numbers don't have a length function. Also, as 'Barmar' pointed out, you haven't incremented the count variable, and neither are you returning the count variable.
Here's a solution that works using recursion.
function AdditivePersistence(num) {
var result = recursive(String(num).split('').reduce(function(x,y){return parseInt(x) + parseInt(y)}), 1);
function recursive(n, count){
c = count;
if(n < 10)return c;
else{
count += 1
return recursive(String(n).split('').reduce(function(x,y){return parseInt(x) + parseInt(y)}), count)
}
}
return num < 10 ? 0 : result
}
To fix the 'too much recursion problem',
if(sum.toString().length == 1)
However, as the others have said, your implementation does not return the Additive Persistence. Use James Farrell's answer to solve the Coderbyte challenge.

Having problems understanding the result mixing "For loops" and "array" (beginner)

I'm currently studying javascript and I don't understand the result based on a specific condition. Thanks for you patience with newbies like myself ;)
In the following case, I don't understand why the last line "blue" is displayed since the condition is "show only when counter > 0".
var table = ['blue','yellow','orange','red'];
for (var counter = table.length ; counter > 0 ; counter--)
{
document.write(table[counter-1] + "<br>")
}
Another way to see the result would be :
var table = ['blue','yellow','orange','red'];
document.write(table[table.length-1] + '<br>'); // result: table[3] "red"
document.write(table[table.length-2] + '<br>'); // result: table[2] "orange"
document.write(table[table.length-3] + '<br>'); // result: table[1] "yellow"
document.write(table[table.length-4] + '<br>'); // result: table[0] "blue" = should not be displayed if we have the condition 'counter > 0'
Thanks for your help!
Because you are using -
var table = ['blue','yellow','orange','red'];
for (var counter = table.length ; counter > 0 ; counter--)
{
document.write(table[counter-1] + "<br>") //when table has 4 item, counter = 1, counter > 0, table[counter - 1] = table[0]
}
In other words, your code perfectly prints all. If you wish to skip the last one do this -
var table = ['blue','yellow','orange','red'];
for (var counter = table.length - 1; counter > 0 ; counter--)
{
document.write(table[counter] + "<br>")
}
In the below line:
document.write(table[counter-1] + "<br>"), you are decrementing the counter by 1. It will not validate the condition here.
Use this counter - 1 > 0
It is because inside your loop, you are using table[counter-1].
Counter never reaches 0 but you take away 1 from it, which makes it access the zero'th element of table
In JavaScript arrays are initiate in index 0. In your conditional you do loop from length array until 1 "counter >0" but when you print the array item you get counter-1, if counter is equal 1 you will get array index 0.

Categories