Finding Gapful number in javascript - javascript

A number is gapful if it is at least 3 digits long and is divisible by the number formed by stringing the first and last numbers together.
The smallest number that fits this description is 100. First digit is
1, last digit is 0, forming 10, which is a factor of 100. Therefore,
100 is gapful.
Create a function that takes a number n and returns the closest gapful
number (including itself). If there are 2 gapful numbers that are
equidistant to n, return the lower one.
Examples gapful(25) ➞ 100
gapful(100) ➞ 100
gapful(103) ➞ 105
so to solve this i wrote the code that loops from the given number to greater than that and find out if it is or not by
function getFrequency(array){
var i=array
while(i>=array){
let a=i.toString().split('')
let b=a[0]+a[a.length-1]
b= +b
if(i%b==0) return i
i++
}
}
console.log(getFrequency(103))
Thats fine but what if the gapful number is less than the number passed in the function ?
like if i pass 4780 the answer is 4773 so in my logic how do i check simultaneoulsy smaller and greater than the number passed ?
I am only looping for the numbers greater than the number provided in function

You can alternate between subtracting and adding. Start at 0, then check -1, then check +1, then check -2, then check +2, etc:
const gapful = (input) => {
let diff = 0; // difference from input; starts at 0, 1, 1, 2, 2, ...
let mult = 1; // always 1 or -1
while (true) {
const thisNum = input + (diff * mult);
const thisStr = String(thisNum);
const possibleFactor = thisStr[0] + thisStr[thisStr.length - 1];
if (thisNum % possibleFactor === 0) {
return thisNum;
}
mult *= -1;
if (mult === 1) {
diff++;
}
}
};
console.log(
gapful(100),
gapful(101),
gapful(102),
gapful(103),
gapful(104),
gapful(105),
gapful(4780),
);

You could take separate functions, one for a check if a number is a gapful number and another to get left and right values and for selecting the closest number.
function isGapful(n) {
if (n < 100) return false;
var temp = Array.from(n.toString());
return n % (temp[0] + temp[temp.length - 1]) === 0;
}
function getClosestGapful(n) {
var left = n,
right = n;
while (!isGapful(right)) right++;
if (n < 100) return right;
while (!isGapful(left)) left--;
return n - left <= right - n
? left
: right;
}
console.log(getClosestGapful(25)); // 100
console.log(getClosestGapful(100)); // 100
console.log(getClosestGapful(103)); // 105
console.log(getClosestGapful(4780)); // 4773

Related

javascript function edge cases solving

function doNf(num, left, right) {
let numStr = num.toString();
const numArray = numStr.split('.');
let leftPart = numArray[0]; // Grab the left part of numStr
// Determine how many times to loop based on left and leftPart
const timesToLoop = left - leftPart.length;
if (typeof right === 'undefined') {
for (let i = 0; i < timesToLoop; i++) {
numStr = '0' + numStr; // Add a 0 to the beginning of numStr
}
return numStr;
} else {
let rightRounded = num.toFixed(right); // Round num to right decimals
numStr = rightRounded.toString();
for (let i = 0; i < timesToLoop; i++) {
numStr = '0' + numStr; // Add a 0 to the beginning of numStr
}
}
return numStr;
}
This Function is basically a modified rounding-off function. It works correctly but there are few edge cases that i am unable to handle, need help with that.
for (let i = 0; i < 10; i++) {
const n = Math.pow(10, -i);
console.log(i, n, doNf(n, 4, 2));
}
This gives output like:
0 1 0001.00
1 0.1 0000.10
2 0.01 0000.01
3 0.001 0000.00
4 0.0001 0000.00
5 0.00001 0000.00
6 0.000001 0000.00
7 1e-7 0.00
8 1e-8 0.00
9 1e-9 0.00
case 7,8,9 are behaving incorrectly.
there should be exactly 4 zeros before decimal since left = 4. I even checked that the typeof those 0.00 is string, but i am unable to figure out why the concatanation is not happening??
You should avoid using toString() as that will produce scientific notation. In that case no . is found in the string, which breaks the algorithm.
Instead, use toFixed immediately and pad the result at the left so it has the required digits before the decimal point.
There are maybe some boundary cases to deal with:
When right is 0, there will be no decimal point in the result; the padding should take this into account
When left is 0, you maybe want the results to start with a decimal point. toFixed always produces at least one digit before the decimal point.
When the given number has an absolute value is too great to be represented in the given format, the left restriction is ignored (as padLeft will do).
function doNf(num, left, right) {
let s = num.toFixed(right).padStart(left+right+!!right, "0");
return left ? s : s.replace(/^0/, "");
}
for (let i = 0; i < 10; i++) {
let n = 1 / 10 ** i;
console.log(i, n, doNf(n, 4, 2));
}

