How could I function named unfactorial that takes a number and returns a string representing it's base factorial in the form: n!? This would result in the un-do the factorial operation if one is possible. It should return null if no factorial was possible.
Package
A factorial operation looks like this:
5! = 5 * 4 * 3 * 2 * 1 = 120
Function Output:
unfactorial(120) // '5!'
unfactorial(150) // null
unfactorial(5040) // '7!'
My current Solution
const unfactorial = (num) => {
let d = 1
while (num > 1 && Math.round(num === num)) {
d += 1
num /= d
}
if (num === 1)
return `${d}!`
else return null
}
Here's one way you could do it using an auxiliary recursive function.
Note, it will not work for numbers that are not actual factorials. This is left as an exercise for the asker.
const unfactorial = x => {
const aux = (acc, x) => {
if (x === 1)
return acc - 1
else
return aux(acc + 1, x / acc)
}
return aux(2, x)
}
console.log(unfactorial(120)) // 5
console.log(unfactorial(5040)) // 7
How it works
Starting with the input number x and a counter, acc = 2, successively divide x by acc (then acc + 1, then acc + 2, etc) until x == 1. Then return acc - 1.
Or go bananas using only expressions. You'll probably like this, #Mr.Polywhirl
const U = f => f (f)
const Y = U (h => f => f (x => h (h) (f) (x)))
const unfactorial = Y (f => acc => x =>
x === 1 ? acc - 1 : f (acc + 1) (x / acc)
) (2)
console.log(unfactorial(120)) // 5
console.log(unfactorial(5040)) // 7
Related
let power2 = (x,n) => {
if(n == 0) return 1;
let temp = power2(x,n/2);
if(n%2 == 1) return temp * temp * x;
return temp*temp;
}
console.log(power2(4,3));
This method has less nodes and time complexity but its giving wrong output
The problem with the original code was the fact that n / 2 will result in a real number when you need it to be treated as an integer. Bitwise operation are always performed on integers so n >> 1 will correctly yield an integer. The same goes with modulo which converts the number to an integer first that's why it worked correctly in your code.
let power2 = (x, n) => {
if (n === 0) return 1;
const temp = power2(x, (n >> 1));
if (n % 2 === 1) return temp * temp * x;
return temp * temp;
}
console.log(power2(4, 3));
If you need custom integer power function, based on recursion, consider this snippet:
// Custom pow
const myPow = (n, i) => i > 0 ? myPow(n, i - 1) * n : 1;
// Test
console.log(myPow(4, 3));
I have written the code of this problem but it works for only 70% of the test cases. I can't figure out what is wrong with it. Please help.
Problem:-
Find the number of ways that a given integer, X, can be expressed as the sum of the Nth powers of unique, natural numbers in the range of [1,25] both inclusive.
Hint:-
The answer will be (1^2 + 3^2).
My code is not working for x = 100 and n = 2. The output should be 3 but it returns 33.
let x = 100;
let n = 2;
let num = 0;
let index = 1;
function power(x, n, num, index, ways = 0) {
if (x === num) {
return 1;
}
if (x < num) {
return 0;
}
for (let i = index; i <= 25; i++) {
ways += power(x, n, (num + ((i) ** n)), index + 1);
}
return ways;
}
console.log(power(x, n, num, index));
Your logic is almost right. But you're not properly removing duplicate values and ending up including things like 9^2 + 3^2 + 3^2 + 1^2 or 5^2 + 5^2 + 5^2 + 4^2 + 3^2.
You need to change the recursive index you pass. You shouldn't use your index parameter but your loop iterator, i:
let x = 100;
let n = 2;
let num = 0;
let index = 1;
function power(x, n, num, index, ways = 0) {
if (x === num) {
return 1;
}
if (x < num) {
return 0;
}
for (let i = index; i <= 25; i++) {
// ways += power(x, n, (num + ((i) ** n)), index + 1);
// v-^
ways += power(x, n, (num + ((i) ** n)), i + 1);
}
return ways;
}
console.log(power(x, n, num, index));
I figured this out fairly quickly by writing my own version of the function from scratch, and getting the exact same wrong result. I added some logging and realized the problem and was able to spot it quickly. This translated easily to your code.
But I think my function is cleaner, so I'm including it here. It does much the same logic, but in a cleaner functional manner:
const range = (lo, hi) =>
Array .from ({length: hi - lo + 1}, (_, i) => i + lo)
const sum = (ns) =>
ns .reduce ((a, b) => a + b, 0)
const countPowerSums = (n, p, i = 1) =>
n < 0
? 0
: n == 0
? 1
: sum (range (i, 25) .map (b => countPowerSums (n - b ** p, p, b + 1)))
console .log (countPowerSums (100, 2))
I am trying to solve this kata on Codewars: https://www.codewars.com/kata/56e56756404bb1c950000992/train/javascript, and I have a method that I think should be correct, but it throws a RangeError. This is my code:
function sumDifferencesBetweenProductsAndLCMs(pairs){
return pairs.reduce((acc, curr) => {
// LCM * GCD = product
return acc + (curr[0] * curr[1] * (1 - 1 / GCD(curr)))
}, 0)
}
function GCD(pair) {
// Euclidean algorithm
let a = Math.max(...pair);
let b = Math.min(...pair);
let r = a % b;
if (r == 0) {
return b;
}
return GCD([b, r]);
}
Where am I going wrong? How else can I implement the Euclidean Algorithm?
I'm not sure I get any of the maths stuff here, but skipping zeros seems to stop it from trying to recurse forever.
Anything % 0 will give NaN and probably anything % NaN will give NaN and NaN == 0 is false, so if you start with a zero value entering GCD there's no way for the recursion to terminate.
function sumDifferencesBetweenProductsAndLCMs(pairs){
return pairs.reduce((acc, curr) => {
// LCM * GCD = product
if(Math.min(...curr) === 0) return acc; // Skip zeros
return acc + (curr[0] * curr[1] * (1 - 1 / GCD(curr)))
}, 0)
}
function GCD(pair) {
// Euclidean algorithm
let a = Math.max(...pair);
let b = Math.min(...pair);
let r = a % b;
if (r == 0) {
return b;
}
return GCD([b, r]);
}
console.log(sumDifferencesBetweenProductsAndLCMs([[15,18], [4,5], [12,60]]),840);
console.log(sumDifferencesBetweenProductsAndLCMs([[1,1], [0,0], [13,91]]),1092);
console.log(sumDifferencesBetweenProductsAndLCMs([[15,7], [4,5], [19,60]]),0);
console.log(sumDifferencesBetweenProductsAndLCMs([[20,50], [10,10], [50,20]]),1890);
console.log(sumDifferencesBetweenProductsAndLCMs([]),0);
var y;
function deci(y) {
var res = "";
while (y != 1) {
res = res + y % 2;
y = y / 2;
}
return (1 + res);
}
What you could do
change the loop to a do ... while loop, because it loops at least one time, for zero values,
switch the assignment of res to res = y % 2 + res;, because it has the right order now,
take the integer value of the divided value for the next loop,
check the value and go on with non zero values.
function deci(y) {
var res = "";
do {
res = y % 2 + res;
y = Math.floor(y / 2);
} while (y)
return res;
}
console.log (deci(0));
console.log (deci(1));
console.log (deci(2));
console.log (deci(3));
console.log (deci(4));
console.log (deci(5));
console.log (deci(13));
This to me looks like an endless loop. Try to modify the condition to y >= 1
var y;
function deci(y) {
var res = "";
while (y >= 1) {
res = res + y % 2;
y = y / 2;
}
return (1 + res);
}
When you call deci(3), y will never become 1, so you will get an infinite loop. The only inputs that does not result in an infinite loop are powers of 2 (1, 2, 4, 8, 16, ...)
To figure out what's going on, add a console.log call inside the while loop.
function deci(y) {
console.log('converting', y, 'to binary')
var res = '1'
while (y != 1) {
res += y % 2
y = y / 2
console.log('y is', y)
// let's throw an error after a while to avoid freezing the computer
if (y < 0.001) throw "infinite loop"
}
console.log('the result is', res)
}
deci(64) // this works fine
deci(3) // this ends up in an infinite loop
In general do not use =! and == with floating point numbers. Since even when your logic seems correct, there might be rounding errors that you would not get with decimal numbers. Is floating point math broken?
To convert a number to base 2, you can use number.toString(2)
function deci(n) {
return n.toString(2)
}
console.log(deci(3)) // -> '11'
Three problems
global y is bad practice – you're shadowing it with a local y so I'm guessing you didn't intend to do this
Your while condition is broken – repeatedly dividing a number by 2 will not always reach 1
JavaScript performs floating point division, so you need to truncate the decimal
This is probably what you meant to write
const deci = y =>
{
let res = ''
while (y >= 2)
{
res = res + String (y % 2)
y = y / 2 >> 0
}
return res + String (y)
}
console.log (deci (0))
console.log (deci (1))
console.log (deci (2))
console.log (deci (3))
console.log (deci (4))
console.log (deci (5))
Here's another way you can write the program
const deci = y =>
y < 2
? String (y)
: deci (y / 2 >> 0) + String (y % 2)
console.log (deci (0))
console.log (deci (1))
console.log (deci (2))
console.log (deci (3))
console.log (deci (4))
console.log (deci (5))
A default parameter value and better name make this function a little nicer to read, imo
const decimalToBinary = (n = 0) =>
n < 2
? String (n)
: decimalToBinary (n / 2 >> 0) + String (n % 2)
As #NinaScholz points out, you can perform n / 2 >> 0 in a single operation n >> 1 - the function is further improved
const decimalToBinary = (n = 0) =>
n < 2
? String (n)
: decimalToBinary (n >> 1) + String (n % 2)
Alternatively, we could make 2 a parameter of our function to create a generic base converter
const decimalToBase = (n = 0, base = 2) =>
n < base
? String (n)
: decimalToBase (n / base >> 0) + String (n % base)
const decimalToBinary = (n = 0) =>
decimalToBase (n, 2)
const decimalToOctal = (n = 0) =>
decimalToBase (n, 8)
console.log (decimalToBinary (0), decimalToOctal (0)) // 0 0
console.log (decimalToBinary (1), decimalToOctal (1)) // 0 1
console.log (decimalToBinary (2), decimalToOctal (2)) // 10 2
console.log (decimalToBinary (7), decimalToOctal (7)) // 111 7
console.log (decimalToBinary (8), decimalToOctal (8)) // 1000 10
console.log (decimalToBinary (9), decimalToOctal (9)) // 1001 11
I am pretty new to programming, I am getting to know JavaScript, and I've just learned the notion of recursion. Now I am given a problem, to create a function (like const f = function(n) { }) and if we if we call the function with f(5), we should see:
*
***
*****
*******
*********
The number of vertical stars must be determined by the input.
I've got to use no for/while/do-while; recursion only to loop.
I've come up with this code to concatenate 5 stars
const f = function(n) {
if (n === 0) {
return "";
}
return "*" + f(n - 1);
};
console.log(f(5));
Though, I don't see how to make the triangle, what can I do?
You can use this code:
const f = function(chr, n) {
if (n === 0) {
return "";
}
return chr + f(chr, n - 1);
};
const g = function(max) {
const inner = function(n) {
if (n > 1) {
inner(n-1);
}
console.log(f(' ', max-n) + f('*', (n*2)-1));
};
inner(max);
};
g(5);
Please see and play the example below
function pyramid(n, row = 0, level = '') {
if (row === n) {
return
}
if (level.length === n * 2 - 1) {
console.log(level)
return pyramid(n, row + 1)
}
const midpoint = Math.floor((2 * n - 1) / 2)
let add;
if (midpoint - row <= level.length && midpoint + row >= level.length) {
add = '#'
} else {
add = ' '
}
pyramid(n, row, level + add)
}
pyramid(3)
You are on the right way with the
if (n === 0) ...
and the
f(n-1)
these are correct already.
Now you just need to output the correct number of stars in every function call. Look at string.repeat() for that.
If you want to see a complete solution and not just a hint: here is my solution.
function recursiveStar(n){
if(n === 0) return 0;
recursiveStar(n - 1);
return console.log('*'.repeat(n));
}
recursiveStar(5)
You can try this
function pyramid(n, row = 0) {
if (n === row) return;
let midpoint = Math.ceil((n + n - 1) / 2);
let str = "";
for (let j = 1; j <= n + n - 1; j++) {
if (j <= midpoint + row && j >= midpoint - row) str += "#";
else str += " ";
}
console.log(str);
pyramid(n, row + 1);
}
pyramid(5);
As this old question has recently been brought back up, here's an alternative version that treats the depth as constant and recurs on the row number:
const pyramid = (n, r = 0) =>
r > n - 1
? ''
: ' '.repeat ((n - 1 - r)) + '*'.repeat ((2 * r + 1)) + '\n' + pyramid (n, r + 1)
console .log (pyramid (5))
We keep n fixed, starting r at zero, and then recursively incrementing r until it's greater than n. In our base case, when n is 0 and r is 0, we get r > n - 1, and return an empty string. The recursive case proceeds by adding the right number of spaces, the the right number of starts to our first row, and calculating the remaining rows by incrementing r, and recurring.
const pyramid = (n, r = 0) =>
r > n - 1
? ''
: ' ' .repeat ((n - 1 - r)) + '*' .repeat ( (2 * r + 1)) + '\n' + pyramid (n, r + 1)
// `-----------------------' `------------------------' `--' `----------------'
// | | | |
// | | | +-- next rows
// | | +---------------- line break
// | +----------------------------------- asterisks
// +--------------------------------------------------------------- empty spaces
The only slight trickiness in that is the calculation of the correct number of stars and spaces. It's pretty easy to see that for pyramid (5), the spaces should decrease steadily from 4 down to 0 and the asterisks should increase from 1 up to 9. These are captured by the formulas n - 1 - r and 2 * r + 1 respectively.
This was originally for an assignment, and if that assignment didn't allow us to use String.prototype.repeat, then we could easily write our own recursive version in a function like this:
const repeat = (c, n) =>
n < 1 ? '' : c + repeat (c, n - 1)
const pyramid = (n, r = 0) =>
r > n - 1
? ''
: repeat (' ', (n - 1 - r)) + repeat ('*', (2 * r + 1)) + '\n' + pyramid (n, r + 1)