Point out errors in a JavaScript Loop - javascript

What's wrong with this function? I want to add 1 to c_count until it reaches 100
<script type="text/javascript"> var result = cMat(0); function cMat (c_count) { var limit = 100; match = 1; while (c_count != limit) c_count ++ match; if (c_count == 95) { c_count = 10; } } return (c_count) } </script>

I want to add 1 to c_count until it reaches 100
You're resetting c_count to 10 every time it reaches the value of 95, so it's never reaching your limit. Your match variable doesn't seem to be used, so it can be removed. One thing to check is where the value of c_count is in relation to 100. If it's greater than 100, you need to decrement the value instead of incrementing it.
var result = cMat(0);
function cMat (c_count) {
var limit = 100;
while (c_count != limit)
if(c_count < limit) {
c_count++;
} else { // Implied that it's greater than the limit at this point
c_count--;
}
}
return c_count;
}

Related

Add a number from right to left in the decimal value using javascript

I have an input field where by default I will have $0.00.
when I enter a number, say 1, the input should show $0.01,
again if I enter 2, the input should show $0.12
simultaneously if I press 3, 4, 5, the final output should be $123.45.
Now, If I click delete, it should remove 5, so output will be $123.4
again if I click delete it should remove 4, so output will be $123
If I add a number 2 again here, it should show, $123.2
Is it possible? I am stuck at the last 3 steps.
I have this so far,
let previousTip = 0;
const addingFunction = (value) => {
if(Number(value) <= Number(previousTip)) return Number(value).toFixed(2);
const addNumberRightToLeft = (baseValue, updatedValue) => ((baseValue * 10) + (updatedValue / 100)).toFixed(2);
previousTip = addNumberRightToLeft((Number(previousTip) || 0), value.length > 1 ? value.slice(-1) : value);
return previousTip;
}
my onClick event has
const tipString = addingFunction(e?.target?.value?.trim()?.replace(/[^\d.]/g, '') || '');
Any help will be really appreciated
Here are two functions that should do what you need. You can call the correct one depending on which key is pressed on onKeyPressed
I'm currently not able to test this, but the logic is there.
function addValueToNumber(number,value){
count = 0;
while (number%10 != 0){
number *= 10;
count ++;
}
number += value/10;
for (i=0,i<count-1,i++){
number /= 10;
}
}
function remove(number){
count = 0;
while (number%10 != 0){
number *= 10;
count ++;
}
number = number//10;
for (i=0,i<count-1,i++){
number /= 10;
}
}

NaN in the context of a recursive for loop