Count how many palindrome numbers are on the segment [1, 10 ** n] (n <100)

It is necessary to calculate how many palindrome numbers are on the segment [1, 10 ** n] (n <100).
function f(n) {
let res = 10 ** (parseInt(n / 2) + n % 2);
return res - res / 10;
}
function countPalindromes(n) {
let count = 0;
for (let i = 1; i <= n; i++) {
count += f(i);
}
return count;
}
for (let i = 1; i < 100; i++) {
console.log(i, f(i), countPalindromes(i));
}
Problems:
Over time js returns the result in exponential form, and the result cannot be translated into a string.
Adding such large numbers into a column does not work
And so, how can I count the number of palindromes in the segment [1, 10 ** n] (n <100)???
Let's start with a smaller problem first. How many n digit palindromic numbers exist?
If n is even, let the number be of the form _ _ _ _ (midpoint) _ _ _ _. Now, in the first digit, you can't fill 0, so you have 9 options (1-9). For the second digit to the n/2th digit, you can fill any of the digits in 0-9. Since we're dealing with palindromes, second half of the number will have the same digits as the first half. So, using basic counting, total number of n digit palindromes when n is even is 9*[10*10*...10 (n/2)-1 times] = 9 * 10^((n/2)-1)
When n is odd, the analysis will be similar, but with two differences:
You have 10 choices (0-9) for the midpoint.
There are (n-1)/2 digits on either side of the midpoint, where the first digit can't be 0.
Again, using basic counting, number of palindromes if n is odd = 9 (for first digit) * 10 (for midpoint) * 10^((n/2)-2) (the remaining digits) = 9 * (10^(n/2)-1), similar to the even case.
Thus, number of n digit palindromes = 9 * (10^(n/2)-1) if n is greater than 1. After that, you just have to loop n from 2 to 100 to get the total count of palindromic numbers you need.
I'm not 100% sure, so correct me if I'm wrong. It works, check the code at the bottom.
There should be two kinds of palindromes: ones with odd number of digits and ones with even number of digits. You can go from one palindrome to another (of the same kind) by appending and prepending the same digit to the first one. So...
Single-digit palindromes: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
For every single-digit palindrome, we can construct 10 3-digit palindromes:
000, 101, 202, ..., 010, 111, 212, ..., 898, 999.
Similarly, for every 3-digit palindromes, we can construct 10 5-digit palindromes.
10 ** n would have up to n-digit palindromes. Let's count:
10 ** 1 single-digit, 10 ** 2 3-digit, 10 ** 3 5-digit, ..., 10 ** ((n + 1) / 2) n-digit.
The same can be done for double-digit palindromes (00, 11, 22, 33, 44, 55, 66, 77, 88, 99), to iteratively obtain palindromes with an even number of digits.
Then we need to drop the 'illegal' numbers - numbers starting with the digit 0.
It works. Yay!
// Counting without creating the numbers
function getSmartCount(n) {
let smartPalindromeCount = 0;
let startingWithZeroCount = 0;
for (let digits = 1; digits <= n; digits += 2) { // even digits
const power = (digits + 1) / 2;
smartPalindromeCount += 10 ** power;
startingWithZeroCount += 10 ** (power - 1); // the zero-x-zero numbers
}
for (let digits = 2; digits <= n; digits += 2) { // odd digits
const power = digits / 2;
smartPalindromeCount += 10 ** power;
startingWithZeroCount += 10 ** (power - 1); // the zero-x-zero numbers;
}
return smartPalindromeCount - startingWithZeroCount;
}
// Counting by creating the numbers
function getCountIteratively(n) {
const singleDigitPalindromes = '0123456789'.split('');
const doubleDigitPalindromes = singleDigitPalindromes.map(x => x + x);
const palindromes = [...singleDigitPalindromes, ...doubleDigitPalindromes];
const nestedPalindromes = [
singleDigitPalindromes,
doubleDigitPalindromes,
];
for (let digits = 3; digits <= n; digits++) {
const index = digits - 1;
const extraPalindromes = [];
const previousPalindromes = nestedPalindromes[index - 2];
for (const previousPalindrome of previousPalindromes) {
for (const character of singleDigitPalindromes) {
const newPalindrome = character + previousPalindrome + character;
extraPalindromes.push(newPalindrome);
palindromes.push(newPalindrome);
}
}
nestedPalindromes.push(extraPalindromes);
}
const legalPalindromes = palindromes.filter(palindrome => palindrome[0] !== '0');
// console.log(legalPalindromes); // uncomment to see the numbers
return legalPalindromes.length;
}
// Counting by checking every single number
function getCountByBruteForce(n) {
const bruteForcePalindromes = [];
for (let i = 1; i < 10 ** n; i++) {
const leftToRight = i.toString();
const rightToLeft = leftToRight.split('').reverse().join('');
if (leftToRight === rightToLeft) {
bruteForcePalindromes.push(i);
}
}
// console.log(bruteForcePalindromes); // uncomment to see the numbers
return bruteForcePalindromes.length;
}
for (let n = 2; n <= 5; n++) {
console.log({
n,
smart: getSmartCount(n),
byCreatingTheNumbers: getCountIteratively(n),
bruteForce: getCountByBruteForce(n),
});
}

