How to shuffle a number following a sequence (not random) - javascript

I need to build a function that returns a given number shuffled writing one digit from the front of the number and the following taken from the back, then the 3rd digit from the front of the number and the 4th from the back and so on.
Example:
const initialNumber = 123456 should return
const finalNumber = 162534
or
const initialNumber2 = 104 should return
const finalNumber2 = 140
Also, the number should be between the values of 0 and 100.000.000.
How to do it? Should I first transform the number into an array first of all using the split() method and then using a for loop?

You can do it with splitting the input into array and reduce:
const shuffle = input => input.toString().split('').reduce((acc, item, index, data) => {
const arr = (index % 2 ? data.slice().reverse() : data);
return acc.concat(arr[Math.floor(index / 2)]);
}, []).join('');
console.log(shuffle(104)); // 140
console.log(shuffle(123456)); // 162534
console.log(shuffle(1234567)); // 1726354
A bit reduced code:
const shuffle = input => input.toString().split('').reduce((acc, item, index, data) =>
acc.concat((index % 2 ? data.slice().reverse() : data)[Math.floor(index / 2)]), []
).join('');

I would prefer converting the number to a string, then using that string in a for loop.
function shuffle(num) {
var str = num.toString();
var result = "";
if(!isNaN(num) && num >= 0 && num <= 100000000) {
for(var i = 0; i < str.length; i++) {
if(i % 2 == 0) {
result += str[Math.floor(i / 2)];
} else {
result += str[str.length - Math.floor(i / 2 + 1)];
}
}
}
return result;
}
console.log(shuffle(123456)); // 162534
console.log(shuffle(1234567)); // 1726354
console.log(shuffle(104)); // 140

This may work as a very basic algo.
function shuffleNum(num,i){
var numArr = num.toString().split('');
var front = numArr.splice(0,i);
var back = numArr.pop();
var shuffledArr = front.concat(back,numArr);
return parseFloat(shuffledArr.join(''));
}
// Test
var num = 12345;
for(var i=0;i<num.toString().length;i++){
num = shuffleNum(num);
console.log(num);
}
// Output
// 51234
// 45123
// 34512
// 23451
// 12345

The best way is to use array push function.
function shuffle(a) {
var b = a.toString();
var c = [];
for(let i=0; i<b.length/2; i++) {
c.push(b[i]);
if(i==(Math.ceil(b.length/2)-1) && b.length%2==1) continue;
c.push(b[b.length-i-1]);
}
return c.join("");
}