I am trying to understand a solution I found for a problem: "You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin."
My question is, if I run the function with change(3,[2]), why does it spit out 0. I am having trouble with comprehending how after a single recursive call currentCoin becomes undefined, and then when the program reaches the for loop in that call, it doesn't call the change function again with total += change(amount - 0 * undefined, coins.slice(0, -1)). Why does it not crash with either an infinite recursive call with change(NaN,[]) or coins.slice(0,-1) being used on an empty array. It seems to ignore that on the for loop.
Am I misunderstanding how a for-loop works?
var change = function(amount, coins) {
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1];
let total = 0;
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
}
return total;
};
console.log(change(3,[2]))
There are a couple things going on here.
First is the behavior of coins[coins.length - 1]. In Javascript, when you access an element of a list at an index that doesn't exist in that list, the indexer will return undefined instead of crashing with an IndexOutOfBoundsException or the like.
Second is qty * currentCoin <= amount. In the case that currentCoin is undefined (due to the above), qty * currentCoin will be NaN. In Javascript, any comparison of NaN with another number will return false by design. (e.g. NaN <= anything is false).
Put this all together and you see that, on the first recursion, the coins array will be empty which makes currentCoin NaN. This causes qty * currentCoin <= currentAmount to be false, which causes the loop to short circuit (so slice never gets called on an empty list). Since the loop never executes, total will still be 0, which is what gets returned. This continues until qty * currentCoin <= amount becomes true in the outermost recursion, and that loop exits with total still equalling 0 (since it only ever added 0).
If you intersperse console.log calls in strategic places about the function, it becomes clearer what is happening:
var change = function(amount, coins) {
console.log(amount, coins);
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1];
console.log(':', currentCoin, amount);
let total = 0;
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
console.log('=', total);
}
console.log('recdone');
return total;
};
console.log(change(3,[2]))
not crash because a NaN in comparison with a number is every false...
NaN < number or NaN > number and so on produce false... so the
qty * currentCoin <= amount
is evaluate false and will exit from the for.
So, if you need to check the NaN you must before the for
let totalCoin = qty * currentCoin;
let check = isNaN(totalCoin);
if(check) {
// return you sentinel value;
}
var change = function(amount, coins) {
if(amount == 0) return 1;
let currentCoin = coins[coins.length - 1]; // firstpass 1-1 = 0, second pas 0-1=-1 => coins[-1] = undefined
let total = 0;
// this will 0*0<=3, second pass 0*undefined => null which is false hence never execute
for(let qty = 0; qty * currentCoin <= amount; qty++){
total += change(amount - qty * currentCoin, coins.slice(0, -1))
}
return total;
};
console.log(change(3,[2]))
In second pass when coins.length = 0 then
let currentCoin = coins[0 - 1]; // = undefined
Later in for loop you will 0 * undefined ( qty * currentCoin) which results NaN which is Not a number
There is no need for recursion in this case. One can use a bottom-up dynamic programming approach. Let ways[i] denote the number of ways to get to i dollars with the given coins and coins[i] represent the value of the ith coin. Then, ways[i] is the sum of all ways[i - coins[j]] for all j from 1 to the number of coins.
var change = function(amount, coins) {
const ways = Array(amount + 1);
ways[0] = 1;
for(const coin of coins){
for(let i = coin; i <= amount; i++){
ways[i] = (ways[i] ?? 0) + ways[i - coin] ?? 0;
}
}
return ways[amount];
};
console.log(change(5,[1,2,3,4,5]))

Is there a minimum possible size change in CSS?

I wrote some JavaScript code to animate CSS properties of elements. I pass the following arguments to the function: amount, interval, and duration; amount being the change in the property (for example 200 could mean add 200 pixels to the element's width), interval being the time between two consecutive changes, and duration being the total duration of the animation.
The code works fine unless I pass the arguments in a way that the change in each interval becomes very small (like a tiny fraction of a pixel).
I know the code is working fine theoretically, as I get the change in console.
Any ideas about the problem?
Cheers.
UPDATE: the code:
function handleTimer (amount, interval, duration, execute, element) {
let i = 0;
let current = 0;
let stepsCount = countSteps(interval, duration);
let stepLength = calcStepLength(stepsCount, amount);
let count = setTimeout(function addOneMore () {
if ( i < stepsCount -1 ){
i++;
current += stepLength;
execute(stepLength, element);
if (current < amount) {
count = setTimeout(addOneMore, interval)
}
} else {
current = amount;
execute(amount - (stepsCount -1) * stepLength, element);
}
}, interval)
}
function countSteps (interval, duration) {
let remainder = duration % interval;
let stepsCount;
if (remainder) {
stepsCount = Math.floor(duration / interval) + 1;
} else {
stepsCount = duration / interval;
}
return stepsCount;
}
function calcStepLength(stepsCount, amount) {
return amount / stepsCount;
}
function resizeWidth (amount, element) {
let widthSTR = $(element).css('width');
let width = parseInt( widthSTR.substr( 0 , widthSTR.length - 2 ) );
$(element).css('width', `${width + amount}px`);
}
So this:
handleTimer(218, 5, 200, resizeWidth, '.box');
works fine, but this:
handleTimer(218, 5, 2000, resizeWidth, '.box');
doesn't.
UPDATE 2:
I know browsers are super accurate with pixels, like when you use percentages. Of course the value will be rounded before rendering since displays cant display half pixels, but the value is still calculated accurately.
I don't know at what decimal the rounding occurs.
This happens because parseInt is rounding your number up.
Pay attention to this line:
let width = parseInt( widthSTR.substr( 0 , widthSTR.length - 2 ) );
if width is a decimal number, like 22.5px, it will be rounded up to 22.
If amount is less than 1, it won't reach 23 and when you round up the number again, you'll get 22 again and it becomes a loop.
You have two solutions:
Use another variable to save the width value, avoiding to writing and reading it from CSS:
let initialWidth = $(element).css('width');
let savedWidth = widthSTR.substr(0, initialWidth, initialWidth.length - 2 ) );
function resizeWidth (amount, element) {
savedWidth += amount;
$(element).css('width', `${savedWidth}px`);
}
Just use parseFloat in place of parseInt to don't round your number up:
let width = parseFloat( widthSTR.substr( 0 , widthSTR.length - 2 ) );

