how to find two max numbers ( negative and positive ) in array? - javascript

I'm looking for best solution to solve this problem
Problem:
Create a function named ArrayChallenge (Javascript) which accepts a single argument "arr" which is an array of numbers. This function will return the string true if any two numbers can be multiplied so that the answer is greater than double the sum of all the elements in the array. If not, return the string false.
For example:
if the argument "arr" is [2, 5, 6, -6, 16, 2, 3, 6, 5, 3] then the sum of all these elements is 42, and doubling it is 84. There are two elements in "arr", 16 * 6 = 96 where 96 is greater than 84, so your program should return the string true. An example of an "arr" that should return false is [1, 2, 4] since double its sum (14) is larger than multiplying its two largest elements (4 * 2 = 8).
my solution was
function ArrayChallenge(arr) {
if (arr.length < 2) return 'false'
let maxNeg = 0
let neg = 0
let pos = 0
let maxPos = 0
const sum = arr.reduce((total, num) => {
if (num < 0) {
if (num < neg) maxNeg = num
else neg = num
} else {
if (num >= maxPos) {
pos = maxPos
maxPos = num
} else if (num > pos) pos = num
}
return total + num
}, 0)
if (maxPos * pos > sum * 2 || maxNeg * neg > sum * 2) return 'true'
else return 'false'
}
https://codepen.io/hamodey85/pen/ExmrdgM

