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

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();

Related

How to limit a number between several numbers (get the most nearest small number)? [duplicate]

Example: I have an array like this: [0,22,56,74,89] and I want to find the closest number downward to a different number. Let's say that the number is 72, and in this case, the closest number down in the array is 56, so we return that. If the number is 100, then it's bigger than the biggest number in the array, so we return the biggest number. If the number is 22, then it's an exact match, just return that. The given number can never go under 0, and the array is always sorted.
I did see this question but it returns the closest number to whichever is closer either upward or downward. I must have the closest one downward returned, no matter what.
How do I start? What logic should I use?
Preferably without too much looping, since my code is run every second, and it's CPU intensive enough already.
You can use a binary search for that value. Adapted from this answer:
function index(arr, compare) { // binary search, with custom compare function
var l = 0,
r = arr.length - 1;
while (l <= r) {
var m = l + ((r - l) >> 1);
var comp = compare(arr[m]);
if (comp < 0) // arr[m] comes before the element
l = m + 1;
else if (comp > 0) // arr[m] comes after the element
r = m - 1;
else // arr[m] equals the element
return m;
}
return l-1; // return the index of the next left item
// usually you would just return -1 in case nothing is found
}
var arr = [0,22,56,74,89];
var i=index(arr, function(x){return x-72;}); // compare against 72
console.log(arr[i]);
Btw: Here is a quick performance test (adapting the one from #Simon) which clearly shows the advantages of binary search.
var theArray = [0,22,56,74,89];
var goal = 56;
var closest = null;
$.each(theArray, function(){
if (this <= goal && (closest == null || (goal - this) < (goal - closest))) {
closest = this;
}
});
alert(closest);
jsFiddle http://jsfiddle.net/UCUJY/1/
Array.prototype.getClosestDown = function(find) {
function getMedian(low, high) {
return (low + ((high - low) >> 1));
}
var low = 0, high = this.length - 1, i;
while (low <= high) {
i = getMedian(low,high);
if (this[i] == find) {
return this[i];
}
if (this[i] > find) {
high = i - 1;
}
else {
low = i + 1;
}
}
return this[Math.max(0, low-1)];
}
alert([0,22,56,74,89].getClosestDown(75));
Here's a solution without jQuery for more effiency. Works if the array is always sorted, which can easily be covered anyway:
var test = 72,
arr = [0,56,22,89,74].sort(); // just sort it generally if not sure about input, not really time consuming
function getClosestDown(test, arr) {
var num = result = 0;
for(var i = 0; i < arr.length; i++) {
num = arr[i];
if(num <= test) { result = num; }
}
return result;
}
Logic: Start from the smallest number and just set result as long as the current number is smaller than or equal the testing unit.
Note: Just made a little performance test out of curiosity :). Trimmed my code down to the essential part without declaring a function.
Here's an ES6 version using reduce, which OP references. Inspired by this answer get closest number out of array
lookup array is always sorted so this works.
const nearestBelow = (input, lookup) => lookup.reduce((prev, curr) => input >= curr ? curr : prev);
const counts = [0,22,56,74,89];
const goal = 72;
nearestBelow(goal, counts); // result is 56.
Not as fast as binary search (by a long way) but better than both loop and jQuery grep https://jsperf.com/test-a-closest-number-function/7
As we know the array is sorted, I'd push everything that asserts as less than our given value into a temporary array then return a pop of that.
var getClosest = function (num, array) {
var temp = [],
count = 0,
length = a.length;
for (count; count < length; count += 1) {
if (a[count] <= num) {
temp.push(a[count]);
} else {
break;
}
}
return temp.pop();
}
getClosest(23, [0,22,56,74,89]);
Here is edited from #Simon.
it compare closest number before and after it.
var test = 24,
arr = [76,56,22,89,74].sort(); // just sort it generally if not sure about input, not really time consuming
function getClosest(test, arr) {
var num = result = 0;
var flag = 0;
for(var i = 0; i < arr.length; i++) {
num = arr[i];
if(num < test) {
result = num;
flag = 1;
}else if (num == test) {
result = num;
break;
}else if (flag == 1) {
if ((num - test) < (Math.abs(arr[i-1] - test))){
result = num;
}
break;
}else{
break;
}
}
return result;
}

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.

Why does repeat function not work the second time?

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));

Javascript function that finds the next largest palindrome number