Javascript Find Nth Digit Number Algorithm Performance [duplicate]

I want to generate the value being searched by the position entered in the check. For example, if 20 is entered, the function should generate numbers starting from 0 and continue in ascending order until 20 digits are created, then output the value of the 20th digit in the generated number string (01234567891011121314), which is 4.
I tried this below, however it is not efficient when it comes to numbers like 1,000,000,000,
[...Array(5).keys()]; output => [0, 1, 2, 3, 4]
Edit this post to clarify I am trying to get a more efficient solution.
Here I am trying to get the answer for long numbers(1,000,000,000) in below one second.
I already have a solution but it takes more than 1 second.
[...Array(5).keys()].join("")[4]; output => 4
This is nearly identical to the Champernowne constant.
A solution from math.stackexchange is:
(Stack Overflow doesn't support MathJax, unfortunately)
The first step is to find what decade you are in. There are 9 digits from the 1 digit numbers, 2⋅90=180 digits from the 2 digit numbers for a total of 189, and generally n⋅9⋅10n−1 from the n digit numbers. Once you have found the decade, you can subtract the digits from the earlier decades. So if you want the 765th digit, the first 189 come from the first and second decades, so we want the 576th digit of the 3 digit numbers. This will come in the ⌈5763⌉=192nd number, which is 291. As 576≡3(mod3), the digit is 1
Programatically:
const getDigit = (target) => {
let i = 0;
let xDigitNumbers = 1; // eg 1 digit numbers, 2 digit numbers
let digitsSoFar = 1;
while (true) {
const digitsThisDecade = xDigitNumbers * 9 * 10 ** (xDigitNumbers - 1);
if (digitsSoFar + digitsThisDecade > target) {
// Then this is the "decade" in which the target digit is
// digitIndexThisDecade: eg, starting from '100101102', to find the last '1' in '101', digitIndexThisDecade will be 6
const digitIndexThisDecade = target - digitsSoFar;
// numIndexThisDecade: this identifies the index of the number in the decade
// eg, starting from '100101102', this could be index 2 to correspond to 101 (one-indexed)
const numIndexThisDecade = Math.floor(digitIndexThisDecade / xDigitNumbers);
// decadeStartNum: the number right before the decade starts (0, 9, 99, 999)
const decadeStartNum = 10 ** (xDigitNumbers - 1);
// num: the number in which the target index lies, eg 101
const num = decadeStartNum + numIndexThisDecade;
// digitIndexInNum: the digit index in num that the target is
// eg, for 101, targeting the last '1' will come from a digitIndexInNum of 2 (zero-indexed)
const digitIndexInNum = digitIndexThisDecade % xDigitNumbers;
return String(num)[digitIndexInNum]
}
digitsSoFar += digitsThisDecade;
xDigitNumbers++;
}
};
for (let i = 0; i < 1000; i++) {
document.write(`${i}: ${getDigit(i)}<br>`);
}
Here's a simple approach without using arrays.
let N = 1000000000, digitsCount = 0, currentNumber = 0;
console.time('Took time: ');
const digits = (x)=>{
if(x<10)
return 1;
if(x<100)
return 2;
if(x<1000)
return 3;
if(x<10000)
return 4;
if(x<100000)
return 5;
if(x<1000000)
return 6;
if(x<10000000)
return 7;
if(x<100000000)
return 8;
if(x<1000000000)
return 9;
return 10; // Default
}
while(true){
digitsCount += digits(currentNumber);
if(digitsCount >= N)
break;
currentNumber++;
}
console.timeEnd('Took time: ');
console.log(String(currentNumber)[N-digitsCount+digits(currentNumber)-1])
Output (The execution time may differ for you but it'll be under 1 second(or 1000ms).)
Took time: : 487.860ms
9
i used .join("") to convert the array to string '01234567891011121314151617181920'
then access the Nth number by Indexing string
N=20;
console.log ( [...Array(N+1).keys()].join("")[N-1] ) //OUTPUT 4
EDIT:i think ther's a solution which is you don't need to create array at all😎
its a mathematical formula
Blockquote
In my Solution , we don't need big iterations and loops...
But This Solution is Big for simple understanding...
I made it for upto 6 digits , and its very efficient...and can be made for any number of digits... And can even be reduced to small functions , but that would get too complex to understand...
So , Total numbers for Given Digits :
For 1 Digit Numbers , They are 10 (0 to 9)....
For 2 Digit Numbers , They are 9*10 => 90 , and total Digits ==> 90*2 ==> 180...
For 3 Digit Numbers , 9*10*10 => 900 , and total Digits ==> 90*3 ==> 2700...
For 4 Digit Numbers , 9*10*10*10 => 9000 , and total Digits ==> 9000*4 ==> 36000...
A function to get Total Digits for a given specified (Number of Digits)
let totalDigits = n => {
if (n == 1) return 10;
return 9 * (10 ** (n - 1)) * n;
}
Now , we set a Range of position for different Digits ,
for 1 Digit , its between 1 and 10....
for 2 Digits , It's Between 11(1+10) and 190(180+10)...(position of 1 in 10 is 11 , and Second 9 in 99 is 190)...
for 3 Digits , It's Between 191(1+10+180) and 2890(2700+180+10)...And so on
for n Digit , Function to get Range is
// This function is used to find Range for Positions... Eg : 2 digit Numbers are upto Position 190...(Position 191 is "100" first digit => 1 )
let digitN = n => {
if (n == 1) return totalDigits(1);
return digitN(n - 1) + totalDigits(n);
}
// To Finally set Ranege for a Given Digit Number... for 1 its [1,10] , for 2 its [11,190]
let positionRange = n => {
if (n == 1) return [1, 10];
else return [digitN(n - 1), digitN(n)]
}
So Final Solution is
// This Function tells the total number of digits for the given digit... Eg : there are 10 one digit Numbers , 180 Two Digit Numbers , 2700 3 Digit Numbers
let totalDigits = n => {
if (n == 1) return 10;
return 9 * (10 ** (n - 1)) * n;
}
// This function is used to find Range for Positions... Eg : 2 digit Numbers are upto Position 190...(Position 191 is "100" first digit => 1 )
let digitN = n => {
if (n == 1) return totalDigits(1);
return digitN(n - 1) + totalDigits(n);
}
// To Finally set Ranege for a Given Digit Number... for 1 its [1,10] , for 2 its [11,190]
let positionRange = n => {
if (n == 1) return [1, 10];
else return [digitN(n - 1), digitN(n)]
}
// A simple Hack to get same value for Different Consecutive Numbers , (0.3 or 0.6 or 0.9 or 1 return 1)
let getDigit = n => {
if (dataType(n) == "float") {
n = Math.floor(n);
n++;
}
return n;
}
// To check for Float or Integer Values
function dataType(x) {
if (Math.round(x) === x) {
return 'integer';
}
return 'float';
}
function f(position) {
let result, charInd, temp;
if ((position >= positionRange(1)[0]) && (position <= positionRange(1)[1])) { // Positions 1 to 10 (1 Digit Numbers)
result = position - 1;
charInd = 0
}
if ((position > positionRange(2)[0]) && (position <= positionRange(2)[1])) { // Positions 11 to 190 (2 Digit Numbers)
temp = (position - 10) / 2;
temp = getDigit(temp);
result = temp + 9;
charInd = (position - 11) % 2
}
if ((position > positionRange(3)[0]) && (position <= positionRange(3)[1])) { // Positions 191 to 2890 (3 Digit Numbers)
temp = (position - 190) / 3;
temp = getDigit(temp);
result = temp + 99;
charInd = (position - 191) % 3
}
if ((position > positionRange(4)[0]) && (position <= positionRange(4)[1])) { // Positions 2891 to 38890 (4 Digit Numbers)
temp = (position - 2890) / 4;
temp = getDigit(temp);
result = temp + 999;
charInd = (position - 2891) % 4
}
if ((position > positionRange(5)[0]) && (position <= positionRange(5)[1])) { // Positions 38890 to 488890 (5 Digit Numbers)
temp = (position - 38890) / 5;
temp = getDigit(temp);
result = temp + 9999;
charInd = (position - 38891) % 5
}
if ((position > positionRange(6)[0]) && (position <= positionRange(6)[1])) { // Positions 488890 to 5888890 (6 Digit Numbers)
temp = (position - 488890) / 6 ;
temp = getDigit(temp);
result = temp + 99999;
charInd = (position - 488891) % 6
}
finalChar = String(result)[charInd];
console.log("Given Position => ", position, " Result Number => ", result, "Char Index ==> ", charInd, "Final Char => ", finalChar);
}
let d1 = Date.now();
f(138971); // Given Position => 138971 Result Number => 30016 Char Index ==> 0 Final Char => 3
let d2 = Date.now();
console.log(d2-d1) ; // 351

Generate numbers in sequence Order

I want to generate the value being searched by the position entered in the check. For example, if 20 is entered, the function should generate numbers starting from 0 and continue in ascending order until 20 digits are created, then output the value of the 20th digit in the generated number string (01234567891011121314), which is 4.
I tried this below, however it is not efficient when it comes to numbers like 1,000,000,000,
[...Array(5).keys()]; output => [0, 1, 2, 3, 4]
Edit this post to clarify I am trying to get a more efficient solution.
Here I am trying to get the answer for long numbers(1,000,000,000) in below one second.
I already have a solution but it takes more than 1 second.
[...Array(5).keys()].join("")[4]; output => 4
This is nearly identical to the Champernowne constant.
A solution from math.stackexchange is:
(Stack Overflow doesn't support MathJax, unfortunately)
The first step is to find what decade you are in. There are 9 digits from the 1 digit numbers, 2⋅90=180 digits from the 2 digit numbers for a total of 189, and generally n⋅9⋅10n−1 from the n digit numbers. Once you have found the decade, you can subtract the digits from the earlier decades. So if you want the 765th digit, the first 189 come from the first and second decades, so we want the 576th digit of the 3 digit numbers. This will come in the ⌈5763⌉=192nd number, which is 291. As 576≡3(mod3), the digit is 1
Programatically:
const getDigit = (target) => {
let i = 0;
let xDigitNumbers = 1; // eg 1 digit numbers, 2 digit numbers
let digitsSoFar = 1;
while (true) {
const digitsThisDecade = xDigitNumbers * 9 * 10 ** (xDigitNumbers - 1);
if (digitsSoFar + digitsThisDecade > target) {
// Then this is the "decade" in which the target digit is
// digitIndexThisDecade: eg, starting from '100101102', to find the last '1' in '101', digitIndexThisDecade will be 6
const digitIndexThisDecade = target - digitsSoFar;
// numIndexThisDecade: this identifies the index of the number in the decade
// eg, starting from '100101102', this could be index 2 to correspond to 101 (one-indexed)
const numIndexThisDecade = Math.floor(digitIndexThisDecade / xDigitNumbers);
// decadeStartNum: the number right before the decade starts (0, 9, 99, 999)
const decadeStartNum = 10 ** (xDigitNumbers - 1);
// num: the number in which the target index lies, eg 101
const num = decadeStartNum + numIndexThisDecade;
// digitIndexInNum: the digit index in num that the target is
// eg, for 101, targeting the last '1' will come from a digitIndexInNum of 2 (zero-indexed)
const digitIndexInNum = digitIndexThisDecade % xDigitNumbers;
return String(num)[digitIndexInNum]
}
digitsSoFar += digitsThisDecade;
xDigitNumbers++;
}
};
for (let i = 0; i < 1000; i++) {
document.write(`${i}: ${getDigit(i)}<br>`);
}
Here's a simple approach without using arrays.
let N = 1000000000, digitsCount = 0, currentNumber = 0;
console.time('Took time: ');
const digits = (x)=>{
if(x<10)
return 1;
if(x<100)
return 2;
if(x<1000)
return 3;
if(x<10000)
return 4;
if(x<100000)
return 5;
if(x<1000000)
return 6;
if(x<10000000)
return 7;
if(x<100000000)
return 8;
if(x<1000000000)
return 9;
return 10; // Default
}
while(true){
digitsCount += digits(currentNumber);
if(digitsCount >= N)
break;
currentNumber++;
}
console.timeEnd('Took time: ');
console.log(String(currentNumber)[N-digitsCount+digits(currentNumber)-1])
Output (The execution time may differ for you but it'll be under 1 second(or 1000ms).)
Took time: : 487.860ms
9
i used .join("") to convert the array to string '01234567891011121314151617181920'
then access the Nth number by Indexing string
N=20;
console.log ( [...Array(N+1).keys()].join("")[N-1] ) //OUTPUT 4
EDIT:i think ther's a solution which is you don't need to create array at all😎
its a mathematical formula
Blockquote
In my Solution , we don't need big iterations and loops...
But This Solution is Big for simple understanding...
I made it for upto 6 digits , and its very efficient...and can be made for any number of digits... And can even be reduced to small functions , but that would get too complex to understand...
So , Total numbers for Given Digits :
For 1 Digit Numbers , They are 10 (0 to 9)....
For 2 Digit Numbers , They are 9*10 => 90 , and total Digits ==> 90*2 ==> 180...
For 3 Digit Numbers , 9*10*10 => 900 , and total Digits ==> 90*3 ==> 2700...
For 4 Digit Numbers , 9*10*10*10 => 9000 , and total Digits ==> 9000*4 ==> 36000...
A function to get Total Digits for a given specified (Number of Digits)
let totalDigits = n => {
if (n == 1) return 10;
return 9 * (10 ** (n - 1)) * n;
}
Now , we set a Range of position for different Digits ,
for 1 Digit , its between 1 and 10....
for 2 Digits , It's Between 11(1+10) and 190(180+10)...(position of 1 in 10 is 11 , and Second 9 in 99 is 190)...
for 3 Digits , It's Between 191(1+10+180) and 2890(2700+180+10)...And so on
for n Digit , Function to get Range is
// This function is used to find Range for Positions... Eg : 2 digit Numbers are upto Position 190...(Position 191 is "100" first digit => 1 )
let digitN = n => {
if (n == 1) return totalDigits(1);
return digitN(n - 1) + totalDigits(n);
}
// To Finally set Ranege for a Given Digit Number... for 1 its [1,10] , for 2 its [11,190]
let positionRange = n => {
if (n == 1) return [1, 10];
else return [digitN(n - 1), digitN(n)]
}
So Final Solution is
// This Function tells the total number of digits for the given digit... Eg : there are 10 one digit Numbers , 180 Two Digit Numbers , 2700 3 Digit Numbers
let totalDigits = n => {
if (n == 1) return 10;
return 9 * (10 ** (n - 1)) * n;
}
// This function is used to find Range for Positions... Eg : 2 digit Numbers are upto Position 190...(Position 191 is "100" first digit => 1 )
let digitN = n => {
if (n == 1) return totalDigits(1);
return digitN(n - 1) + totalDigits(n);
}
// To Finally set Ranege for a Given Digit Number... for 1 its [1,10] , for 2 its [11,190]
let positionRange = n => {
if (n == 1) return [1, 10];
else return [digitN(n - 1), digitN(n)]
}
// A simple Hack to get same value for Different Consecutive Numbers , (0.3 or 0.6 or 0.9 or 1 return 1)
let getDigit = n => {
if (dataType(n) == "float") {
n = Math.floor(n);
n++;
}
return n;
}
// To check for Float or Integer Values
function dataType(x) {
if (Math.round(x) === x) {
return 'integer';
}
return 'float';
}
function f(position) {
let result, charInd, temp;
if ((position >= positionRange(1)[0]) && (position <= positionRange(1)[1])) { // Positions 1 to 10 (1 Digit Numbers)
result = position - 1;
charInd = 0
}
if ((position > positionRange(2)[0]) && (position <= positionRange(2)[1])) { // Positions 11 to 190 (2 Digit Numbers)
temp = (position - 10) / 2;
temp = getDigit(temp);
result = temp + 9;
charInd = (position - 11) % 2
}
if ((position > positionRange(3)[0]) && (position <= positionRange(3)[1])) { // Positions 191 to 2890 (3 Digit Numbers)
temp = (position - 190) / 3;
temp = getDigit(temp);
result = temp + 99;
charInd = (position - 191) % 3
}
if ((position > positionRange(4)[0]) && (position <= positionRange(4)[1])) { // Positions 2891 to 38890 (4 Digit Numbers)
temp = (position - 2890) / 4;
temp = getDigit(temp);
result = temp + 999;
charInd = (position - 2891) % 4
}
if ((position > positionRange(5)[0]) && (position <= positionRange(5)[1])) { // Positions 38890 to 488890 (5 Digit Numbers)
temp = (position - 38890) / 5;
temp = getDigit(temp);
result = temp + 9999;
charInd = (position - 38891) % 5
}
if ((position > positionRange(6)[0]) && (position <= positionRange(6)[1])) { // Positions 488890 to 5888890 (6 Digit Numbers)
temp = (position - 488890) / 6 ;
temp = getDigit(temp);
result = temp + 99999;
charInd = (position - 488891) % 6
}
finalChar = String(result)[charInd];
console.log("Given Position => ", position, " Result Number => ", result, "Char Index ==> ", charInd, "Final Char => ", finalChar);
}
let d1 = Date.now();
f(138971); // Given Position => 138971 Result Number => 30016 Char Index ==> 0 Final Char => 3
let d2 = Date.now();
console.log(d2-d1) ; // 351

javaScript - Find the sum of all divisors of a given integer

i'm doing some coding exercises and i'm not being able to solve this one.
Find the sum of all divisors of a given integer.
For n = 12, the input should be
sumOfDivisors(n) = 28.
example: 1 + 2 + 3 + 4 + 6 + 12 = 28.
Constraints:
1 ≤ n ≤ 15.
how can i solve this exercise? i'm not being able to.
function(n){
var arr = [],
finalSum;
if(n <= 1 || n => 16){
return false ;
}
for(var i = 0; i < n; i++){
var tmp= n/2;
arr.push(tmp)
// i need to keep on dividing n but i can't get the way of how to
}
return finalSum;
}
This is another way to do it:
var divisors = n=>[...Array(n+1).keys()].slice(1)
.reduce((s, a)=>s+(!(n % a) && a), 0);
console.log(divisors(12));
JSFiddle: https://jsfiddle.net/32n5jdnb/141/
Explaining:
n=> this is an arrow function, the equivalent to function(n) {. You don't need the () if there's only one parameter.
Array(n+1) creates an empty array of n+1 elements
.keys() gets the keys of the empty array (the indexes i.e. 0, 1, 2) so this is a way to create a numeric sequence
[...Array(n+1)].keys()] uses the spread (...) operator to transform the iterator in another array so creating an array with the numeric sequence
.slice(1) removes the first element thus creating a sequence starting with 1. Remember the n+1 ?
.reduce() is a method that iterates though each element and calculates a value in order to reduce the array to one value. It receives as parameter a callback function to calculate the value and the initial value of the calculation
(s, a)=> is the callback function for reduce. It's an arrow function equivalent to function(s, a) {
s+(!(n % a) && a) is the calculation of the value.
s+ s (for sum) or the last value calculated +
!(n % a) this returns true only for the elements that have a 0 as modular value.
(!(n % a) && a) is a js 'trick'. The case is that boolean expressions in javascript don't return true or false. They return a 'truthy' or 'falsy' value which is then converted to boolean. So the actual returned value is the right value for && (considering both have to be truthy) and the first thuthy value found for || (considering only one need to be truthy). So this basically means: if a is a modular value (i.e. != 0) return a to add to the sum, else return 0.
, 0 is the initial value for the reduce calculation.
Reduce documentation: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Edit
Answering to Tristan Forward:
var divisorsList = [];
var divisors = (n)=>[...Array(n+1).keys()].slice(1)
.reduce((s, a)=>{
var divisor = !(n % a) && a;
if (divisor) divisorsList.push(divisor);
return s+divisor;
}, 0);
console.log('Result:', divisors(12));
console.log('Divisors:', divisorsList);
You have to check if specified number is or not a divisor of given integer. You can use modulo % - if there's no rest, specified number is the divisor of the given integer - add it to the sum.
function sumDivisors(num){
var sum = 0;
for (var i = 1; i <= num; i++){
if (!(num % i)) {
sum += i;
}
}
console.log(sum);
}
sumDivisors(6);
sumDivisors(10);
Here is a solution with better algorithm performance (O(sqrt(largest prime factor of n)))
divisors = n => {
sum = 1
for (i = 2; n > 1; i++) {
i * i > n ? i = n : 0
b = 0
while (n % i < 1) {
c = sum * i
sum += c - b
b = c
n /= i
}
}
return sum
}
since n / i is also a devisor this can be done more efficiently.
function sumDivisors(num) {
let sum = 1;
for (let i = 2; i < num / i; i++) {
if (num % i === 0) {
sum += i + num / i;
}
}
const sqrt = Math.sqrt(num);
return num + (num % sqrt === 0 ? sum + sqrt : sum);
}
function countDivisors(n){
let counter = 1;
for(let i=1; i <= n/2; i++){
n % i === 0 ? counter++ : null;
}
return counter
}
in this case, we consider our counter as starting with 1 since by default all numbers are divisible by 1. Then we half the number since numbers that can be able to divide n are less or equal to half its value

Categories