In the interest of better understanding recursion, I'm trying to figure out how to log a recursive trace to the console. I've got the 'trace down' part, but I'm not sure how to 'bubble up' the solution. Any suggestions for a perfectly placed console.log statement?
Here's what I've got so far:
function factorial (num) {
if (num === 1) {
console.log('factorial(' + num + ') = ' + num);
return 1;
} else {
console.log('factorial(' + num + ') = ' + num + ' * ' + 'factorial(' + (num - 1) + ')');
return num * factorial(num - 1);
}
}
which prints the following to the console:
factorial(5) = 5 * factorial(4)
factorial(4) = 4 * factorial(3)
factorial(3) = 3 * factorial(2)
factorial(2) = 2 * factorial(1)
factorial(1) = 1
120
But what about the 1 * 2 * 3 * 4 * 5 part? I know it's happening in there somewhere, how can I print it?
I guess I'd expect it to look something like this:
1
1 * 2
2 * 3
6 * 4
24 * 5
120
Thanks for any suggestions!
Ok after more searching I found this over at CodeRanch, unfortunately sans code (and written in Java):
Enter fact(6)
Enter fact(5)
Enter fact(4)
Enter fact(3)
Enter fact(2)
Enter fact(1)
Enter fact(0)
0!Ret: 1
Ret: 1 * fact(n-1) = 1 * fact(0) = 1 * 1 = 1
Ret: 2 * fact(n-1) = 2 * fact(1) = 2 * 1 = 2
Ret: 3 * fact(n-1) = 3 * fact(2) = 3 * 2 = 6
Ret: 4 * fact(n-1) = 4 * fact(3) = 4 * 6 = 24
Ret: 5 * fact(n-1) = 5 * fact(4) = 5 * 24 = 120
Ret: 6 * fact(n-1) = 6 * fact(5) = 6 * 120 = 720
fact(6) = 720
Pretty cool, right? After more experimenting, I still can't achieve this though...
function factorial (num) {
if (num === 1) {
console.log(num); //print new line after this
return 1;
} else {
var val = factorial(num - 1);
console.log(num +'*' + val); //print new line after this
return num * val;
}
}
I think it's best explained by using your example (edited a little) with comments. Assume you call this function with the parameter set to 5 the first time.
// num = 5, the first time it's called
function factorial (num) {
console.log('factorial(' + num + ')');
if (num === 1) {
// If num === 1, the function will just return 1 and exit.
return 1;
} else {
// Otherwise, which happens almost every time (since 1 is only
// reached once and then it stops). For 5, this would return
// 5 * factorial(4), which in order returns 4 * factorial(3),
// and so on.
return num * factorial(num - 1);
}
}
This output might help you understand:
factorial(5) == (5) * (factorial(4)) // (5) * (4 * 3 * 2 * 1)
factorial(4) == (4) * (factorial(3)) // (4) * (3 * 2 * 1)
factorial(3) == (3) * (factorial(2)) // (3) * (2 * 1)
factorial(2) == (2) * (factorial(1)) // (2) * (1)
factorial(1) == (1) // (1)
function factorial (num) {
for (var i=1; i<6-num; i++)
console.log(' ');
}
console.log('Enter fact('+num+')'); //add code to move new line
if(num==0) {
for (var i=1; i<6-num; i++)
console.log(' ');
}
console.log('0!Ret: 1 '); // add code to move new line
return 1;
} else {
int val = factorial(num-1);
for (var i=1; i<6-num; i++)
console.log(' ');
}
console.log('Ret:'+num+ ' * fact(n-1) = ' + num+ ' * fact('+(num-1)+') = '+num+' * ' + val + ' = ' + (num*val) ); // add code to move new line
return num*val;
}
}
Related
Im working on javascript problem code:
function randomNumberInt() {
return Math.floor(Math.random() * (1000 - 100 + 1) + 100);
}
You can use this function:
function genRandom() {
const digitHundreds = Math.floor(Math.random() * 9) + 1;
let digitTens = Math.floor(Math.random() * 9);
if (digitTens >= digitHundreds) digitTens++;
let digitUnits = Math.floor(Math.random() * 8);
if (digitUnits >= digitHundreds || digitUnits >= digitTens) digitUnits++;
if (digitUnits >= digitHundreds && digitUnits >= digitTens) digitUnits++;
return digitHundreds * 100 + digitTens * 10 + digitUnits;
}
console.log(genRandom());
Here digiHundreds, digitTens and digitUnits are the three digits of the number to generate.
digiHundreds has 9 choices: 1..9 (it cannot be 0)
digitTens has 10 choices, but excluding digiHundreds, so we choose from 0..8 and add 1 if it is greater or equal to digiHundreds
digitUnits has 10 choices, but excluding digiHundreds and digitTens, so we choose from 0..7 and add 1 if is greater or equal to either digiHundreds or digitTens, and add 1 more if it is greater or equal than both.
This process guarantees that the three digits are distinct. Combining the three digits to a number is a matter of multiplying them with the correct power of 10.
Fill the array untill the length is 3 and then join.
function getRandomArbitrary(min, max) {
return Math.floor(Math.random() * (max - min) + min) + 1;
}
function randomNumberInt() {
const result = [];
while (result.length !== 3) {
let random = getRandomArbitrary(0, 9);
if (!result.includes(random)) result.push(random);
// To check if the first no is not zero
if (result.length === 1 && random === 0) result.pop();
}
return parseInt( result.join("") );
}
const result = randomNumberInt();
console.log(result);
Decide each number separately.
First get last digit (any 0-9).
Then second (any 0-9, but not first).
Then the first digit (any 0-9, but not first, second, or 0).
function range(n) {
return [...Array(n).keys()] // returns [0,1,2,...,n-1]
}
function randomFromArray(arr) {
return arr[Math.floor(Math.random() * arr.length)]
}
function randomNumberInt() {
const digits = range(10) // or [...Array(10).keys()] if u do not want to declare range function
const lastDigit = randomFromArray(digits)
const possibleSecondDigits = digits.filter((n) => n !== lastDigit)
const secondDigit = randomFromArray(possibleSecondDigits)
const possibleFirstDigits = possibleSecondDigits.filter((n) => n !== 0 && n !== secondDigit)
const firstDigit = randomFromArray(possibleFirstDigits)
return firstDigit * 100 + secondDigit * 10 + lastDigit
}
console.log(randomNumberInt())
console.log(randomNumberInt())
console.log(randomNumberInt())
console.log(randomNumberInt())
console.log(randomNumberInt())
For example digits=4 means if input is 7 need output 7999, for 83 output should be 8399, for 9 output should be 9999. Want to add trailing 9 based on digits
You could take the stringes number and pad the needed values.
function nines(value, digits) {
return +value.toString().padEnd(digits, 9);
}
console.log(nines(83, 4));
A numerical version
function nines(value, digits) {
while (value < 10 ** (digits - 1)) value = value * 10 + 9;
return value;
}
console.log(nines(83, 4));
console.log(nines(2, 1));
console.log(nines(2, 2));
One thing you may be able to do is to multiply the input number by a power of 10 in order to add extra digits of 0 to the end, and then use addition to add 9 into each of those newly created digits.
For example:
Input - 7
7 * 1000 -> 7000 (NOTE: 1000 is a power of 10: 10^3)
7000 + (100 * 9) + (10 * 9) + (1 * 9) = 7999
Input
83 * 100 -> 8300 (NOTE: 100 is a power of 10: 10^2)
8300 + (10 * 9) + (1 * 9) = 8399
Not entirely sure if this is what you want
trailNines(number) {
let numberString = number.toString();
let result = '';
if(numberString.length === 4){
result = number.toString();
}
if(numberString.length === 3) {
result = number.toString() + '9';
}
if(numberString.length === 2) {
result = number.toString() + '99';
}
if(numberString.length === 1) {
result = number.toString() + '999';
}
return parseInt(result);
}
I have tried this
function binToDec(num) {
let dec = 0;
for(let i = 0; i < num.length; i++) {
if(num[num.length - (i + 1)] === '1') {
dec += 2 ** i;
}
}
return dec;
}
console.log(binToDec('1010'));
this code is not mine and it works but i want to know how it converts the binary number to decimal and it will be very helpful is you could tell me another way to do it.
I have also tried this
function binToDec(num) {
let bin = parseInt(num, 2);
return bin;
}
console.log(binToDec(1010));
I know this also work but i am not looking for this answer.
thank you for your help.
I just starts with the last character of the string and adds the value of this position to the result.
string dec
------ -------
1010 0
0 0
1 0 + 2
0 2
1 2 + 8
------ ------
10
function binToDec(num) {
let dec = 0;
for (let i = 0; i < num.length; i++) {
if (num[num.length - (i + 1)] === '1') {
dec += 2 ** i;
}
}
return dec;
}
console.log(binToDec('1010')); // 10
Another way is to start with the left side of the sting and
multiply the converted value by the base (2) and
add the value of the string.
The result is now the converted number. This works for all bases, as long as the value at the index is converted to a number.
function binToDec(num) {
let dec = 0;
for (let i = 0; i < num.length; i++) {
dec *= 2;
dec += +num[i];
}
return dec;
}
console.log(binToDec('1101')); // 13
Explanation
Think of how base 10 works.
909 = 900 + 9
= (9 * 100) + (0 * 10) + (9 * 1)
= (9 * 10**2) + (0 * 10**1) + (9 * 10**0)
As you can see, a natural number in base 10 can be seen as a sum where each term is in the form of:
digit * base**digit_position
This is true for any base:
base 2 : 0b101 = (0b1 * 2**2) + (0b0 * 2**1) + (0b1 * 2**0)
base 16 : 0xF0F = (0xF * 16**2) + (0x0 * 16**1) + (0xF * 16**0)
Therefore, here is a possible abstraction of a natural number:
function natural_number (base, digits) {
var sum = 0;
for (var i = 0; i < digits.length; i++) {
digit = digits[i];
digit_position = digits.length - (i + 1);
sum += digit * base**digit_position;
}
return sum;
}
> | natural_number(2, [1, 0, 1]) // 1 * 2**2 + 1 * 2**0
< | 5
> | natural_number(10, [1, 0, 1]) // 1 * 10**2 + 1 * 10**0
< | 101
> | natural_number(16, [1, 0, 1]) // 1 * 16**2 + 1 * 16**0
< | 257
Your own function takes only binary numbers (base 2). In this case digit can be either 0 or 1, that's all. We know that it's useless to multiply something by 0 or 1, so the addition can be replaced with:
if (digit === 1) {
sum += 2**digit_position;
}
Which is the equivalent of:
if (num[num.length - (i + 1)] === '1') {
dec += 2 ** i;
}
Do you get it? :-)
Alternative
You don't feel confortable with the exponentiation operator (**)? There is a workaround. Did you ever notice that multiplying a number by 10 is nothing more than shifting its digits one time to the left?
909 * 10 = 9090
Actually, shifting a number to the left boils down to multiplying this number by its base:
number *= base
This is true for any base:
base 2 : 0b11 * 2 = 0b110
base 16 : 0xBEE * 16 + 0xF = 0xBEE0 + 0xF = 0xBEEF
Based on this, we can build an algorithm to convert an array of digits into a number. A trace of execution with [9,0,9] in base 10 as input would look like this:
init | 0 | n = 0
add 9 | 9 | n += 9
shift | 90 | n *= 10
add 0 | 90 | n += 0
shift | 900 | n *= 10
add 9 | 909 | n += 9
Here is a possible implementation:
function natural_number (base, digits) {
var n = 0;
for (var i = 0; i < digits.length; i++) {
n += digits[i];
if (i + 1 < digits.length) {
n *= base;
}
}
return n;
}
Of course this function works the same as before, and there is a good reason for that. Indeed, unroll the for loop that computes [9,0,9] in base 10, you get this:
return ((0 + 9) * 10 + 0) * 10 + 9;
Then expand this expression:
((0 + 9) * 10 + 0) * 10 + 9
= (0 + 9) * 10 * 10 + 0 * 10 + 9
= 9 * 10 * 10 + 0 * 10 + 9
= 9 * 10**2 + 0 * 10**1 + 9 * 10**0
Do you recognize the equation discussed earlier? :-)
Bonus
Reverse function:
function explode_natural_number (base, number) {
var remainder, exploded = [];
while (number) {
remainder = number % base;
exploded.unshift(remainder);
number = (number - remainder) / base;
}
return exploded.length ? exploded : [0];
}
> | explode_natural_number(2, 5)
< | [1, 0, 1]
> | explode_natural_number(3, 5) // base 3 (5 = 1 * 3**1 + 2 * 3**0) :-)
< | [1, 2]
> | explode_natural_number(16, natural_number(16, [11, 14, 14, 15])) // 0xBEEF
< | [11, 14, 14, 15]
String to number and number to string:
function parse_natural_number (number, base) {
var ZERO = 48, A = 65; // ASCII codes
return natural_number(base, number.split("").map(function (digit) {
return digit.toUpperCase().charCodeAt(0);
}).map(function (code) {
return code - (code < A ? ZERO : A - 10);
}));
}
function stringify_natural_number (number, base) {
var ZERO = 48, A = 65; // ASCII codes
return String.fromCharCode.apply(
String, explode_natural_number(base, number).map(function (digit) {
return digit + (digit < 10 ? ZERO : A - 10);
})
);
}
> | stringify_natural_number(parse_natural_number("48879", 10), 16)
< | "BEEF"
> | parse_natural_number("10", 8)
< | 8
More levels of abstraction for convenience:
function bin_to_dec (number) {
return parse_natural_number(number, 2);
}
function oct_to_dec (number) {
return parse_natural_number(number, 8);
}
function dec_to_dec (number) {
return parse_natural_number(number, 10);
}
function hex_to_dec (number) {
return parse_natural_number(number, 16);
}
function num_to_dec (number) {
switch (number[0] + number[1]) {
case "0b" : return bin_to_dec(number.slice(2));
case "0x" : return hex_to_dec(number.slice(2));
default : switch (number[0]) {
case "0" : return oct_to_dec(number.slice(1));
default : return dec_to_dec(number);
}
}
}
> | oct_to_dec("10")
< | 8
> | num_to_dec("010")
< | 8
> | 010 // :-)
< | 8
function dec_to_bin (number) {
return stringify_natural_number(number, 2);
}
> | dec_to_bin(8)
< | "1000"
I wish to use Javascript to generate a random number between 1 and 2 inclusive.
Easy enough, I think -- something like?
Math.floor((Math.random() * 2) + 1);
But then I want to generate a second number, which if the first result is 1, is 2; and if the first result is 2, is 1.
(I hope the punctuation is clear.)
Update — random integers, I should have said (i.e. 1 or 2 only).
You can do so eloquently just by subtracting the first value from 3:
var first = Math.floor((Math.random() * 2) + 1);
var second = 3 - first;
var result = Math.floor((Math.random() * 2) + 1); // Get 1 or 2
console.log("Random was: " + result); // Test
var result2 = result === 1 ? 2 : 1; // Ternary to get 2 or 1 based on first #
console.log("Answer is: " + result2); // Test
var rest = Math.floor((Math.random() * 2) + 1);
var rest2 = rest === 1 ? 2 : 1;
console.log("Random " + rest);
console.log("Num: " + rest2);
Given that this is the only scenario your scripting will handle, you can do it with a simple if statement or a ternary like so:
if example
var firstRandomNumber = Math.floor((Math.random() * 2) + 1);
var secondRandomNumber;
if (firstRandomNumber === 1) {
secondRandomNumber = 2;
} else {
secondRandomNumber = 1;
}
Ternary example
var firstRandomNumber = Math.floor((Math.random() * 2) + 1);
var secondRandomNumber = firstRandomNumber === 2 ? 1 : 2;
So you want to generate the second number, given 1 you get 2 and given 2 you get 1.
You can use this for that:
num2 = num1 % 2 + 1
This uses the modulo operator which returns the remainder of integer division. i.e.:
1 % 2 == 1 // 1 / 2 = 0r1
2 % 2 == 0 // 2 / 2 = 1r0
I wish to use Javascript to generate a random number between 1 and 2
inclusive.
function getRandInteger(min, max) {
return Math.floor(min + (1 + max - min) * Math.random());
}
var myRandomNumb = getRandInteger(1, 2);
edit for integers only
But then I want to generate a second number, which if the first result
is 1, is 2; and if the first result is 2, is 1.
a simple if / ternary operator...
I created following generator for Czech tax number (IČO). I know that there is certainly better way how to code that in javascript. I am beginner and I would like to see how to write my code properly. The number is created with special formula and it has 8didgits, tha last digit is based on modulo11 as you can see below in code.
Thanks for your replies.
//Generation of single random numbers as variables
var a = Math.floor(Math.random() * 10);
var b = Math.floor(Math.random() * 10);
var c = Math.floor(Math.random() * 10);
var d = Math.floor(Math.random() * 10);
var e = Math.floor(Math.random() * 10);
var f = Math.floor(Math.random() * 10);
var g = Math.floor(Math.random() * 10);
//Formula for tax number
var formula = a * 8 + b * 7 + c * 6 + d * 5 + e * 4 + f * 3 + g * 2;
var modulo11 = formula % 11;
if (modulo11 === 0) {
var h = 1;
} else if (modulo11 === 1) {
var h = 0;
} else {
var h = 11 - modulo11;
};
//Completing tax number
var identificationNumber = "" + a + b + c + d + e + f + g + h;
//displaying number in console
console.log(identificationNumber);
Take benefit from Array data structure to store a, b,...g.
Then "map" this array by (8- indexOfItem) * item
👉🏼 so , for the 1ˢᵗ item which has index = 0 , we will have (8 - 0) * a -➡ 8* a.
👉🏼 for the 2ⁿᵈ item ➡ (8 -1) * b ➡ 7 *b
👉🏼....so on.
Then use "reduce" to calculate the sum .
Then use "join" instead of ""+ a +b + ....+ g+ h
function getH(modulo11) {
if (modulo11 === 0) return 1;
if (modulo11 === 1) return 0;
return 11 - modulo11;
}
//Generation of single random numbers as variables
const numbers= Array.from({length: 7},(v, k) =>Math.floor(Math.random() * 10))
//Formula for tax number
const formula= numbers.map((n, i) => (8 - i) * n).reduce((total, next) => total+ next , 0)// alternative of sum : a * 8 + b * 7 + c * 6 + d * 5 + e * 4 + f * 3 + g * 2
const h= getH(formula % 11);
//Completing tax number
const identificationNumber = [...numbers, h].join('');
//displaying number in console
console.log(identificationNumber);