IF statements, Arrays and functions - Javascript

For a task I must create a function that generates a number between 1 and 9. This function needs to be called 100 times. Then I need to create a 9 element array that will keep count of the number of times each number appears. My code is below. Currently a number is being generated and the array changes. However the array doesn't change correctly, it changes the wrong index and I don't know why, can anyone help? Any advice on how to call the function 100 times as well would be appreciated. It doesn't matter how it works or looks, I don't need to have a set format.
Thanks in advance!
<script>
function numberGenerate () {
var nmbrGen = Math.floor(Math.random()*8 +1) ;
return nmbrGen;
}
function numberChange () {
document.write(numberGenerate(), "<br>");
var numberArray = [0,0,0,0,0,0,0,0,0];
if (numberGenerate() == 1){
numberArray[0]++;
}
else if (numberGenerate() == 2) {
numberArray[1]++;
}
else if (numberGenerate() == 3) {
numberArray[2]++;
}
else if (numberGenerate() == 4) {
numberArray[3]++;
}
else if (numberGenerate() == 5) {
numberArray[4]++;
}
else if (numberGenerate() == 6) {
numberArray[5]++;
}
else if (numberGenerate() == 7) {
numberArray[6]++;
}
else if (numberGenerate() == 8) {
numberArray[7]++;
}
else {numberArray[8]++;}
document.write(numberArray);
}
</script>
</head>
You call numberGenerate() in each if statement what means that it will generate a new number every if statement. Your code would work if you generate the number one time and compare it, something like that:
var nRand = numberGenerate();
if (nRand ==...
It is needless to say that your code is not well written (to say it in a harmless way). You could just replace all of your if statements with the following:
numberArray[nRand - 1]++;
And to run it 100 times:
for (var i = 0; i < 100; i++) {
var nRand = numberGenerate();
console.log('run ' + (i+1) + ': ' + nRand);
numberArray[nRand - 1]++;
}
You get the wrong index because you are assigning 1 to 0, 2 to 1 and so on. Try this:
var numberArray = [0,0,0,0,0,0,0,0,0,0];
var times = 100; // Run this 100 times
for(var i = 0; i < times; ++i) {
number = numberGenerate();
if(number < numberArray.length) { //Checks, just to be sure
numberArray[number]++;
}
}
PS: with your random function you will get numbers from 1 to 8 both included, but never 9. I'm not sure if that was your intention. This would fix it:
function numberGenerate () {
return Math.floor(Math.random() * 9 + 1);
}
Try this:
function numberGenerate () {
var nmbrGen = Math.floor(Math.random()*9 +1) ;
return nmbrGen;
}
function randomGenerationStats(howManyTimes) {
var stats = {};
for(var i = 0; i < howManyTimes; i++) {
var randomNumber = numberGenerate();
if(stats[randomNumber]) {
++stats[randomNumber];
} else {
stats[randomNumber] = 1;
}
}
return stats;
}
console.log(randomGenerationStats(100));
Prints:
Object {1: 14, 2: 13, 3: 11, 4: 8, 5: 12, 6: 18, 7: 6, 8: 5, 9: 14}
The output in console will be object whch keys are numbers from 1-9 with values how many times they occurred.
Hm.. I'll ad my answer
Your Math.random is false, check out : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Math/random
A for loop will let you repeat instruction for a counted number of time. See : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for (You can also check a while loop if you don't know the number of occurence you gonna pass)
Using this approch, numberArray[0] will give the occurence of 1.
You don't need to call a function which call Math.random, it's pointless if you aren't doing it in a dynamic way.
Hope this help, even if some answer do the tricks.
var numberArray = [0,0,0,0,0,0,0,0,0];
var nmbrGen;
for(var i=0; i<100; i++) { // From 0 to 99, so 100 time.
nmbrGen = Math.floor(Math.random() * 9 + 1); // 9 + 1 = (Max - Min + 1 + Min)
console.log("Generated : "+nmbrGen);
numberArray[nmbrGen-1]++;
}
Firstly, there's a bug in your numberGenerate function. It will only produce numbers from 1 to 8. What you need to do is change the corresponding line to Math.floor(9 * Math.random() + 1).
Secondly, every successive call to numberGenerate creates a new random number. Call the function once and store the value once per loop iteration. So, you must insert a line like var rand = numberGenerate(); at the top of the numberChange function, and replace every call to numberGenerate following with rand.
Thirdly, notice a pattern with the number in your if conditions and the statement underneath. The number in the condition is from 0-8, and the number in the statement beneath is one more than it. You can simply all of that into one statement after realizing this pattern by replacing all the if statements with this single line numberArray[rand - 1]++.
And lastly, you forgot the most important part! You need to iterate 100 times! Include a for loop surrounding the code in the numberChange function.
After you've made all these changes, the code should resemble this.
function numberGenerate () {
return Math.floor(9 * Math.random() + 1);
}
function numberChange () {
var numberArray = [0, 0, 0, 0, 0, 0, 0, 0, 0];
for(var i = 0; i < 100; i++) {
var rand = numberGenerate();
document.write(rand, "<br>");
numberArray[rand - 1]++;
}
document.write(numberArray);
}
If I understood you right, you want to count the occurrences of these 9 random numbers?
It is easier if you use an associative array (dictionary) for this.
You have a function that generates random numbers between 1 and 9.
I have created an associative array with 9 keys (from 1 to 9), and set the respective value to 0. That value is the "occurrence counter".
Then we loop through 100 times, as you requested and change the counter of that value. Something like this:
function numberChange() {
// read this array as "value 1 has 0 occurrences, value 2 has 0 occurrences, etc."
var numberArray = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9:0 }
for (var i = 0; i < 100; i++) {
// generate 100 random numbers and add the relative counter value.
var newRandomNumber = numberGenerate();
numberArray[newRandomNumber]++;
}
// loop through all keys and display the respective occurrence counter value.
for (var key in numberArray) {
console.log("Number: " + key + " Occurrences: " + numberArray[key]);
}
}
function numberGenerate() {
var nmbrGen = Math.floor(Math.random() * 9 + 1);
return nmbrGen;
}

Javascript countdown then count-up from a prompted variable?

Please Help! I'm new to Javascript, so there's probably an easier solution to this. Basically, I need it to prompt for a number and then count down from that number to zero. Once it reaches zero, I need it to count-up and stop at the same prompted number.
I got it to count down at first, then I completely butchered it, I have no clue what to do.
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var counter = setInterval(timer, 1000);
console.log(startNum);
function timer() {
startNum--; // reduce number by 1
console.log(startNum);
if (startNum <= 0) {
clearInterval(counter);
}
}
var counter = setInterval(timer2, 1000);
var endNum = 0
function timer2() {
console.log(endNum)
endNum++; // add number by 1
console.log(endNum);
if (endNum >= startNum) {
clearInterval(counter);
}
}
</script>
You've got a couple issues here. the first one was pointed out by Rob in the comments. You're running both functions at the same time.
The other issue you have is that you're never storing the number. You're just subtracting and adding to nothing essentially.
So -
<script type="text/javascript">
// get number from user
var startNum = parseInt(prompt("Input a number to start counting down from.",""));
var currentNum = startNum;
var counter = setInterval(timer, 1000);
function timer() {
console.log(currentNum);
currentNum -= 1; // reduce number by 1
console.log(currentNum);
if (currentNum == 0) {
clearInterval(counter);
counter = setInterval(timer2, 1000);
}
}
function timer2() {
console.log(currentNum)
currentNum += 1; // add number by 1
console.log(currentNum);
if (currentNum == startNum) {
clearInterval(counter);
}
}
</script>
Something like this should do the trick. Basically creating another variable to hold your start number and consider that the current number and the value that is going to change.
here's a fiddle - http://jsfiddle.net/w5FM6/
cheers

Categories