I want to write a function that finds the next largest palindrome for a given positive integer. For example:
Input: 2
Output: 3 (every single digit integer is a palindrome)
Input: 180
Output: 181
Input: 17
Output: 22
My try
function nextPalindrome(num) {
let input = num;
let numToStringArray = input.toString().split('');
let reversedArray = numToStringArray.reverse();
if (numToStringArray.length < 2) {
return Number(numToStringArray) + 1;
} else {
while (numToStringArray !== reversedArray) {
// numToStringArray = num.toString().split('');
// reversedArray = numToStringArray.reverse();
num += 1;
}
return numToStringArray.join('');
}
}
As a beginner, I thought that the numToStringArray would constantly increment by 1 and check for whether the while-statement is true.
Unfortunately it doesn't. I commented out two lines in the while-statement because they seemed somewhat redundant to me. Thanks to everyone reading or even helping me out!
The reason your code doesn't work is because you don't have any code updating the conditions of your while loop. So if you enter it once, it will loop indefinitely. You need to do something inside of the while loop that might make the condition false the next time through the loop, like so:
function getReverse(num) {
// get the reverse of the number (in positive number form)
let reversedNum = +Math.abs(num).toString().split("").reverse().join("");
// keep negative numbers negative
if (num < 0) { reversedNum *= -1; }
return reversedNum;
}
function nextPalindrome(num) {
// if single digit, simply return the next highest integer
if (num >= -10 && num < 9) {
return num+1;
}
else {
while(num !== getReverse(num)) {
num += 1;
}
return num;
}
}
console.log(nextPalindrome(3));
console.log(nextPalindrome(17));
console.log(nextPalindrome(72));
console.log(nextPalindrome(180));
console.log(nextPalindrome(1005));
console.log(nextPalindrome(-150));
console.log(nextPalindrome(-10));
You could also solve this pretty cleanly using recursion, like so:
function getReverse(num) {
// get the reverse of the number (in positive number form)
let reversedNum = +Math.abs(num).toString().split("").reverse().join("");
// keep negative numbers negative
if (num < 0) { reversedNum *= -1; }
return reversedNum;
}
function nextPalindrome(num) {
// if single digit, simply return the next highest integer
if (num >= -10 && num < 9) {
return num+1;
}
else if(num === getReverse(num)) {
return num;
}
else {
// if not the same, recurse with n + 1
return nextPalindrome(num + 1)
}
}
console.log(nextPalindrome(3));
console.log(nextPalindrome(17));
console.log(nextPalindrome(72));
console.log(nextPalindrome(180));
console.log(nextPalindrome(1005));
console.log(nextPalindrome(-150));
console.log(nextPalindrome(-10));

Loop to determine whether digits of a number meet a condition (Javascript)

So, I am trying to create a function that determines whether a number is 'tidy'. (i.e. Each digit in the given integer is greater than the one that came before it.)
I have successfully managed to convert the integer into an array. But when I loop through it, I don't get the desired true for tidy and false, if otherwise. I am wondering what I am doing wrong?
function tidyNumber(n){
var arr = n.toString(10).split("").map(function(t){return parseInt(t)});
let tof;
if(arr.length == 1){
return true;
}
for(i = 0; i < arr.length; i++){
if(arr[i] <= arr[i+1]){
tof = true;
} else if(arr[i] > arr[i+1]){
tof = false;
}
}
return tof;
}
You could check only if a previous digit is greater than the actual digit and exit the function with false.
Then you need to start at index 1 and prevent checking a not given index.
function tidyNumber(n) {
var arr = Array.from(n.toString(), Number),
i; // declare, otherwise its a global variable
for (i = 1; i < arr.length; i++) {
if (arr[i - 1] > arr[i]) return false;
}
return true;
}
console.log(tidyNumber(1234)); // true
console.log(tidyNumber(1)); // true
console.log(tidyNumber(1223334)); // true
console.log(tidyNumber(51223334)); // false
To answer your question: The reason your function does not return the desired result is that is only returns the last value of tof. So your function currently only reports whether the last two digits of a number are tidy. To use the example of #Seblor, 1324:
First, the code will check whether 1 < 3 and set tof = true.
Next, it will check whether 3 < 2 and set tof = false.
Next, it will check whether 2 < 4 and set tof = true. This erases the actual result that you were seeking.
Incidentally, the code will finally check whether 4 < undefined (as #Pointy mentioned) but will not change the value of tof since neither conditional expression was satisfied.
You can achieve the desired behavior by returning the false result immediately when tof = false (as #nina-scholz suggested). Here is what that might look like within your code:
function tidyNumber(n){
var arr = n.toString(10).split("").map(function(t){return parseInt(t)});
let tof;
if(arr.length == 1){
return true;
}
for(i = 0; i < arr.length; i++){
if(arr[i] <= arr[i+1]){
tof = true;
} else if(arr[i] > arr[i+1]){
tof = false;
return tof; // <-- Added return statement here
}
}
return tof;
}
I hope that helps!
Try like this:
function tidyNumber(n){
current = 0;
while(n){
if(current > n % 10){
return false;
}
current = n % 10;
n = parseInt(n / 10);
}
return true;
}
The idea is to by "% 10" to get the remainder of a division by 10. This will get you the last digit. Look if its smaller then the one before, else loop until the number is zero!

Categories

Resources