Why does repeat function not work the second time? - javascript

The challenge is to return an array that follows an arrow pattern when given a number. For example:
arrow(3) ➞ [">", ">>", ">>>", ">>", ">"]
I have almost completed it but it repeats the middle value in the array twice.
function arrow(n) {
var arr = [];
var num = 1;
while(num <= n) {
arr.push(">".repeat(num));
num++;
}
while(num > 0) {
arr.push(">".repeat(num - 1));
num--;
}
return arr;
}
console.log(arrow(3));
So then I changed it to this (for the second repeat I changed it to num - 2 but it says an error).
function arrow(n) {
var arr = [];
var num = 1;
while(num <= n) {
arr.push(">".repeat(num));
num++;
}
while(num > 0) {
arr.push(">".repeat(num - 2));
num--;
}
return arr;
}
console.log(arrow(3));
Can someone explain to me why this doesn't work?

Your function does not work because you start the second loop when num is equal to n + 1 (which causes the middle value to be added twice) and do not end the loop until num is 0 (which causes an empty string to be appended to the result). For a simpler solution, you can use Array.from with a bit of arithmetic.
function arrow(n) {
return Array.from({length: n * 2 - 1}, (_,i)=>">".repeat(i < n ? i + 1 : n * 2 - 1 - i));
}
console.log(arrow(3));

The first one does not work because "num" is incremented a last time and thus equals "n + 1" when the code goes out from the while loop.
So if "n" = 3, when the code executes the first "while(num > 0) {", num will equal 4. So 4 - 1 = 3 repetition of the arrow.
So, to fix it :
function arrow(n) {
var arr = [];
var num = 1;
while(num <= n) {
arr.push(">".repeat(num));
num++;
}
num--; // add this line
while(num > 0) {
arr.push(">".repeat(num - 1));
num--;
}
return arr;
}
console.log(arrow(3));

The error with the first solution is that when num equals 3, you increment it to 4 in the while loop. When the second while loop runs, num - 1then equals 3.
In the second solution, num - 2 will equal -1 during the fourth iteration, which throws an error.
A for-loop may be easier to control here:
function arrow(n) {
var arr = [];
var num = 1;
for (let i = 1; i <= n; i++) {
arr.push(">".repeat(i))
}
for (let i = n - 1; i > 0; i--) {
arr.push(">".repeat(i));
}
return arr;
}

The issue with your second function :
when you were using the second while loop, the value of num was decreasing by 1 in each loop.
when the loop value of num comes to 1 , and and you tried to use arr.push(">".repeat(num - 2)); , then n-2 = -1 , but repeat(-1) is invalid function.
Solution:
I think in between two while loop, use num--; to decrease the value of num by 1. it will solve your problem.
function arrow(n) {
var arr = [];
var num = 1;
while(num <= n) {
arr.push(">".repeat(num));
num++;
}
num --;
while(num > 1) {
arr.push(">".repeat(num - 1));
num--;
}
return arr;
}
console.log(arrow(3));

so when your loop get the last element number == 1
the repeat function (num-2) will not work
for this challenger i simply put a (number--;) in the middle of the While loops
i hope that work.
function arrow(n) {
var arr = [];
var num = 1;
while(num <= n) {
arr.push(">".repeat(num));
num++;
}
num--; // take 1 out
while(num > 1) {
arr.push(">".repeat(num -1));
num--;
}
return arr;
}
console.log(arrow(3));

Related

Why always return "None" string, like my if statment was always false?