Java code snippet.
public static int solution(int a) {
int[] arr = Integer.toString(a).chars().map(e->e-'0').toArray();
System.out.println(Arrays.toString(arr));
int[] temp = new int[arr.length];
int j=1;
for(int i = 0; i<arr.length; i++) {
if(i % 2 == 0) {
temp[i] = arr[i/2];
} else {
temp[i] = arr[arr.length - j];
j++;
}
}
System.out.println(Arrays.toString(temp));

Related

Character with longest consecutive repetition

i think i have wirtten the correct code for the problem only one thing and it that i return the first longest sequence how can i alter that to return the last maximum sequence?
an example from codewars editor :
for input '00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'
Expected: ['c', 19], instead got: ['0', 19]
here is my code:
function longestRepetition(s) {
var count = 0;
var temp = s.charAt(0);
var arr = [];
for (var i = 0; i < s.length; i++) {
if (temp === s.charAt(i)) {
count++
temp = s.charAt(i)
}
else {
temp = s.charAt(i);
arr.push(count)
count = 1;
}
if(i==s.length-1)
arr.push(count);
}
if(arr.length>0)
{
var Max=arr[0]
for(var i=0;i<arr.length;i++)
{
if(Max<=arr[i])
Max=arr[i];
}
}
else var Max=0;
var mindex=arr.indexOf(Max);
return [s.charAt(mindex),Max]
}
I think this would be easier with a regular expression. Match any character, then backreference that character as many times as you can.
Then, you'll have an array of all the sequential sequences, eg ['000', 'aaaaa']. Map each string to its length and pass into Math.max, and you'll know how long the longest sequence is.
Lastly, filter the sequences by those which have that much length, and return the last item in the filtered array:
function longestRepetition(s) {
const repeatedChars = s.match(/(.)\1*/g);
const longestLength = Math.max(...repeatedChars.map(str => str.length));
const longestChars = repeatedChars.filter(str => str.length === longestLength);
return [longestChars.pop(), longestLength];
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
The issue in your code is that minindex is an index in your arr, but that index has nothing to do with s. So s.charAt(minindex) makes no sense. You should maintain for which character you had found the count. For instance you could push in arr both the count and the corresponding character (as a subarray with two values). Then the rest of your code would only need little modification to make it work.
Applying this idea to your code without changing anything else, we get this:
function longestRepetition(s) {
var count = 0;
var temp = s.charAt(0);
var arr = [];
for (var i = 0; i < s.length; i++) {
if (temp === s.charAt(i)) {
count++
temp = s.charAt(i) // Not necessary: was already equal
}
else {
arr.push([temp, count]); // <--- pair, BEFORE changing temp
temp = s.charAt(i);
count = 1;
}
if(i==s.length-1)
arr.push([temp, count]); // <---
}
if(arr.length>0)
{
var Max=arr[0]; // <-- Max is now a pair of char & count
for(var i=0;i<arr.length;i++)
{
if(Max[1]<arr[i][1]) // Comparison changed to just less-than
Max=arr[i];
}
}
else Max=[null, 0]; // Must be a pair here also
return Max; // Just return the pair
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
But you can do the same with less code:
function longestRepetition(s) {
let result = [null, 0]; // pair of character and count
for (var i = 0; i < s.length; null) {
let start = i++;
while (i < s.length && s[i] === s[start]) i++; // Find end of series
if (i - start > result[1]) result = [s[start], i - start];
}
return result;
}
console.log(longestRepetition('00000000000000111111111111111112222222222222223333333333333344444444444445555555555555666666666666777777777777888888888888888999999999999999999aaaaaaaaabbbbbbbbbbbbbbbbcccccccccccccccccccdddddddddddddddddddeeeeeeeeeeeeeeefffffffffffffggggggggggggggghhhhhhhhhhhhhiiiiiiiiiijjjjjjjjjjjjjjkkkkkkkkkkkkllllllllllmmmmmmmmmmnnnnnnnnnnnnnnoooooooooooopppppppppppppppppqqqqqqqqqqqqrrrrrrrrrrrrrrrrrrrssssssssssttttttttttttuuuuuuvvvvvvvvvvvvvvvvvwwwwwwwwwwwwwwwwxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyzzzzzzzzzzzzzz'));
The solution below answers the question with O(n) runtime:
function longestRepetition(s) {
let count = s.length > 0 ? 1 : 0
let char = s.length > 0 ? s[0] : ''
for (let string_i = 0; string_i < s.length - 1; string_i += 1) {
// keep track of current_char
let current_char = s[string_i]
let next_char = s[string_i + 1]
// while the next char is same as current_char
let tracker = 1
while (current_char === next_char) {
// add one to tracker
tracker += 1
string_i += 1
next_char = s[string_i + 1]
}
// if tracker greater than count
if (tracker > count) {
// returned char = current char
// count =tracker
count = tracker;
char = current_char;
}
}
return [char, count]
}
console.log(longestRepetition("bbbaaabaaaa"))//, ["a",4]

Use Recursion to Sum Digits until there is nothing left to sum

Question
Digital root is the recursive sum of all the digits in a number.
Given n, take the sum of the digits of n. If that value has more than one digit, continue reducing in this way until a single-digit number is produced. This is only applicable to the natural numbers.
My Code
function digital_root(n) {
let a = n.toString();
let ai = a.split('');
let bi = ai.map((item)=>{
return parseInt(item);
})
let newArr = [];
for(let i = 0; i < bi.length; i++){
let c = bi[i];
newArr.push(c);
}
let d = newArr.reduce((total, item)=>{
return total + item;
}, 0);
function recursive(d){
if(d < 10){
return d
}
a = d.toString();
ai = a.split('');
bi = ai.map((item)=>{
return parseInt(item);
});
newArr = [];
for(let i = 0; i < bi.length; i++){
let c = bi[i];
newArr.push(c);
}
d = newArr.reduce((total, item)=>{
return total + item;
}, 0);
return recursive(d);
}
return d;
}
console.log(digital_root(123));
console.log(digital_root(111));
console.log(digital_root(51024));
My Problem
For some reason the code doesn't seem to recognise that I need to run the operation again if d >= 9.
How can I resolve the problem with the code that I have already done?
Also out of interest, how would you approach it, my answer seems quite convoluted!
Let's put in some comments to see what is going on.
function digital_root(n) {
// convert multiple digit number to String
let a = n.toString();
// split the String into an array of single digit Strings
let ai = a.split('');
// convert String array into int array
let bi = ai.map((item)=>{
return parseInt(item);
})
// it looks like you are just copying the array here,
//I don't think there is a need for that
// let newArr = [];
// for(let i = 0; i < bi.length; i++){
// let c = bi[i];
// newArr.push(c);
// }
// reduce the int array to the sum of its digits
let d = bi.reduce((total, item)=>{
return total + item;
}, 0);
// That should be it, now just print it or recurse it
if (d < 10) {
return d;
}
// here is how you recurse, call the method from within the method
return digital_root(d);
// I'm not sure what you are doing here, you are repeating code
// this is not how recursion works
// function recursive(d){
// if(d < 10){
// return d
// }
// a = d.toString();
// ai = a.split('');
// bi = ai.map((item)=>{
// return parseInt(item);
// });
// newArr = [];
// for(let i = 0; i < bi.length; i++){
// let c = bi[i];
// newArr.push(c);
// }
// d = newArr.reduce((total, item)=>{
// return total + item;
// }, 0);
// return recursive(d);
// }
// return d;
}
console.log(digital_root(123));
console.log(digital_root(111));
console.log(digital_root(51024));
you never call recursive function you made, replace return d to return recursive(d);
How I would do this:
function digital_root(n){
return n < 10 ? n : digital_root(String(n).split('').reduce((acc,val) => acc+(val|0),0));
}
In addition to what Photon said, here's a simpler solution
function sum(n) {
if (n <= 9) {
return n;
} else {
return sum((n % 10) + sum(n / 10));
}
}
>>> sum(156)
... 3
>>> sum(9999)
... 9
>>> sum(10)
... 1

Multiplying N positive odd numbers

I'm trying to get the product of N positive odd numbers
function multOdd(n) {
var mult = 1;
var counter=[];
for (var i = 1; i <= 2*n-1; i += 2){
counter.push(i);
}
console.log(counter);
return mult=mult*counter[i];
}
console.log(multOdd(10));
I pushed the numbers into an array and attempted to get the product from them but I can't get it to work.
When you return mult=mult*counter[i] you're only returning the multipication once. It should return mult = 1 * counter[lastElement+2] which will be wrong. In your case, the last element of counter is 19, before exiting for loop i value is i= 19 + 2 = 21. You're returning mult = 1 * 21 = 21.
You can instead return the multipication value by for loop with no need for an array:
function multOdd(n) {
var mult = 1;
for (var i = 1; i <= 2*n-1; i += 2){
mult = mult * i;
}
return mult;
}
If you just want the result for n, use:
function multOdd(n) {
var result = 1;
for (var i = 1; i <= 2*n-1; i += 2){
result = result * i;
}
console.log(result);
return result;
}
console.log(multOdd(4));
If you want an array that has an array indexed by the number of odd numbers up to n you could use:
function multOdd(n) {
let result = 1;
let results = [];
for (let i = 1; i <= 2*n-1; i += 2){
result = result * i;
results[(i+1) / 2] = result;
}
console.log(results);
return results;
}
console.log(multOdd(10));
There are a few ways to get the product of an array of numbers. Here are two easy ones:
Relevant MDN
// Using `Array.prototype.reduce`
[3, 5, 7, 9].reduce((acc, val) => acc * val)
// Using a `for ... of` loop
let product = 1
for (const val of [3, 5, 7, 9]) {
product *= val
}
You could separate out the two steps of your current code into two functions:
const getFirstNOddNums = (n) => {
let oddNums = []
for (let i = 1; i <= 2*n-1; i+=2) {
oddNums.push(i)
}
return oddNums
}
const productOfArray = (arr) => {
return arr.reduce((a, b) => a * b)
}
const N = 5
const firstNOddNums = getFirstNOddNums(N)
console.log(`The first ${N} odd numbers are: ${JSON.stringify(firstNOddNums)}`)
console.log(`The product of the first ${N} odd numbers is: ${productOfArray(firstNOddNums)}`)
let multOdd = (n) => {
let total = 1;
for (let i = 1; i<= 2*n; i+=2){
total *= i;
}
return total;
}
console.log(multOdd(10));
Instead of recursion, We should use the standard mathematical formula for the product of first n positive odd integers which is
Can also be written as (in the form of pi notation)
For this latex image, I used https://codecogs.com/latex/eqneditor.php.
Factorial is
n! = n(n-1)(n-2)(n-3) ... and so on
So we can use Array(n).fill() to get an array of 10 elements and reduce them to get a factorial by
Array(n).fill().reduce((v,_,i) => (i+1) * v || 2)
Then we divide it by 2 to the power n times the n!. Which is what we want. The advantage here is that, this makes your solution, a one liner
let n = 10
let answer = Array(2*n).fill().reduce((v,_,i) => (i+1) * v || 2) / (Math.pow(2,n) * Array(n).fill().reduce((v,_,i) => (i+1) * v || 2))
console.log(answer)

Replace a letter with its alphabet position

This looked fairly straightforward to me when I started, but for some reason I'm getting an empty array everytime I try to run the result on codewars. I'm hoping you can help me identify what the problem is.
function alphabetPosition(text) {
text.split(' ').join('');
var chari = "";
var arr = [];
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for(var i = 0; i < text.len; i++){
chari = text.charAt(i).toLowerCase();
if(alphabet.indexOf(chari) > -1){
arr.push(alphabet.indexOf(chari));
}
}
return arr;
}
console.log(alphabetPosition("Hello World"));
My idea is to get the text from the parameter then strip out the spaces. I made a variable for my empty array and make an alphabet string that I can later search through. In the for loop, i make each character lowercase, and if the character is found in the alphabet string, its position gets pushed into the array (arr). I appreciate your time.
The Kata works with this code. Try with this one:
function alphabetPosition(text) {
var result = "";
for (var i = 0; i < text.length; i++) {
var code = text.toUpperCase().charCodeAt(i)
if (code > 64 && code < 91) result += (code - 64) + " ";
}
return result.slice(0, result.length - 1);
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
You need the String#length property
text.length
instead of text.len.
function alphabetPosition(text) {
var chari,
arr = [],
alphabet = "abcdefghijklmnopqrstuvwxyz",
i;
for (var i = 0; i < text.length; i++){
chari = text[i].toLowerCase();
if (alphabet.indexOf(chari) !== -1){
arr.push(alphabet.indexOf(chari));
}
}
return arr;
}
console.log(alphabetPosition("Hello World!!1"));
A solution with ES6
function alphabetPosition(text) {
return [...text].map(a => parseInt(a, 36) - 10).filter(a => a >= 0);
}
console.log(alphabetPosition("Hello World!!1"));
First : deleting space
Second : mapping each char with its alphabet rank
Third : test with the string Happy new year
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
var alphabetPosition = text =>
text.split('').map(x => alphabet.indexOf(x) + 1);
console.log(alphabetPosition("happy new year"));
function alphabetPosition(text) {
const words = text.toLowerCase().replace(/[^a-z]/g,"");
return [...words].map(v=> v.charCodeAt() - 96);
}
First we take the text and transform it into lowercase to get rid of the capital letters using text.toLowerCase() and then we do .replace(/[^a-z]/g,"") to replace all the non a-z characters with nothing.
The next step is to spread the string out into an array using [...words] and then mapping it to get the ascii character code of each a-z character.
Since a = 97 and b = 98 etc we will subtract 96 so that we get a = 1 and b = 2 etc (the position of the letters in the alphabet)
You can make it even easier, by making use of the acii code. Because a = ascii code 97, b = 98 etc. And there is a javascript function String.charCodeAt( n ) which returns the ascii code at a specific function. You only have to alter the offset for capitals (if you want to support them).
function alphabetPosition( text ) {
var positions = [];
for ( var i = 0; i < text.length; i++ ) {
var charCode = text.charCodeAt( i );
if ( charCode >= 97 && charCode <= 122 ) {
positions.push( charCode - 96 );
} else if ( charCode >= 65 && charCode <= 90 ) { // get rid of this if you don't care about capitals
positions.push( charCode - 64 );
}
}
return positions;
}
var positions = alphabetPosition( 'Hello World' );
console.log(positions);
Checkout this working fiddle
This example will return based on a 0 based array, and uses lambda expressions with filter. I recycle the original byte array created by splitting the text passed to the method.
function alphabetPosition(text) {
var bytes = text.split('');
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for (var i = 0, len = text.length; i < len; i++) {
bytes[i] = alphabet.indexOf(bytes[i].toLowerCase());
}
return bytes.filter(n => { if(n > -1) return n; } ).join(' ');
}
console.log(alphabetPosition("Hello World"));
For a 1 based array result Kata Codewars Friendly
function alphabetPosition(text) {
var bytes = text.split('');
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for (var i = 0, len = text.length; i < len; i++) {
bytes[i] = alphabet.indexOf(bytes[i].toLowerCase()) + 1;
}
return bytes.filter(n => { if(n > 0) return n; } ).join(' ');
}
console.log(alphabetPosition("Hello World"));
You can also use .charCodeAt function:
function alphabetPosition(text) {
start = "a".charCodeAt(0);
end = "z".charCodeAt(0);
res = [];
for (var i = 0; i < text.length; i++) {
index = text.charAt(i).toLowerCase().charCodeAt(0);
if (index >= start && index <= end) {
res.push(index - start +1); // +1 assuming a is 1 instead of 0
} else {
res.push(0); // Or do w/e you like with non-characters
}
}
return res;
}
console.log(alphabetPosition("Hello World"));
You may do something like this;
var alpha = [].reduce.call("abcdefghijklmnopqrstuvwxyz0123456789 .,!",(p,c,i) => (p[c] = i,p),{}),
str = "Happy 2017 whatever..!",
coded = [].map.call(str, c => alpha[c.toLowerCase()]);
console.log(coded);
change len to length:
(var i = 0; i < text.len; i++)
// change to
(var i = 0; i < text.length; i++)
Here is a much shorter version that does the same:
function alphabetPosition(text){
return text.split('').map(function(character){ return character.charCodeAt(0) - 'a'.charCodeAt(0) + 1; })
}
console.log(alphabetPosition("Hello World"));
This was my solution on CodeWars. Works perfectly ;)
let alphabetPosition = (text) => {
let str = Array.from(text.toLowerCase().replace(/[^a-z]/g,''));
let arr = [];
for (let i = 0; i < str.length; i++) {
arr.push(str[i].charCodeAt() - 96);
}
return arr.join(' ');
}
my answer
function alphabetPosition(text) {
if (text.match(/[a-z]/gi)) { // if text is not emtpty
let justAlphabet = text.match(/[a-z]/gi).join("").toLowerCase(); //first extract characters other than letters
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let a = []; // Create an empty array
for (let i = 0; i < justAlphabet.length; i++) {
a.push(alphabet.indexOf(justAlphabet[i]) + 1); //and characters index number push in this array
}
return a.join(" ");
} else {
return "";
}
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
this one should work
const lineNumberHandler = (arr) => {
const alphabet = 'abcdefghijklmnopqrstuwxyz';
return arr.map((el) => `${alphabet.indexOf(el) + 1}:${el}`);
}
This may solve the issue too:
function alphabetPosition(text) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const textWithoutSpaces = text.replace(/\s/g, '');
const numbers = Array.from(textWithoutSpaces).map((letter) => {
const lowerCaseLetter = letter.toLowerCase();
const charI = alphabet.indexOf(lowerCaseLetter)+1
if(charI) return charI
return null
})
const withoutEmptyValues = numbers.filter(Boolean)
return withoutEmptyValues.join(' ')
}
function alphabetPosition(text) {
const letters = text.split('')
const result = letters.map((l, ix) => {
const code = l.toUpperCase().charCodeAt() - 64
if (l.length && code > 0 && code <= 26) {
return code
}
})
return result.join(' ').replace(/\s+/g, ' ').trim()
}
I like to do "Single Line Responsibility", so in every line you can find only one action.
The return line, delete all multiples spaces.
An optimized version of it.
function alphabetPosition(text) {
let split = text.split("");
split = split.filter((el) => /^[a-zA-Z]+$/.test(el));
let str = "";
split.forEach(
(el) => (str += el.toLowerCase().charCodeAt(0) - "96" + " ")
);
return str.trim();
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
function alphaPosition(test){
//the object assigns the position value to every alphabet property
const lookupAlph = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26}
//converts our text first to lowercase, then removes every non-alphabet
// it proceeds to covert the text to an array,
// then we use the map method to convert it to its position in the alphabet
// the last thing we do is convert our array back to a string using the join method
const alphaPosition = text.toLowerCase()
.replace(/[^a-z]/g, "")
.split("")
.map((a) => lookupAlph[a])
.join(" ")
return alphaPosition;
}

Trying to find factors of a number in JS

I am just starting JS, and understand the concept of finding a factor. However, this snippet of code is what I have so far. I have the str variable that outputs nothing but the first factor which is 2. I am trying to add each (int) to the str as a list of factors. What's the wrong in below code snippet?
function calculate(num) {
var str = "";
var int = 2;
if (num % int == 0) {
str = str + int;
int++;
} else {
int++;
}
alert(str);
}
calculate(232);
UPDATED ES6 version:
As #gengns suggested in the comments a simpler way to generate the array would be to use the spread operator and the keys method:
const factors = number => [...Array(number + 1).keys()].filter(i=>number % i === 0);
console.log(factors(36)); // [1, 2, 3, 4, 6, 9, 12, 18, 36]
ES6 version:
const factors = number => Array
.from(Array(number + 1), (_, i) => i)
.filter(i => number % i === 0)
console.log(factors(36)); // [1, 2, 3, 4, 6, 9, 12, 18, 36]
https://jsfiddle.net/1bkpq17b/
Array(number) creates an empty array of [number] places
Array.from(arr, (_, i) => i) populates the empty array with values according to position [0,1,2,3,4,5,6,7,8,9]
.filter(i => ...) filters the populated [0,1,2,3,4,5] array to the elements which satisfy the condition of number % i === 0 which leaves only the numbers that are the factors of the original number.
Note that you can go just until Math.floor(number/2) for efficiency purposes if you deal with big numbers (or small).
As an even more performant complement to #the-quodesmith's answer, once you have a factor, you know immediately what its pairing product is:
function getFactors(num) {
const isEven = num % 2 === 0;
const max = Math.sqrt(num);
const inc = isEven ? 1 : 2;
let factors = [1, num];
for (let curFactor = isEven ? 2 : 3; curFactor <= max; curFactor += inc) {
if (num % curFactor !== 0) continue;
factors.push(curFactor);
let compliment = num / curFactor;
if (compliment !== curFactor) factors.push(compliment);
}
return factors;
}
for getFactors(300) this will run the loop only 15 times, as opposed to +-150 for the original.
#Moob's answer is correct. You must use a loop. However, you can speed up the process by determining if each number is even or odd. Odd numbers don't need to be checked against every number like evens do. Odd numbers can be checked against every-other number. Also, we don't need to check past half the given number as nothing above half will work. Excluding 0 and starting with 1:
function calculate(num) {
var half = Math.floor(num / 2), // Ensures a whole number <= num.
str = '1', // 1 will be a part of every solution.
i, j;
// Determine our increment value for the loop and starting point.
num % 2 === 0 ? (i = 2, j = 1) : (i = 3, j = 2);
for (i; i <= half; i += j) {
num % i === 0 ? str += ',' + i : false;
}
str += ',' + num; // Always include the original number.
console.log(str);
}
calculate(232);
http://jsfiddle.net/r8wh715t/
While I understand in your particular case (calculating 232) computation speed isn't a factor (<-- no pun intended), it could be an issue for larger numbers or multiple calculations. I was working on Project Euler problem #12 where I needed this type of function and computation speed was crucial.
function calculate(num) {
var str = "0";
for (var i = 1; i <= num; i++) {
if (num % i == 0) {
str += ',' + i;
}
}
alert(str);
}
calculate(232);
http://jsfiddle.net/67qmt/
Below is an implementation with the time complexity O(sqrt(N)):
function(A) {
var output = [];
for (var i=1; i <= Math.sqrt(A); i++) {
if (A % i === 0) {
output.push(i);
if (i !== Math.sqrt(A)) output.push(A/i);
}
}
if (output.indexOf(A) === -1) output.push(A);
return output;
}
here is a performance friendly version with complexity O(sqrt(N)).
Output is a sorted array without using sort.
var factors = (num) => {
let fac = [], i = 1, ind = 0;
while (i <= Math.floor(Math.sqrt(num))) {
//inserting new elements in the middle using splice
if (num%i === 0) {
fac.splice(ind,0,i);
if (i != num/i) {
fac.splice(-ind,0,num/i);
}
ind++;
}
i++;
}
//swapping first and last elements
let temp = fac[fac.length - 1];
fac[fac.length - 1] = fac[0];
fac[0] = temp;
// nice sorted array of factors
return fac;
};
console.log(factors(100));
Output:
[ 1, 2, 4, 5, 10, 20, 25, 50, 100 ]
This got me an 85% on Codility (Fails on the upperlimit, over a billion).
Reducing the input by half doesn't work well on large numbers as half is still a very large loop. So I used an object to keep track of the number and it's half value, meaning that we can reduce the loop to one quarter as we work from both ends simultaneously.
N=24 becomes: (1&24),(2&12),(3&8),(4&6)
function solution(N) {
const factors = {};
let num = 1;
let finished = false;
while(!finished)
{
if(factors[num] !== undefined)
{
finished = true;
}
else if(Number.isInteger(N/num))
{
factors[num] = 0;
factors[N/num]= 0;
}
num++
}
return Object.keys(factors).length;
}
Using generators in typescript in 2021
function* numberFactorGenerator(number: number): Generator<number> {
let i: number = 0;
while (i <= number) {
if (number % i === 0) {
yield i;
}
i++;
}
}
console.log([...numberFactorGenerator(12)]); // [ 1, 2, 3, 4, 6, 12 ]
function factorialize(num) {
var result = '';
if( num === 0){
return 1;
}else{
var myNum = [];
for(i = 1; i <= num; i++){
myNum.push(i);
result = myNum.reduce(function(pre,cur){
return pre * cur;
});
}
return result;
}
}
factorialize(9);
I came looking for an algorithm for this for use in factoring quadratic equations, meaning I need to consider both positive and negative numbers and factors. The below function does that and returns a list of factor pairs. Fiddle.
function getFactors(n) {
if (n === 0) {return "∞";} // Deal with 0
if (n % 1 !== 0) {return "The input must be an integer.";} // Deal with non-integers
// Check only up to the square root of the absolute value of n
// All factors above that will pair with factors below that
var absval_of_n = Math.abs(n),
sqrt_of_n = Math.sqrt(absval_of_n),
numbers_to_check = [];
for (var i=1; i <= sqrt_of_n; i++) {
numbers_to_check.push(i);
}
// Create an array of factor pairs
var factors = [];
for (var i=0; i <= numbers_to_check.length; i++) {
if (absval_of_n % i === 0) {
// Include both positive and negative factors
if (n>0) {
factors.push([i, absval_of_n/i]);
factors.push([-i, -absval_of_n/i]);
} else {
factors.push([-i, absval_of_n/i]);
factors.push([i, -absval_of_n/i]);
}
}
}
// Test for the console
console.log("FACTORS OF "+n+":\n"+
"There are "+factors.length+" factor pairs.");
for (var i=0; i<factors.length; i++) {
console.log(factors[i]);
}
return factors;
}
getFactors(-26);
function calculate(num){
var str = "0" // initializes a place holder for var str
for(i=2;i<num;i++){
var num2 = num%i;
if(num2 ==0){
str = str +i; // this line joins the factors to the var str
}
}
str1 = str.substr(1) //This removes the initial --var str = "0" at line 2
console.log(str1)
}
calculate(232);
//Output 2482958116
Here's an optimized solution using best practices, proper code style/readability, and returns the results in an ordered array.
function getFactors(num) {
const maxFactorNum = Math.floor(Math.sqrt(num));
const factorArr = [];
let count = 0; //count of factors found < maxFactorNum.
for (let i = 1; i <= maxFactorNum; i++) {
//inserting new elements in the middle using splice
if (num % i === 0) {
factorArr.splice(count, 0, i);
let otherFactor = num / i; //the other factor
if (i != otherFactor) {
//insert these factors in the front of the array
factorArr.splice(-count, 0, otherFactor);
}
count++;
}
}
//swapping first and last elements
let lastIndex = factorArr.length - 1;
let temp = factorArr[lastIndex];
factorArr[lastIndex] = factorArr[0];
factorArr[0] = temp;
return factorArr;
}
console.log(getFactors(100));
console.log(getFactors(240));
console.log(getFactors(600851475143)); //large number used in Project Euler.
I based my answer on the answer written by #Harman
We don't have to loop till end of the given number to find out all the factors. We just have to loop till reaching the given number's squareroot. After that point we, can figure out the rest of the factors by dividing the given number with the already found factors.
There is one special case with this logic. When the given number has a perfect square, then the middle factor is duplicated. The special case is also handled properly in the below code.
const findFactors = function (num) {
const startingFactors = []
const latterFactors = []
const sqrt = Math.sqrt(num)
for (let i = 1; i <= sqrt; i++) {
if (num % i == 0) {
startingFactors.push(i)
latterFactors.push(num / i)
}
}
// edge case (if number has perfect square, then the middle factor is replicated, so remove it)
if (sqrt % 1 == 0) startingFactors.pop()
return startingFactors.concat(latterFactors.reverse())
}
function factorialize(num) {
if(num === 0)
return 1;
var arr = [];
for(var i=1; i<= num; i++){
arr.push(i);
}
num = arr.reduce(function(preVal, curVal){
return preVal * curVal;
});
return num;
}
factorialize(5);

Categories