For this problem you need to understand the fact that if the highest possible product of the 2 numbers in the array are not greater than the twice sum of the array then there are no possible pairs available.
Steps to solve the problem
step 1
precompute the sum of the array.(can be easily done using for loop or reduce function)
step 2
get the 2 maximum values from the array(depending on allowed complexity you can either sort the array and get it i.e.O(nlogn) or traverse the array twice i.e.O(2n) which is better.
step 3
compare product of the 2 maximum and precomputed sum and return true if product is greater than the precomputed sum
Sorting Apprach
function ArrayChallenge(arr){
var precomputedSum = arr.reduce((a,c) => a+c,0); //Step 1
var sortedArray = arr.sort(function(a, b){return b-a});// Step 2
var product = sortedArray[0] * sortedArray[1];//part of step 2
return product > 2*precomputedSum ;
}
looping approach
function ArrayChallenge(arr){
var precomputedSum = arr.reduce((a,c) => a+c,0); //Step 1
int firstMax = -2147483648;// Step 2
for(int i=0;i<arr.length;i++){
if(arr[i]>firstMax)firstMax=arr[i];//step 2
}
int secondMax = -2147483648;// Step 2
for(int i=0;i<arr.length;i++){
if(arr[i]>secondMax && arr[i]!=firstMax)secondMax=arr[i];//step 2
}
var product = firstMax * secondMax;//part of step 2
return product > 2*precomputedSum ;
}

so I tried to solve it in several way but I found this better solution so far
function ArrayChallenge(arr) {
if (arr.length < 2) return 'false'
let maxNeg = 0
let neg = 0
let pos = 0
let maxPos = 0
const sum = arr.reduce((total, num) => {
if (num < 0) {
if (num < neg) maxNeg = num
else neg = num
} else {
if (num >= maxPos) {
pos = maxPos
maxPos = num
} else if (num > pos) pos = num
}
return total + num
}, 0)
if (maxPos * pos > sum * 2 || maxNeg * neg > sum * 2) return 'true'
else return 'false'
}

Related

Cheking if it's a prime number with JS

I'm first trying to push only prime numbers (without 2) to an array and then sum them all but getting undefined.
I've been working on this for long days, I'd appreciate if anyone could help me.
let letsCheck = () => {
let ourList = []
let sum = 0
for(let i = 2; i <= 50; i++) {
if(i % 2 !== Number.isInteger()) {
ourList.push(Number(i))
}
}
for(let prime in ourList) {
sum += ourList[prime]
}
}
First of all, You are not checking prime but checking odd numbers by % operator.
Second, you are checking Number.isNumber function which will return the boolean so, the comparison have some issues.
Here is one solution which may help.
let letsCheck = () => {
let ourList = []
let sum = 0
for(let i = 3; i <= 50; i++) {
if(isPrimeNumber(i)) {
ourList.push(Number(i))
}
}
for(let prime in ourList) {
sum += ourList[prime]
}
}
const isPrimeNumber = number => {
for(let i = 2; i <= Math.ceil(number/2); i++) {
if(number % 2 === 0) {
return false;
}
}
return true;
}
From, your code, it was more likely for obtaining odd/even numbers instead of prime numbers.
Prime numbers are whole numbers greater than 1, that have only two factors – 1 and the number itself
Odd numbers are the numbers that doesn't have 2 as its factor, and will have remainder = 1 if it gets divided by 2.
Then, as the basic programming math, the mod works like multiplication/add/subtraction that if both operators/numbers are Integer, the result would be Integer. The mod operation is basically for obtaining the remainders from the division, i.e. 5 / 2 = 2, with remainders = 1, thus 5 % 2 = 1.
And, in the looping, the i is already a number, so pushing the Number(i) is equivalent with pushing i alone. If you just want to get the sum, the array is not necessary there and should be just removed. You can get the sum by accumulate it into the sum variable.
Thus, if you wish to get the sum of odd numbers in the range [2,50], it should be:
let letsCheck = () => {
let sum = 0
for(let i = 2; i <= 50; i++) {
if(i % 2 !== 0) {
sum += i;
}
}
console.log(sum);
}
letsCheck();
And if you wish to get the prime numbers from 0 to 50 excluding 2, it should be:
function isPrimeExclude2(num) {
if(num <= 2) return false;
for(let i=2; i*i <= num; i++){
if (num % i == 0) return false;
}
return true;
}
let letsCheck = () => {
let sum = 0
for(let i = 2; i <= 50; i++) {
if(isPrimeExclude2(i)) {
sum = sum + i;
}
}
console.log(sum);
}
letsCheck();

find sum of multiples 3 and 5, JS

I'm given a number and I need to find the sum of the multiples of 3 and 5 below the number.
For example:
20 => 78 = 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18
My code works, but not for numbers greater than 1,000,000 (I tested it for 100,000 - it gives the result with 2sec delay). So, it should be optimized. Could someone help me? Why is my code slow? Thanks.
My logic is as follows:
add multiples to an array
filter duplicate values
sum all values
my code:
function sumOfMultiples(number) {
let numberBelow = number - 1;
let numberOfThrees = Math.floor(numberBelow / 3);
let numberOfFives = Math.floor(numberBelow / 5);
let multiples = [];
let multipleOfThree = 0;
let multipleOfFive = 0;
for (var i = 0; i < numberOfThrees; i++) {
multiples.push(multipleOfThree += 3);
}
for (var j = 0; j < numberOfFives; j++) {
multiples.push(multipleOfFive += 5);
}
return multiples
.filter((item, index) => multiples.indexOf(item) === index)
.reduce((a, b) => a + b);
}
You can also do this without using any loops.
For example if N is 1000, the sum of all multiples of 3 under 1000 is 3 + 6 + 9 ..... 999 => 3( 1 + 2 + 3 .... 333)
Similarly for 5, sum is 5(1 + 2 + 3 .... 200). But we have to subtract common multiples like 15, 30, 45 (multiples of 15)
And sum of first N natural numbers is N*(N+1)/2;
Putting all of this together
// Returns sum of first N natural numbers
const sumN = N => N*(N+1)/2;
// Returns number of multiples of a below N
const noOfMulitples = (N, a) => Math.floor((N-1)/a);
function sumOfMulitples(N) {
const n3 = noOfMulitples(N, 3); // Number of multiples of 3 under N
const n5 = noOfMulitples(N, 5); // Number of multiples of 5 under N
const n15 = noOfMulitples(N, 15); // Number of multiples of 3 & 5 under N
return 3*sumN(n3) + 5*sumN(n5) - 15*sumN(n15);
}
You can just run a loop from 1 to number, and use the modulo operator % to check if i divides 3 or 5:
function sumOfMultiples(number) {
var result = 0;
for (var i = 0; i < number; i++) {
if (i % 5 == 0 || i % 3 == 0) {
result += i;
}
}
return result;
}
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
You can do that just using a single loop.
function sumOfMultiples(number) {
let sum = 0;
for(let i = 1; i < number; i++){
if(i % 3 === 0 || i % 5 === 0){
sum += i;
}
}
return sum;
}
console.time('t');
console.log(sumOfMultiples(100000))
console.timeEnd('t')
You can do something like this
Set the difference equal to 5 - 3
Start loop with current as 0, keep looping until current is less than number,
Add 3 to current in every iteration,
Add difference to current and check if it is divisible by 5 only and less than number, than add it final result,
Add current to final result
function sumOfMultiples(number) {
let num = 0;
let difference = 5 - 3
let current = 0
while(current < number){
current += 3
let temp = current + difference
if((temp % 5 === 0) && (temp %3 !== 0) && temp < number ){
num += temp
}
difference += 2
if(current < number){
num += current
}
}
return num
}
console.log(sumOfMultiples(20))
console.log(sumOfMultiples(1000));
console.log(sumOfMultiples(100000));
console.log(sumOfMultiples(10000000));
you can do something like this
function multiplesOfFiveAndThree(){
let sum = 0;
for(let i = 1; i < 1000; i++) {
if (i % 3 === 0 || i % 5 === 0) sum += i;
}
return sum;
}
console.log(multiplesOfFiveAndThree());

Sum a negative number's digits

'Write a function named sumDigits which takes a number as input and
returns the sum of each of the number's decimal
digits.'
How can I sum the digits with the first digit being negative?
For example: sumDigits(-32); // -3 + 2 = -1;
I was able to solve it partially.
function sumDigits(number) {
return Math.abs(number).toString().split("").reduce(function(a, b) {
return parseInt(a) + parseInt(b);
}, 0);
}
console.log( sumDigits(-32) );
Simple math and recursion make short work of this problem.
Recall that when you divide a number by 10, the remainder is its rightmost decimal digit and the integer part of the quotient is the number formed by the remaining digits. In other words:
let n = 5678;
console.log(n % 10); // => 8
console.log(Math.floor(n / 10)); // => 567
With this in mind, summing a number's digits is a straightforward recursive procedure:
Procedure(n)
Divide n by 10.
Set digit to the remainder.
Set n to the integer part of the quotient.
If n = 0, return digit.
Otherwise, return digit + Procedure(n)
Keeping the sign for the leftmost digit adds a small amount of complexity, but not much. Here's how it looks in JavaScript:
function digitSum(n, sign=1) {
if (n < 0) {
sign = -1; // Save the sign
n = Math.abs(n);
}
const digit = n % 10; // Remainder of |n÷10|
n = Math.floor(n / 10); // Integer part of |n÷10|
if (n === 0) {
return sign * digit; // No digits left, return final digit with sign
}
return digit + digitSum(n, sign); // Add digit to sum of remaining digits
}
console.log(digitSum(32)); // => 5
console.log(digitSum(-32)); // => -1
Here is a way to do it with Array.prototype.reduce().
Stringify the input and split it on each character.
Iterate over the characters with reduce.
Initialize the accumulator with a sum of 0 and a multiplier of 1.
If the first character is a -, set the multiplier to -1
For the subsequent characters, multiply the digit with the multiplier and add it to the sum. Then set the multiplier back to 1 so the next digits will only be multiplied by 1.
const sumDigits = x => [...`${x}`].reduce(({ sum, mult }, x, i) => {
return i === 0 && x === '-' ? { sum: 0, mult: -1 } : { sum: sum + mult * x, mult: 1 };
}, { sum: 0, mult: 1 }).sum;
console.log(sumDigits(-32)); // -1
console.log(sumDigits(32)); // 5
console.log(sumDigits(5555)); // 20
Here's a way you can do it without String conversion -
const sumDigits = (n = 0) =>
n < 0
? n > -10
? n
: (-n % 10) + sumDigits (n / 10 >> 0)
: n < 10
? n
: (n % 10) + sumDigits (n / 10 >> 0)
console.log(sumDigits(-321))
// (-3 + 2 + 1)
// => 0
console.log(sumDigits(321))
// (3 + 2 + 1)
// => 6
The same answer using imperative style -
const sumDigits = (n = 0) =>
{ if (n < 0)
if (n > -10)
return n
else
return (-n % 10) + sumDigits (n / 10 >> 0)
else
if (n < 10)
return n
else
return (n % 10) + sumDigits (n / 10 >> 0)
}
console.log(sumDigits(-321))
// (-3 + 2 + 1)
// => 0
console.log(sumDigits(321))
// (3 + 2 + 1)
// => 6
An approach that does not require converting to a string adapted from another answer by #NinaScholz to a closely related question (for those that are bitwise shift operator challenged).
Converts the number to its absolute value, loops with modulus operator to sum the remainder after dividing by 10 until a ones value remains, and then subtracts the leftmost digit if the original number was negative.
const sumDigits = (n) => {
const negative = !!(n < 0);
let sum = 0;
let num = negative ? Math.abs(n) : n;
while (num) {
if (negative && num <= 10) {
sum -= num % 10;
} else {
sum += num % 10;
}
num = Math.floor(num / 10);
}
return sum;
};
console.log(sumDigits(-32));
// -1
You could take a different method for separating the digits and keep the first one with a possible sign.
'-32'.match(/-?\d/g)
returns
['-3', '2']
function sumDigits(number) {
return number.toString().match(/-?\d/g).reduce(function(a, b) {
return a + +b;
}, 0);
}
console.log(sumDigits(-32));
First, "decimal digits" means only the characters to the right of the decimal point. Converting the number to a string sets you up as JavaScript strings are arrays of characters. So, then it's just a matter of splitting out the decimal digits then summing them by iterating that array, then converting back to a number type.
//'Write a function named sumDigits which takes a number as input and returns the sum of each of the number's decimal digits.'
var a = 10.12345;
var b = -1012345;
function sumDigits(x){
var result = 0;
x = x.toString();
x = x.split('.')[1];
if (x == null){
//there's not decimal digits to sum!
return "there's not decimal digits to sum!"
}
for (var i = 0; i < x.length; i++) {
if (digit >= 0 && digit <= 9) { //just in case, probably unnecessary
var digit = Number(x[i]);
result = result + digit;
}
}
//if you care about negative uncomment this
//if(x[0] === "-"){
// result = result * -1;
//}
return result;
}
console.log(sumDigits(a));
console.log(sumDigits(b));
// try this to get the sum of negatives:
const sumOfNegative = (numbers) => {
let sum = 0;
numbers.forEach((number) => {
if (number < 0) {
sum += number;
}
});
return sum;
};

Split number into 4 random numbers

I want to split 10 into an array of 4 random numbers, but neither can be 0 or higher than 4. For example [1,2,3,4], [1,4,4,1] or [4,2,3,1].
I think it's an easy question, but for some reason I can't think of how to do this. If someone has some instruction that would be very helpful!
Edit:
This is the code I have now, but I generates also a total number under 10:
let formation = [];
let total = 0;
for (let i = 0; i < 4; i ++) {
if (total < 9) {
formation[i] = Math.floor(Math.random() * 4) + 1;
} else {
formation[i] = 1;
}
}
You could create all possible combinations and pick a random array.
function get4() {
function iter(temp) {
return function (v) {
var t = temp.concat(v);
if (t.length === 4) {
if (t.reduce(add) === 10) {
result.push(t);
}
return;
}
values.forEach(iter(t));
};
}
const
add = (a, b) => a + b,
values = [1, 2, 3, 4],
result = [];
values.forEach(iter([]));
return result;
}
console.log(get4().map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
An algorithm for getting random values without a list of all possible combinations
It works by using a factor for the random value and an offset, based on the actual sum, index, minimum sum which is needed for the next index, and the maximum sum.
The offset is usually the minimum sum, or the greater value of the difference of sum and maximum sum. For getting the factor, three values are taken for the minimum for multiplying the random value.
The table illustrates all possible values of the sum and the needed iterations, based on a given value and the iteration for getting all values.
At the beginning the sum is the value for distribution in small parts. The result is the second block with a rest sum of 14 ... 10, because it is possible to take a value of 1 ... 5. The third round follows the same rules. At the end, the leftover sum is taken as offset for the value.
An example with 1, ..., 5 values and 5 elements with a sum of 15 and all possibilities:
min: 1
max: 5
length: 5
sum: 15
smin = (length - index - 1) * min
smax = (length - index - 1) * max
offset = Math.max(sum - smax, min)
random = 1 + Math.min(sum - offset, max - offset, sum - smin - min)
index sum sum min sum max random offset
------- ------- ------- ------- ------- -------
_ 0 15 4 20 5 1
1 14 3 15 5 1
1 13 3 15 5 1
1 12 3 15 5 1
1 11 3 15 5 1
_ 1 10 3 15 5 1
2 13 2 10 3 3
2 12 2 10 4 2
2 11 2 10 5 1
2 10 2 10 5 1
2 9 2 10 5 1
2 8 2 10 5 1
2 7 2 10 5 1
2 6 2 10 4 1
_ 2 5 2 10 3 1
3 10 1 5 1 5
3 9 1 5 2 4
3 8 1 5 3 3
3 7 1 5 4 2
3 6 1 5 5 1
3 5 1 5 4 1
3 4 1 5 3 1
3 3 1 5 2 1
_ 3 2 1 5 1 1
4 5 0 0 1 5
4 4 0 0 1 4
4 3 0 0 1 3
4 2 0 0 1 2
4 1 0 0 1 1
The example code takes the target 1, ..., 4 with a length of 4 parts and a sum of 10.
function getRandom(min, max, length, sum) {
return Array.from(
{ length },
(_, i) => {
var smin = (length - i - 1) * min,
smax = (length - i - 1) * max,
offset = Math.max(sum - smax, min),
random = 1 + Math.min(sum - offset, max - offset, sum - smin - min),
value = Math.floor(Math.random() * random + offset);
sum -= value;
return value;
}
);
}
console.log(Array.from({ length: 10 }, _ => getRandom(1, 4, 4, 10).join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
The simplest solution is brute force.
Make a while loop to nest your calculations in
In the loop, create an empty array and fill it with random values until length is reached
Check if the sum of the array is your desired value, and if it is then break the loop
The above should run until you have a result.
Two things worth considering though.
Your can easily test if a solution is at all possible by calculating, that length-of-array times minimum-value isn't more than the sum and length-of-array times maximum-value isn't less than the sum.
A loop based on random conditions could potentially run forever, so a maximum amount of iterations might be desirable.
Both of these points are considered in the snippet below:
function randomNumber(max, min) {
while (true) {
var r = Math.round(Math.random() * max);
if (r >= min) {
return r;
}
}
}
function splitXintoYComponentsBetweenMaxAndMin(numberToSplit, numberOfSplits, maxValue, minValue, onUpdate) {
if (minValue === void 0) {
minValue = 1;
}
//Test that a result can exist
if (maxValue * numberOfSplits < numberToSplit || minValue * numberOfSplits > numberToSplit) {
return new Promise(function(resolve, reject) {
resolve(false);
});
}
//Create returner array
var arr = [];
var accumulator = 0;
while (arr.length < numberOfSplits) {
var val = randomNumber(Math.floor(numberToSplit / numberOfSplits), minValue);
accumulator += val;
arr.push(val);
}
return new Promise(function(resolve, reject) {
function runTest() {
var d = Date.now();
var localMaxValue = Math.min(maxValue, Math.ceil((numberToSplit - accumulator) / 4));
//Combination loop
while (accumulator < numberToSplit && Date.now() - d < 17) {
var index = Math.round(Math.random() * (arr.length - 1));
if (arr[index] >= maxValue) {
continue;
}
var r = randomNumber(localMaxValue, minValue);
while (arr[index] + r > maxValue || accumulator + r > numberToSplit) {
if (Date.now() - d >= 17) {
break;
}
r = randomNumber(localMaxValue, minValue);
}
if (arr[index] + r > maxValue || accumulator + r > numberToSplit) {
continue;
}
arr[index] += r;
accumulator += r;
}
if (accumulator < numberToSplit) {
if (onUpdate !== void 0) {
onUpdate(arr);
}
requestAnimationFrame(runTest);
} else {
resolve(arr);
}
}
runTest();
});
}
//TEST
var table = document.body.appendChild(document.createElement('table'));
table.innerHTML = "<thead><tr><th>Number to split</th><th>Number of splits</th><th>Max value</th><th>Min value</th><th>Run</th></tr></thead>" +
"<tbody><tr><th><input id=\"number-to-split\" value=\"10\" type=\"number\" min=\"1\"/></th><th><input id=\"number-of-splits\" value=\"4\" type=\"number\" min=\"1\"/></th><th><input id=\"max-value\" type=\"number\" min=\"1\" value=\"4\"/></th><th><input id=\"min-value\" type=\"number\" min=\"1\" value=\"1\"/></th><th><input id=\"run\" type=\"button\" value=\"Run\"/></th></tr></tbody>";
var output = document.body.appendChild(document.createElement('pre'));
output.style.overflowX = "scroll";
document.getElementById("run").onclick = function() {
splitXintoYComponentsBetweenMaxAndMin(parseInt(document.getElementById("number-to-split").value, 10), parseInt(document.getElementById("number-of-splits").value, 10), parseInt(document.getElementById("max-value").value, 10), parseInt(document.getElementById("min-value").value, 10))
.then(function(data) {
if (data !== false) {
output.textContent += data.join("\t") + '\n';
} else {
output.textContent += 'Invalid data\n';
}
});
};
EDIT 1 - Big calculations
Using requestAnimationFrame and Promises the code can now execute asynchronously, which allows for longer calculation time without bothering the user.
I also made the random function scale with the remaining range, greatly reducing the amount of calculations needed for big numbers.
A litte late to the show, but I found this a fun task to think about so here you go. My approach does not need to create all partitions, it also does not rely on pure luck of finding a random match, it is compact and it should be unbiased.
It works efficiently even when large values are used, as long as max is not too limiting.
const len = 4;
const total = 10;
const max = 4;
let arr = new Array(len);
let sum = 0;
do {
// get some random numbers
for (let i = 0; i < len; i++) {
arr[i] = Math.random();
}
// get the total of the random numbers
sum = arr.reduce((acc, val) => acc + val, 0);
// compute the scale to use on the numbers
const scale = (total - len) / sum;
// scale the array
arr = arr.map(val => Math.min(max, Math.round(val * scale) + 1));
// re-compute the sum
sum = arr.reduce((acc, val) => acc + val, 0);
// loop if the sum is not exactly the expected total due to scale rounding effects
} while (sum - total);
console.log(arr);
Basically you need the partitions (See https://en.wikipedia.org/wiki/Partition_(number_theory)) of 10 and apply your conditions on the resulting set.
// Partition generator taken from
// https://gist.github.com/k-hamada/8aa85ac9b334fb89ac4f
function* partitions(n) {
if (n <= 0) throw new Error('positive integer only');
yield [n];
var x = new Array(n);
x[0] = n;
for (var i = 1; i < n; i++) x[i] = 1;
var m = 0, h = 0, r, t;
while (x[0] != 1) {
if (x[h] == 2) {
m += 1;
x[h] = 1;
h -= 1;
} else {
r = x[h] - 1;
x[h] = r;
t = m - h + 1;
while (t >= r) {
h += 1;
x[h] = r;
t -= r;
}
m = h + (t !== 0 ? 1 : 0);
if (t > 1) {
h += 1;
x[h] = t;
}
}
yield x.slice(0, m + 1);
}
}
results = [];
// Get all possible partitions for your number
for (var partition of partitions(10)) {
// Apply your conditions (must be 4 numbers, none of them greater than 4)
if(partition.length != 4 || partition.some((x) => x > 4)) continue;
results.push(partition);
}
console.log(results);
Given that:
In a collection of n positive numbers that sum up to S, at least one of them will be less than S divided by n (S/n)
and that you want a result set of exactly 4 numbers,
you could use the following algorithm:
Get a random number from range [1, floor(S/n)], in this case floor(10/4) = 2, so get a random number in the range of [1,2]. Lets mark it as x1.
Get a random number from range [1, floor((S - x1)/(n - 1))]. Lets mark it as x2.
Get a random number from range [1, floor((S - x1 - x2)/(n - 2))].
Continue until you get x(n-1).
Get the last number by doing S - x1 - x2 .... - x(n-1).
Finally, extend the above algorithm with a condition to limit the upper limit of the random numbers.
In n steps, you can get a collection.
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomCollection(min, max, length, sum) {
var collection = [];
var leftSum = sum - (min - 1);
for(var i = 0; i < length - 1; i++) {
var number = getRandomInt(min, Math.min(Math.ceil(leftSum/(length - i)), max));
leftSum -= number;
collection.push(number);
}
leftSum += min - 1;
while(leftSum > max) {
var randomIndex = Math.floor(Math.random() * collection.length);
if(collection[randomIndex] < max) {
collection[randomIndex]++;
leftSum--;
}
}
collection.push(leftSum);
return collection;
}
console.log(getRandomCollection(1, 4, 4, 10).join(' + ') + ' = 10');
console.log(getRandomCollection(3, 20, 10, 100).join(' + ') + ' = 100');
Reference
My answer using the same algorithm for another question
Quick and simple but biased and nondeterministically terminating
function partition(sum, len, min, max) {
const a = Array(len).fill(min)
while (a.reduce((acc,val)=>acc+val) < sum) {
const i = Math.random()*len|0
if (a[i] < max) a[i]++
}
return a
}
console.log(Array(10).fill().map(_=>partition(10, 4, 1, 4).join(' ')))
.as-console-wrapper { max-height: 100% !important; top: 0; }
The while loop can loop forever with an infinitesimal probability. To prevent this, you can keep another array of "valid indexes" and delete keys of it when the value reaches max.
this calculates a random number from 1 to 4
wrap it on a function to your needs to generate the arrays
Math.floor(Math.random() * 4) + 1
var randomNumber = Math.floor(Math.random() * 4) + 1 ;
console.log(randomNumber);
It was too easy.
var values = null;
while(true) {
var currentSum = 0;
var expectedSum = 10;
values = [];
while(expectedSum !== currentSum) {
//var value = Math.floor(Math.random() * 9) + 1;
var value = Math.floor(Math.random() * 4) + 1;
if(value + currentSum > expectedSum) {
continue;
}
currentSum += value;
values.push(value);
}
if(values.length === 4) {
break;
} else {
console.log('false iteration')
}
}
console.log(values);

I need to sum all odd fibonacci numbers but only works for some numbers

Task: Given a positive integer num, return the sum of all odd Fibonacci numbers that are less than or equal to num.
The first two numbers in the Fibonacci sequence are 1 and 1. Every additional number in the sequence is the sum of the two previous numbers. The first six numbers of the Fibonacci sequence are 1, 1, 2, 3, 5 and 8.
For example, sumFibs(10) should return 10 because all odd Fibonacci numbers less than 10 are 1, 1, 3, and 5.
This is on freecodecamp. I have looked at examples I know I could of easily copied them but I wanted to write my own code, can someone explain why I get these results and where I've gone wrong? Thanks.
function sumFibs(num) {
var arr = [0, 1, 1]; //array of fibonacci numbers
var fin = 0; //variable for final number
for(var i = 3;i < 35;i++)
{
arr[i] = arr[i-1] + arr[i-2];
}
// loop to make fibonacci numbers
for(var x = 0; x < arr.length-1; x++)
{
if(arr[x] <= num && (arr[x] % 2 === 0))
{
fin += arr[x];
}//if to check if array of fibonacci numbers[x] is less than num && if it is odd
}//loop to go through every fibonacci number
return fin;
}
sumFibs(1000);
When you have the modulo operation:
if(arr[x] <= num && (arr[x] % 2 === 0))
You are asking two things:
if the arr[x] value is less than the number (check)
if the arr[x] value is even, NOT odd.
That is where your issue is occurring.
Rather you should use:
if(arr[x] <= num && (arr[x] % 2 != 0))
This is my solution :
function sumFibs(num)
{
var prev=0,curr=1,result=0,added;
while(curr<=num)
{
if(curr % 2 !=0)
{
result+=curr;
}
added= curr+prev;
prev=curr;
curr=added;
}
return result;
}
sumFibs(4);
Give this a try
function sumFibs(num) {
var firstNum = 0;
var secondNum = 1;
var sequence = [];
var index = [];
while (firstNum <= num) {
sequence.push(firstNum, secondNum);
firstNum = firstNum + secondNum;
secondNum = firstNum + secondNum;
/**/
}
for (var key in sequence) {
if (sequence[key] <= num) {
index.push(sequence[key]);
}}
//return index;
var oddIndex = [];
for (var key in index) {
if (index[key] % 2 !== 0) {
oddIndex.push(index[key]);
}
}
// return oddIndex;
var output = oddIndex.reduce(function(a,b){
return a+b;
});
return output;
}
sumFibs(75025); //should return 135721

Categories

Resources