My second approach to learning JS.
Maybe someone will tell me why I always get "none".
Thank you for any help.
const reverseFactorial = (num) => {
for (let i = 1; num > 1; num = num / ++i) {
if (num === 1) return `${i}`
}
return 'None'
};
console.log(reverseFactorial(120))
check your if condition and for loop condition.num>i is your for loop condition so when i=1 in for loop it will immediately exit the for loop and not enters into the if condition so your if condition is never satisfied that's why you always get none.
so change your for loop condition to
num>=1;
Here's a working demo
Code Snippet
const reverseFactorial = (num) => {
for (let i = 1; num >= 1; num = num / ++i) { // condition updated to "num >= 1"
if (num === 1) return `${i}`
}
return 'None'
};
console.log('reverseFactorial(120) gives: ', reverseFactorial(120))
Sure it is possible to perform this also with the ternary operator, you have to change the internal 'if' check with an assignment to a temporary variable (let's call it 'result') which will be holding the temporary result at each iteration until the num equals one (num === 1) condition is met or num is no longer greater than nor equal to one (num >= 1); at that point, the for loop will end and the result is returned with the associated 'reversefactorial' value or 'None' value:
const reverseFactorial = (num) => {
// this avoids exceptions if num < 1 as you always return a valid value
// by returning zero, the function is reporting an invalid num argument
result = 0
for (let i = 1; num >= 1; num = num / ++i) { // condition updated to "num >= 1"
result = (num === 1) ? `${i}` : 'None'
}
return result
};
console.log('reverseFactorial(120) gives: ', reverseFactorial(120))
You can also speed the loop by taking everything out like this:
const reverseFactorial = (num) => {
// take into account num < 1
if (num < 1) {
i = 0;
num = 1;
}
else i = 1;
for (;num >= 1; num = num / ++i) { // condition updated to "num >= 1"
if (num === 1) break;
}
return (num === 1) ? `${i}` : 'None'
};
console.log('reverseFactorial(120) gives: ', reverseFactorial(120))
Though, as you can see, it is now more cumbersome to take into account invalid num entries with the starting if to correctly set the initial value for i; anyway this function should be faster than the previous one, the more the higher num is as we are taking the assigment out of the loop.

What is while(n- - >1)meaning?

I saw a question in leetcode.
Also,I found solution in it.
And one thing i don't understand is this line of code
while(n-- >1)
Could someone explain --> meaning?
Here is the JS:
var countAndSay = function(n) {
var result = "1";
var prev;
var count;
var tmp;
while (n-- > 1) {
prev = result[0];
count = 1;
tmp = [];
for (var i = 1; i < result.length; i++) {
if (prev === result[i]) {
count++;
} else {
tmp.push(count, prev);
prev = result[i];
count = 1;
}
}
tmp.push(count, prev);
result = tmp.join("");
}
return result;
};
console.log(countAndSay(4))
One last thing,Could someone explain what is this question's meaning.
I still don't understand why 2 is 11,3 is 21,4 is 1211 and 5 is 111221.
The expression
n-- > 1
means: subtract one from n, and check whether its value before the subtraction was greater than 1.
while (n-- > 1) {
// rest of the code
is equivalent to
while (true) {
if (n > 1) {
n--;
// rest of the code
} else {
// n is decremented regardless:
n--;
// initial condition was not fulfilled:
break;
}
Or, with the negation of the condition:
while (true) {
const origN = n;
n--;
if (!(origN > 1)) {
break;
}
// rest of the code
That means you check whether the n is greater than 1 and after that decrement n by 1.
That means, subtract 1 from n and check if the result is greater than 1.
n-- in any part of the code is equivalent to n = n - 1, or ``n -= 1`, in that loop is a consised way to subtract and evaluate.
The expression (n-- > 1) is similar to comparing the value of n greater than 1. But the thing which you must notice is the value of n will not be decremented(at the beginning) while comparing here. This is because the value of n is first compared with 1 after that only, the value of n is decremented. To understand this clearly, you can take a look over this.
function test(name) {
var n = 5;
while (n-- == 5) { //Here the decrement doesn't takes places so it gets inside the block
console.log(n); //This statement returns the value of n as 4.
}
}
const testing = new test();

My code crashes javascript console

My code is freezing Chrome (and Firefox), won't execute on Coderbyte console but when I submit the code as an answer to the exercise, it does take.
var numOrdered = 0;
var numReversed = 0;
var tries = 0;
function KaprekarsConstant(num) {
var arr = [];
while (num > 0) {
arr.unshift(num % 10);
num = num / 10 | 0;
}
arr.sort();
numOrdered = Number(arr.join(''));
numReversed = Number(arr.reverse().join(''));
while (num !== 6174) {
num = numReversed - numOrdered;
tries += 1;
}
return tries;
};
KaprekarsConstant(8593);
Why is it crashing? How can I prevent it?
Thank you guys!
the actual problem is the second while loop:
while (num !== 6174) {
num = numReversed - numOrdered;
tries += 1;
}
Removing it, your code doesn't hang the browser:
var numOrdered = 0;
var numReversed = 0;
var tries = 0;
function KaprekarsConstant(num) {
var arr = [];
while (num > 0) {
arr.unshift(num % 10);
num = num / 10 | 0;
}
arr.sort();
numOrdered = Number(arr.join(''));
numReversed = Number(arr.reverse().join(''));
return tries;
};
console.log(KaprekarsConstant(8593));
You need to revisit the logic in the second loop so that it doesn't become infinite.
The second loop makes your code to hang up.Try this. I have made some changes.
var numOrdered = 0;
var numReversed = 0;
var tries = 0;
function KaprekarsConstant(num) {
while (num !== 6174) {
var arr = [];
while(num >0){
arr.unshift(num % 10);
num = num / 10 | 0;
}
arr.sort();
numOrdered = Number(arr.join(''));
numReversed = Number(arr.reverse().join(''));
num = numReversed - numOrdered;
tries += 1;
}
return tries;
};
KaprekarsConstant(8593);
The while loop in the post keeps calculating the same value for num, so it it is not immediately 6174, the loop continues forever.
Basically the code is not following the algorithm for demonstrating Kaprekar's constant as shown on Wikipedia:
pad numbers of less than 4 digits with leading zeroes,
subtract the smaller number from the larger of { number, number with reversed digits), and
repeat from the step of extracting digits from the latest subtraction result.
Spoiler alert - here's a working example of a recursive function with the extra pieces of logic:
"use strict";
function KaprekarsConstant(num, tries=0) {
if( num == 6174) // Kaprekar's constant.
return tries;
if( num == 0) // degenerate case, digits are the same
return -tries;
var arr = [];
while (num > 0) {
arr.unshift(num % 10);
num = num / 10 | 0;
}
while( arr.length<4) { // leading zeroes as required
arr.unshift(0);
}
arr.sort();
var numOrdered = Number(arr.join(''));
var numReversed = Number(arr.reverse().join(''));
num = Math.abs( numOrdered - numReversed) // larger - smaller
return KaprekarsConstant( num, ++tries); // try again
};
// and test
function test() {
var num = Number(input.value);
if( Number.isNaN(num) || num < 1 || num > 9999) {
throw new Error("Enter number between 1 and 9999");
}
console.log("Tries = %s", KaprekarsConstant(num) );
}
<label> Enter 1 to 4 digit number: <input type="text" id="input"></label><br>
<button type="button" onclick="test()">Calculate tries</button>
While the answers do address your question, the solutions and the code are missing the part about leading zeros as in wiki Kaprekar's constant
and the whole solution is very simple
function KaprekarsConstant(num)
{
var tries=0;
var numOrdered =0;
var numRevesed=0;
while(num!=6174)
{
numOrdered=("0000" + num).substr(-4,4).split("").sort().join("");
numRevesed=numOrdered.split("").reverse().join("");
num = numRevesed-numOrdered;
tries+=1;
}
return tries;
}
KaprekarsConstant(8593);
To the reason for 'Why is it crashing?', its maybe due to Infinite Loop .
The response I got when I try to run your code
Possible infinite loop detected.
Error: Infinite loop
at KaprekarsConstant (script 19:68)
at script 27:1
Thank you everybody for the answers!!
Thanks to #Jaromanda X I realise the last while loop was infinite, since
num = numOrdered - numReversed;
will always be the same.
I realised I had to re-arrange the numbers every time so I create a function for that and incorporate it into the while loop.
I also added a bit of code from #traktor53 to add the leading zeros in case of a number with less than 4 digits.
And to finish I declare
var tries = 0;
inside the function so it will start from zero in each run.
.
.
Final result:
var numOrdered = 0;
var numReversed = 0;
function KaprekarsConstant(num) {
var tries = 0;
function order(num) { // function to order the numbers
var arr = [];
while (num > 0) {
arr.unshift(num % 10);
num = num / 10 | 0;
}
while(arr.length<4) { // leading zeroes as required
arr.unshift(0);
}
arr.sort();
numOrdered = Number(arr.join(''));
numReversed = Number(arr.reverse().join(''));
}
while (num !== 6174) {
order(num);
num = Math.abs(numOrdered - numReversed); // larger - smaller
tries += 1;
}
return tries;
};
KaprekarsConstant(8593);

I need to sum all odd fibonacci numbers but only works for some numbers

Task: Given a positive integer num, return the sum of all odd Fibonacci numbers that are less than or equal to num.
The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8.
For example, sumFibs(10) should return 10 because all odd Fibonacci numbers less than 10 are 1, 1, 3, and 5.
This is on freecodecamp. I have looked at examples I know I could of easily copied them but I wanted to write my own code, can someone explain why I get these results and where I've gone wrong? Thanks.
function sumFibs(num) {
var arr = [0, 1, 1]; //array of fibonacci numbers
var fin = 0; //variable for final number
for(var i = 3;i < 35;i++)
{
arr[i] = arr[i-1] + arr[i-2];
}
// loop to make fibonacci numbers
for(var x = 0; x < arr.length-1; x++)
{
if(arr[x] <= num && (arr[x] % 2 === 0))
{
fin += arr[x];
}//if to check if array of fibonacci numbers[x] is less than num && if it is odd
}//loop to go through every fibonacci number
return fin;
}
sumFibs(1000);
When you have the modulo operation:
if(arr[x] <= num && (arr[x] % 2 === 0))
You are asking two things:
if the arr[x] value is less than the number (check)
if the arr[x] value is even, NOT odd.
That is where your issue is occurring.
Rather you should use:
if(arr[x] <= num && (arr[x] % 2 != 0))
This is my solution :
function sumFibs(num)
{
var prev=0,curr=1,result=0,added;
while(curr<=num)
{
if(curr % 2 !=0)
{
result+=curr;
}
added= curr+prev;
prev=curr;
curr=added;
}
return result;
}
sumFibs(4);
Give this a try
function sumFibs(num) {
var firstNum = 0;
var secondNum = 1;
var sequence = [];
var index = [];
while (firstNum <= num) {
sequence.push(firstNum, secondNum);
firstNum = firstNum + secondNum;
secondNum = firstNum + secondNum;
/**/
}
for (var key in sequence) {
if (sequence[key] <= num) {
index.push(sequence[key]);
}}
//return index;
var oddIndex = [];
for (var key in index) {
if (index[key] % 2 !== 0) {
oddIndex.push(index[key]);
}
}
// return oddIndex;
var output = oddIndex.reduce(function(a,b){
return a+b;
});
return output;
}
sumFibs(75025); //should return 135721

Factorialize a Number

I'm taking the freecodecamp course one of the exercises it's to create a Factorialize function, I know there is several ways to do it just not sure what this one keeps returning 5
function factorialize(num) {
var myMax = num;
var myCounter = 1;
var myTotal = 0;
for (i = 0; i>= myMax; i++) {
num = myCounter * (myCounter + 1);
myCounter++;
}
return num;
}
factorialize(5);
This is a recursive solution of your problem:
function factorialize(num) {
if(num <= 1) {
return num
} else {
return num * factorialize(num-1)
}
}
factorialize(5)
This is the iterative solution:
function factorialize(num) {
var cnt = 1;
for (var i = 1; i <= num ; i++) {
cnt *= i;
}
return cnt;
}
factorialize(5)
with argument 5, it will return the 5! or 120.
To answer your question, why your function is returning 5:
Your function never reaches the inner part of the for-loop because your testing if i is greater than myMax instead of less than.
So you are just returning your input parameter which is five.
But the loop does not calculate the factorial of num, it only multiplies (num+1) with (num+2);
My solution in compliance with convention for empty product
function factorializer(int) {
if (int <= 1) {
return 1;
} else {
return int * factorializer(int - 1);
}
}
Here is another way to solve this challenge and I know it is neither the shortest nor the easiest but it is still a valid way.
function factorialiaze(num){
var myArr = []; //declaring an array.
if(num === 0 || num === 1){
return 1;
}
if (num < 0){ //for negative numbers.
return "N/A";
}
for (var i = 1; i <= num; i++){ // creating an array.
myArr.push(i);
}
// Reducing myArr to a single value via .reduce:
num = myArr.reduce(function(a,b){
return a * b;
});
return num;
}
factorialiaze(5);
Maybe you consider another approach.
This solution features a very short - cut to show what is possible to get with an recursive style and a implicit type conversion:
function f(n) { return +!~-n || n * f(n - 1); }
+ convert to number
! not
~ not bitwise
- negative
function f(n) { return +!~-n || n * f(n - 1); }
var i;
for (i = 1; i < 20; i++) {
console.log(f(i));
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this function
const factorialize = (num) => num === 0 ? 1 : num * factorialize(num-1)
Use it like this:
factorialize(5) // returns 120
Try this :
function factorialize(num) {
var value = 1;
if(num === 1 || num ===0) {
return value;
} else {
for(var i = 1; i<num; i++) {
value *= i;
}
return num * value;
}
}
factorialize(5);
// My solution
const factorialize = num => {
let newNum = 1;
for (let i = 1; i <= num; i++) {
newNum *= i
}
return newNum;
}
I love syntactic sugar, so
let factorialize = num => num <= 1 ? num : num * factorialize(num -1)
factorialize(5)

Categories

Resources