I've a simple FOR statement like this:
var num = 10,
reverse = false;
for(i=0;i<num;i++){
console.log(i);
}
when reverse is false I want it to return something like [0,1,2,3,4,5,6,7,8,9]
but, when reverse is true, it should return [9,8,7,6,5,4,3,2,1,0]
Which is the most efficient way to get this result, without checking every time if reverse is true or false inside the loop?
I don't want to do this:
var num = 10,
reverse = false;
for(i=0;i<num;i++){
if(reverse) console.log(num-i)
else console.log(i)
}
I would like to check reverse only one time outside the loop.
var num = 10,
reverse = false;
if(!reverse) for( var i=0;i<num;i++) log(i);
else while(num-- ) log(num);
// to avoid duplication if the code gets long
function log( num ) { console.log( num ); }
EDIT:
As noted in the comments below, if i is not declared elsewhere and you do not intend for it to be global, then declare it with the other variables you declared.
And if you don't want to modify the value of num, then assign it to i first.
var num = 10,
reverse = false,
i;
if(!reverse) for(var i=0;i<num;i++) log(i); // Count up
else {var i=num; while(i--) log(i);} // Count down
function log( num ) { console.log( num ); }
Try use 2 loops:
if (reverse) {
for(i=num-1;i>=0;i--){
console.log(i)
}
}
else {
for(i=0;i<num;i++){
console.log(i)
}
}
var num = 10,
reverse = false;
for (var i = 0, n = reverse?num-1:0, d = reverse?-1:1; i < num; i++, n+=d) {
console.log(n);
}
This is equivalent to the following, which is more readable, but less compact:
var num = 10,
reverse = false;
var start = reverse ? num-1 : 0,
end = reverse ? -1 : num,
step = reverse ? -1 : 1;
for (var i = start; i != end; i += step) {
console.log(i);
}
Edit:
Actually, these two solutions are not identical, because the first one has an additional increment operation. Still, it is negligible from performance point of view. If you really want to get a compact solution that has the best performance, you can do the following (not for the faint of heart):
var num = 10,
reverse = false;
for (var r=reverse, i=r?num-1:0, n=r?-1:num, d=r?-1:1; i!=n; i+=d) {
console.log(i);
}
This has the advantage of having a single control structure, a single test in each loop, and a single iterator addition. It is not as fast as having an iterator increment/decrement, but only marginally so.
var start; var end; var inc;
if (reverse) {
start = num-1; end = 0; inc = -1;
}
else {
start = 0; end = num-1; inc = 1;
}
for(i=start;i!=end;i+=inc){
console.log(i)
}
I just came across the need for this the other day. Here's how I did it:
var num = 10,
i = 0,
direction = 1,
reverse = false;
if(reverse)
i = num + (direction = num = -1);
for(; i !== num; i += direction) {
console.log(i);
}
No need for separate loops, and no need to do math to calculate the proper i in the loop.
So if reverse is true...
i (which represents our first item) becomes num - 1, so we're now starting on what would have been the last item
num (which represents out of bounds) becomes -1, so we're now stopping on what would have been the first item
direction is -1, which means it will decrement when we do i += direction
So by swapping our starting point with our ending point and changing the alteration of i from 1 to -1, we'll be going up or down based on those modifications.
I think this meets your requirements:
var num = 10;
var reverse = false;
var diff = 0;
if (reverse) {
diff = num - 1;
}
for (i = 0; i < num; i++) {
console.log(Math.abs(diff - i));
}
Here's how I've always done reverse loops:
for (i = num; --i >= 0; ) ...
And what's your problem with:
if (reverse)
{
for(i=num-1; i>=0;i--){
console.log(i);
}
}
else
{
for(i=0;i<num;i++){
console.log(i)
}
}
}
Roy's is similar to mine, but here's what I was thinking. I'll give you what I wrote in C# and how I think it translates to Javascript.
C#
int num = 10;
bool reverse = true;
for (int i = reverse ? num : 0; (reverse ? 0 : i) < (reverse ? i : num); i += reverse ? -1 : 1)
{
Console.Write((reverse ? i - 1 : i).ToString());
}
Console.ReadKey();
Javascript
var num = 10,
reverse = true;
for (int i = reverse ? num : 0; (reverse ? 0 : i) < (reverse ? i : num); i += reverse ? -1 : 1)
{
console.log(reverse ? i - 1 : i);
}
And here's another way
Javascript
var num = 10,
reverse = false;
for (int i = 0; i < num; i++)
{
console.log((reverse ? abs(-num + (i + 1)) : i));
}
It seems to work:
var num = 10;
var z = 1;
var k = -10;
if (reverse ){
k = -1;
z = -1;
}
for(int i = 0; i < 10; i++){
console.log(num+i*z+k);
}
Surely in a language like Javascript there must be a way to define a local function and use that in the loop?
function SubtractFrom(val, subtractor) {
return val - subtractor;
}
function PassThrough(val) {
return val;
}
var num = 10;
var processor = reverse ? SubtractFrom(num-1) : PassThrough;
for (i = 0; i < num; i++) {
console.log(processor(i));
}
Not knowing Javascript though, I don't know what actual form the function definitions would take.
//reverse a number
let c = [2,3,5,67,4]
let sum = '';
let d = c.toString().split('')
console.log(d)
for(let i = d.length-1; i >= 0; i--) {
sum += d[i]
}
console.log(sum)
Related
I have a problem I am sitting on for the past few days.
I want to write an optimal (in JS) program for verifying if a number is a Palindrome.
My current approach:
function isPalidrom2(pali){
//MOST time consuming call - I am splitting the digit into char array.
var digits = (""+pali).split("");
//To get the length of it.
var size = digits.length;
var isPali = true;
for(var i = 0; i<Math.floor(size/2); i++){
//I am comparing digits (first vs last, second vs last-1, etc.) one by one, if ANY of the pars is not correct I am breaking the loop.
if(parseInt(digits[i]) != parseInt(digits[size-i-1])){
isPali = false;
break;
}
}
return isPali;
}
It's not optimal. The biggest amount of time I am waisting is the change from INT to STRING.
And I am out of ideas
- I tried to understand the BIT operators but I can't.
- I tried to google and look for alternative approaches - but I can't find anything.
- I tried to play with different algorithms - but this one is the fastest I was able to apply.
So in short - my question is:
"how can I make it faster?"
EDIT:
So the task I want to solve:
Find all of the prime numbers within the range of all five digit numbers.
Among all of the multiplies (i*j) they are between them, find the most significant palindrome.
My current approach:
function isPrime(number){
var prime = true;
var i
for(i = 2; i<= number/2; i++){
if((number%i)==0){
prime = false;
break;
}
}
return prime;
}
function get5DigitPrimeNr(){
var a5DigitsPrime = [];
var i;
for(i = 10000; i<100000; i++){
if(isPrime(i)){
a5DigitsPrime.push(i)
}
}
return a5DigitsPrime;
}
function isPalidrom(pali){
var digits = (""+pali).split("");
//we check if first and last are the same - if true, we can progress
size = digits.length;
return
(digits[0]==digits[size-1]) &&
(parseInt(digits.slice(1, Math.floor(size/2)).join("")) ==
parseInt(digits.reverse().slice(1, Math.floor(size/2)).join("")))
}
function isPalidrom2_48s(str) {
var str = str.toString();
const lower = str.substr(0, Math.floor(str.length / 2));
const upper = str.substr(Math.ceil(str.length / 2));
return lower.split("").reverse().join("") === upper;
}
function isPalidrom_22s(pali){
var digits = (""+pali).split("");
var size = digits.length;
for(var i = 0; i<Math.floor(size/2); i++){
//console.log("I am comparing: "+i+", and "+(size-i-1)+" elements in array")
//console.log("I am comparing digit: "+digits[i]+", and "+digits[(size-i-1)]+"")
if(digits[i] !== digits[size-i-1]){
//console.log('nie sa rowne, koniec')
return false;
}
}
return true;
}
function isPalidrom2_80s(pali){
return parseInt(pali) == parseInt((""+pali).split("").reverse().join(""))
}
function runme(){
var prime5digits = get5DigitPrimeNr();
var size = prime5digits.length;
var max = 0;
var message = "";
for(var i = 0; i<size; i++){
for(var j = 0; j<size; j++){
var nr = prime5digits[i]*prime5digits[j];
if(nr>max && isPalidrom2(nr)){
max = nr;
message = 'biggest palidrome nr: '+nr+', made from numbers: '+prime5digits[i]+' x '+prime5digits[j];
}
}
}
console.log(message)
}
function timeMe(){
var t0 = performance.now();
runme();
var t1 = performance.now();
console.log("Function took " + millisToMinutesAndSeconds(t1 - t0) + " s to find the perfect palindrom.")
}
//helper functons:
function millisToMinutesAndSeconds(millis) {
var minutes = Math.floor(millis / 60000);
var seconds = ((millis % 60000) / 1000).toFixed(0);
return minutes + ":" + (seconds < 10 ? '0' : '') + seconds;
}
To keep the spirit of you code, you could exit the loop with return instead of break and use the string directly without converting to an array. Strings have, as arrays, the possibility of an access single character with an index.
function isPalidrom2(value) {
var digits = value.toString(),
length = digits.length,
i, l;
for (i = 0, l = length >> 1; i < l; i++) {
if (digits[i] !== digits[length - i - 1]) {
return false;
}
}
return true;
}
console.log(isPalidrom2(1));
console.log(isPalidrom2(12));
console.log(isPalidrom2(1221));
console.log(isPalidrom2(123));
The fastest is probably to rely on javascripts native methods:
function isPalindrome(str) {
const lower = str.substr(0, Math.floor(str.length / 2));
const upper = str.substr(Math.ceil(str.length / 2));
return lower.split("").reverse().join("") === upper;
}
Or leave away all unneccessary conversions from your code:
function isPlaindrome(str) {
const half = str.length / 2;
for(var i = 0; i < half; i++)
if(str[i] !== str[str.length - i - 1])
return false;
return true;
}
If you're trying to speed things up, you could shave a few more seconds off by optimising your isPrime(n) function.
You don't need to check every factor, only the prime factors less than sqrt(n)
If you check every number from 2 to 99999 in ascending order, you can store the results as you go, so you don't need to keep re-calculating the list of previous primes
Something like this:
var savedPrimes = [2]
function isPrime(n){
// call this method with increasing values of n (starting at 2), saving primes as we go,
// so we can safely assume that savedPrimes contains all primes less than n
for(var i=0; i<savedPrimes.length; i++)
{
var f = savedPrimes[i];
if ((n % f) == 0)
return false; // found a factor
if (f*f>=n)
break; // stop checking after f >= sqrt(n)
}
// no prime factors - we found a new prime
savedPrimes.push(n);
return true;
}
function get5DigitPrimeNr(){
var a5DigitsPrime = [];
var i;
// first find all the primes less than 10000
for(i = 3; i<10000; i++){
isPrime(i);
}
// now find (and keep) the rest of the primes up to 99999
for(i = 10000; i<100000; i++){
if(isPrime(i)){
a5DigitsPrime.push(i)
}
}
return a5DigitsPrime;
}
EDIT - when I run your code with this method, I get a time of 10 sec
Code :
There are multiple methods that you can use (dunno if they are optimal) :
Palindrom = _ => (_=''+_) === [..._].sort(_=>1).join``
Some more :
let isPalindrome = __ => (_=(__=__+'').length)==0||_==1?!0:__[0]==__.slice(-1)?isPalindrome(__.slice(1,-1)):!1
let isPalindrome = (s,i) => (i=i||0)<0||i>=(s=''+s).length>>1||s[i]==s[s.length-1-i]&&isPalindrome(s,++i);
let isPalindrome = (str) => {
var len = ~~((str=str+'').length / 2);
for (var i = 0; i < len; i++)
if (str[i] !== str[str.length - i - 1])
return false;
return true;
}
Updated now takes numbers as input
I'm trying to create a formula for calculating PI using the Gregory-Leibniz series. I've created a for loop that's populating a new array with the individual values, but I need a way to then alternate between subtracting and adding each array item and then spit out the resulting number. Essentially, I need to get to something like this:
(4/1) - (4/3) + (4/5) - (4/7) + (4/9) - (4/11) + (4/13) - (4/15)
The following for loop is populating the new array correctly:
var arrLimit = 39;
var newArray = [];
for(i = 1; i <= arrLimit; i += 2) {
newArray.push(4/i);
}
At this point I get stuck. I need some way to take newArray and alternate between subtracting and adding the values, and then produce the final number.
You can sum your array with reduce, then judge *=-1 or *=1 based on the index of the array.
The code will be like below:
//Test Case 1
var arrLimit = 39;
var newArray = [];
for(i = 1; i <= arrLimit; i += 2) {
newArray.push(4/i);
}
console.log(newArray.reduce(function(pre, cur, currentIndex){
return pre+cur*(currentIndex%2 ? -1 : 1);
}, 0));
//Test Case 2
arrLimit = 11139;
newArray = [];
for(i = 1; i <= arrLimit; i += 2) {
newArray.push(4/i);
}
console.log(newArray.reduce(function(pre, cur, currentIndex){
return pre+cur*(currentIndex%2 ? -1 : 1);
}, 0));
Keep an extra variable, isNeg = true. On each iteration of the loop, just alternate it with isNeg = !isNeg;.
var arrLimit = 39;
var newArray = [];
var isNeg = false;
for(i = 1; i <= arrLimit; i += 2) {
isNeg = !isNeg;
var val = 4/i;
if (isNeg) {
val *= -1;
}
newArray.push(val);
}
You can also assign 1 to the variable, and multiple it by -1 each time to do the flip:
var arrLimit = 39;
var newArray = [];
var factor = 1;
for(i = 1; i <= arrLimit; i += 2) {
factor *= -1;
var val = factor * 4 / i;
newArray.push(val);
}
Personally I favor the second approach, but both work just fine.
I need some way to take newArray and alternate between subtracting and adding the values, and then produce the final number.
You can do that with Array.prototype.reduce
// Your code, unchanged
var arrLimit = 39;
var newArray = [];
for(i = 1; i <= arrLimit; i += 2) {
newArray.push(4/i);
}
// reduce the array to the final result
// (2*(-i%2)+1) alternates between `-1` and `1`.
var result = newArray.reduce( (prev,curr,i) => prev + (2*(-i%2)+1)*curr );
console.log( result );
How about doing away with the array in the first place and being able to "calculate" pi with as many terms as you like.
let pi = 0,
terms = 100;
for (var i = 0; i < terms; i++){
pi += 4/(2*i + 1) * ( i % 2 == 0 ? 1 : -1)
}
console.log(pi);
You could add an extra variable. If you want you could sum at the same time.
var arrLimit = 39;
var newArray = [];
var a=-1
var sum =0
for(i = 1; i <= arrLimit; i += 2) {
a*=-1;
newArray.push(a*4/i);
sum+=a*4/i
}
You can look at the length of newArray when you build it and multiply the value by -1 or +1
var arrLimit = 39;
var newArray = [];
for(i = 1; i <= arrLimit; i += 2) {
newArray.push(4 / i * (newArray.length % 2 ? 1 : -1));
}
console.log(newArray);
I am working through this Free Code Camp exercise.
Return the sum of all odd Fibonacci numbers up to and including the
passed number if it is a Fibonacci number. The first few numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and
8, and each subsequent number is the sum of the previous two numbers.
And here is what I have so far...
Any suggestions?
function sumFibs(num) {
var arr, isFibVal, isEvenVal, sum, i = 0, fibonacci = function (num){
var a, b, result, fibArr = [1];
a=0;
b=1;
result=b;
for(var j = 0; j < num; j++){
result = a + b;
a = b;
b = result;
fibArr.push(result);
}
return fibArr;
},
isFib = function (val){
var prev = 0;
var curr = 1;
while(prev<=val){
if(prev == val){
return true;
} else {
return false;
}
curr = prev + curr;
prev = curr - prev;
}
},
isEven = function(someNumber){
return (someNumber % 2 === 0) ? true : false;
};
function sumArray(array) {
for (
var
index = 0, // The iterator
length = array.length, // Cache the array length
sum = 0; // The total amount
index < length; // The "for"-loop condition
sum += array[index++] // Add number on each iteration
);
return sum;
}
arr = fibonacci(num);
isFibVal = isFib(num);
isEvenVal = isEven(num);
if (isFibVal && !isEvenVal){
sum += sumArray(arr);
}
return sum;
}
All I get back is undefined which seems to be weird because i thought this part of my code was pretty cool—using the function values to check vs. in the if statement.
arr = fibonacci(num);
isFibVal = isFib(num);
isEvenVal = isEven(num);
if (isFibVal && !isEvenVal){
sum += sumArray(arr);
}
I won't give you the answer outright since you're going through FCC, but I'll provide you with some hints as to where to look:
See this segment:
for(var j = 0; j < num; j++){
result = a + b;
a = b;
b = result;
fibArr.push(result);
}
And this one:
function sumArray(array) {
for (
var
index = 0, // The iterator
length = array.length, // Cache the array length
sum = 0; // The total amount
index < length; // The "for"-loop condition
sum += array[index++] // Add number on each iteration
);
return sum;
}
Also, you probably don't need this segment at all:
isFibVal = isFib(num);
isEvenVal = isEven(num);
if (isFibVal && !isEvenVal){
sum += sumArray(arr);
Good luck. As someone who has finished a good chunk of the curriculum, I can say that Free Code Camp is the real deal.
You're pretty close and the other answer is good for pushing you in the right direction, I'll post a different way that does this using native JS functions:
Example of the code below in JSBin
function fibs(n) {
var f = [0, 1];
var extraNumber = 0;
for (var i = 0; i < n; i++) {
f.push(f[f.length - 1] + f[f.length - 2]);
}
// lets check if the passed in number is a fib:
if (f.indexOf(n) > -1) {
extraNumber = n;
}
console.log(f); // just to check we can cut all the logs later...
var filtered = f.filter(function(num) {
// filter out the even numbers
return num % 2 === 1;
});
console.log(filtered);
var sum = filtered.reduce(function(a, b) {
// add up whats left
return a + b;
});
console.log(sum);
return sum + extraNumber;
}
heres my solution, and i find it to be pretty readable:
function sumOddFibs(num) {
// initialize with 2 because
// fib sequence starts with 1 and 1
var sum = 2;
var prev = 1;
var curr = 1;
var next = 2;
while (next <= num) {
prev = curr;
curr = next;
next = prev + curr;
if (curr % 2 !== 0) {
sum += curr;
}
}
return sum;
}
You could start by defining variables for the previous number, current number, and total Fibonacci
To check for odd numbers, you could use an if statement and use %:
if (currNum % 2 !== 0){ }
If current number is odd, then you add it to the total
fibTotal += currNumber;
To determine the next Fibonacci number you, you will need to add the previous and current number:
var nextNumber = prevNumber + currNumber;
You will need to update the previous number to the current one
prevNumber = currNumber;
Set the current number to the next Fibonacci number in the sequence
currNumber = nextNumber;
Hope this helps.
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);
What is the most effective to map ranges using Arrays in JavaScript?
I have this:
var def = [70,200,1000];
And an array of possible numbers, say:
var n = [23,45,74,120,240,800,1204,2000];
Now, how can I extract the closest value from n that matches the values from def?
In the example above, I would get [74,240,800]. I hope I make myself clear...
Here is a try. Iterate over def and n just once:
var nIndex = 0,
nlen = n.length,
prev,
next;
for(var i = 0, ilen = def.length; i < ilen && nIndex < nlen; i++) {
var current = def[i];
while (n[nIndex] < current && nIndex < nlen - 1) nIndex++;
next = n[nIndex];
prev = nIndex == 0 ? next : n[nIndex - 1];
result[i] = current - prev < next - current ? prev : next;
}
// values in def are larger than the greatest value in n
while (result.length < def.length) result.push(n[nlen-1]);
fiddle
http://jsfiddle.net/8bY2M/
var def = [70,200,1000];
var n = [23,45,74,120,240,800,1204,2000];
var result = [];
for (var i = 0; i < def.length; i++){
var val = def[i];
for (var j = 0; j < n.length; j++){
var nVal = n[j];
if (nVal > val){
var closest = n[j-1] == undefined ? nVal :
nVal - val > val - n[j-1] ? n[j-1] : nVal;
result.push(closest);
break;
}
}
}
console.log(result); // outputs: [74, 240, 800]
Note that this will go with the larger value in the event of two matches. (i.e. if you are trying to match 70, and n contains 66 and 74, this will match it with 74)
Other solutions are pretty simple, but if you're looking for efficiency, your best bet is to pre-sort the initial list (if it's not sorted already) and then perform a binary search. Here's my solution:
var def = [70,200,1000];
var n = [23,45,74,120,240,800,1204,2000];
var findClosest = function(n, def) {
var i, result = [];
n = n.sort(function(a, b) { return a - b; }); //numeric sort
var closestN = (function(val) {
return (function search(r) {
var mid = r.low + (0 | ((r.high - r.low) / 2));
if(n[mid] === val) {
return n[mid];
}
if((r.high - r.low) === 1) {
return n[r[(Math.abs(n[r.low] - val) > Math.abs(n[r.high] - val)) ? "high" : "low"]];
}
r[(val < n[mid]) ? "high" : "low"] = mid;
return search(r);
}({low : 0, high: (n.length - 1)}));
});
for (i=0; i<def.length; i++) {
result.push(closestN(def[i]));
}
return result;
};
//The result can be obtained with findClosest(n, def)
Mind you, it's not very readable (if you're not familiar with binary search algorithms) and if you're looking for a simple solution where performance isn't important, a linear search would result in more maintainable code. But this solution runs in O(n log(n)) time, instead of O(n^2) time like a linear search would.
You can see it in action here:
http://jsfiddle.net/naYu6/
Note that in the case of a "tie" (where two values in the list are equidistant from the value in question, the lower of the two will be picked).