How do I get Fibonacci numbers in an array? - javascript

Given input = [1,2,4] return [1,2], or if no fibonacci numbers return [], [1,1,2] should return [1,2];
I know you can check whether a number is in the fibonacci sequence with this code:
function isSquare(n) {
return n > 0 && Math.sqrt(n) % 1 === 0;
};
//Equation modified from http://www.geeksforgeeks.org/check-number-fibonacci-number/
function isFibonacci(numberToCheck)
{
// numberToCheck is Fibinacci if one of 5*n*n + 4 or 5*n*n - 4 or both
// is a perferct square
return isPerfectSquare(5*numberToCheck*numberToCheck + 4) ||
isPerfectSquare(5*numberToCheck*numberToCheck - 4);
}
But I don’t know how to implement it. Thanks.

Array.from(new Set(arr)) Removes duplicates from the original array
let newArr = []; Defining the new array
for ( let i = 0; i < arrD.length; i++ ) Loop every number of arrD, arrD[i] accesses a number in the array
if(fib(arrD[i])) { newArr.push(arrD[i]); } if the number is in the fibonacci sequence, fib(arrD[i]) will return true, and the number will be .pushed into the newArr
Using a for loop
let arr = [1,2,3,8,3,8];
let sqrt = (num) => { return num > 0 && Math.sqrt(num) % 1 === 0; };
let fib = (num) => { return sqrt(5 * Math.pow(num,2) + 4) || sqrt(5 * Math.pow(num,2) - 4); };
function fibArr(arr) {
arrD = Array.from(new Set(arr));
let newArr = [];
for ( let i = 0; i < arrD.length; i++ ) {
if(fib(arrD[i])) { newArr.push(arrD[i]); }
}
return newArr;
}
console.log(fibArr(arr));
OR using .filter
let arr = [1,2,3,8,3,8];
let sqrt = (num) => { return num > 0 && Math.sqrt(num) % 1 === 0; };
let fib = (num) => { return sqrt(5 * Math.pow(num,2) + 4) || sqrt(5 * Math.pow(num,2) - 4); };
function fibArr(arr) {
arrD = Array.from(new Set(arr));
let newArr = arrD.filter(function(arrD){
return fib(arrD);
})
return newArr;
}
console.log(fibArr(arr));

Related

sample array n^2 times without the same number occurring twice in a row and not repeating every n

I'm trying to write a function that has the arguments of the array to sample arr and the number of samples, size (which is sqaured) and randomly samples from the original array:
arr = [1,2,3,4]
single_number = (x) => {
return x[Math.floor(Math.random()*x.length)];
}
randomize = (arr, size) => {
return Array(size*size).fill().map(x => single_number(arr))
}
randomize(arr, 5)
I want to add the additional requirements to my randomize function:
no number shows up twice in a row
make sure every sizeth item is not the same as the one before it
For example
randomize([1,2,3,4], 2)
[2,4,3,2,4,1,1,2,2,1,4,1,1,1,3,1,1,4,4,1,3,3,2,2,3]
CASE (1)
[
2,4,3,2,4,
2,1,
2,2, // illegal!
1,4,
1,1,1, // illegal!
3,
1,1, // illegal!
4,4, // illegal!
1,
3,3, // illegal!
2,2, // illegal!
3
]
CASE (2)
[
2,4,3,2,4, [0] === 2
2,1,2,2,1, [5] === 2 // illegal!
4,1,1,1,3,
1,1,4,4,1,
3,3,2,2,3
]
I'm trying to use functional programming and avoid a for loop if possible since I think I can do this with a nested for loop?
Well, this isn't as pretty as one would hope, but I think it accomplishes the objective: Iterate size^2 times and choose random elements from the input, taking care to exclude the last value and last nth value chosen...
const randomize = (array, size) => {
const rand = () => Math.floor(Math.random() * array.length);
const randExcept = exclude => {
let v = array[rand()];
while (exclude.includes(v)) v = array[rand()];
return v;
}
const indexes = Array.from(Array(size*size).keys());
let lastV = null, nthV = null;
return indexes.map(i => {
let exclude = nthV!==null && i%size===1 ? [lastV, nthV] : [lastV];
let v = randExcept(exclude);
lastV = v;
if (i%size===1) nthV = v;
return v;
})
}
console.log( JSON.stringify(randomize([1,2,3,4], 2)) )
This defines nth values by the count into the array, so for size===2, the constraint is that every second element (indexes 1,3,5...) can't be equal to the prior second element.
I'd probably do something like this:
const values = [1,2,3,4]
function randomize(values, size) {
let prev;
let prevNth;
return Array(size*size).fill().map( randomNumber );
function randomNumber(_,i) {
let value, ok;
do {
value = values[ Math.floor( Math.random() * values.length ) ];
ok = value != prev;
if ( i % size === 0) {
ok = ok && value != prevNth;
prevNth = value;
}
prev = value;
} while (!ok);
return value;
}
}
arr = randomize(values, 5)
console.log(JSON.stringify(arr));
Or this, using a generator to generate the appropriately sized stream of randomness:
const values = [1,2,3,4];
const arr1 = Array.from( randomValues(5,values) );
console.log(JSON.stringify(arr1));
function *randomValues(n, values) {
const limit = n*n;
let prev, prevNth;
for ( let i = 0 ; i < limit ; ++i ) {
const isNthValue = i % n === 0;
const value = randomValue( values, prev, isNthValue ? prevNth : undefined );
yield value;
prev = value;
prevNth = isNthValue ? value : prevNth;
}
}
function randomValue(values, test1, test2 ) {
let value;
do {
value = values[ Math.floor( Math.random() * values.length ) ];
} while (value === test1 || value === test2 );
return value;
}

How do I solve this specific algorithm in JavaScript?

Given this array: arr = [ '00011100', '00000001', '00101101', '11111111' ];
If the element is on even position in the array, I have to remove all the chars with even index from this element and vice versa. Example:
The first element is on even position:
arr[0] = '00011100'
The second element is on odd position:
arr[1] = '00000001';
I have to remove those characters and return them as concatenated string.
Output of the whole array // 0110 0000 0011 1111
Please, help me solve this task :) Thank you in advance!
let enigma = "";
for(let i = 0; i < arr.length; i++){
let index = arr[i];
let evenStr = "";
let oddStr = "";
if(index % 2 === 0) {
for(let j = 1; j < index.length; j+=2) {
evenStr += index[j];
} enigma += evenStr;
} else if(index % 2 !== 0) {
for(let x = 1; x < index.length; x+=2) {
oddStr += index[x];
} enigma += oddStr;
}
}
console.log(enigma) //0110000100111111;
This is my code so far but the output I recieve is slightly different :/
Here is a potential solution to your problem.
Using reduce()
const removeOddIndex = ( str ) => {
return str.split("").filter( ( element, index ) => index % 2).join("");
}
const removeEvenIndex = ( str ) => {
return str.split("").filter( ( element, index ) => !( index % 2 )).join("");
}
const array = [ '00011100', '00000001', '00101101', '11111111' ];
const result = array.reduce( ( acc, cur, index ) => {
if( index % 2 ) {
acc[index] = removeEvenIndex( cur );
} else {
acc[index] = removeOddIndex( cur );
}
return acc;
}, array).join("")
console.log(result)
Using map()
const removeOddIndex = ( str ) => {
return str.split("").filter( ( element, index ) => index % 2).join("");
}
const removeEvenIndex = ( str ) => {
return str.split("").filter( ( element, index ) => !( index % 2 )).join("");
}
const array = [ '00011100', '00000001', '00101101', '11111111' ];
const result = array.map( ( element, index ) => {
return index % 2 ? removeEvenIndex( element ) : removeOddIndex( element )
} ).join("");
console.log(result)
You can easily achieve this using map, split and join
const arr = ["00011100", "00000001", "00101101", "11111111"];
const getEven = (value) =>
value
.split("")
.filter((el, i) => i % 2 === 0)
.join("");
const getOdd = (value) =>
value
.split("")
.filter((el, i) => i % 2 === 1)
.join("");
const result = arr
.map((val, index) => {
if (index % 2 === 0) return getOdd(val);
else return getEven(val);
})
.join("");
console.log( result );
You could filter by taking the remainder of the item of the outer element and the elment's values.
const
array = ['00011100', '00000001', '00101101', '11111111'],
result = array.map(([...a], i) => a.filter((v, j) => i % 2 !== j % 2).join(''));
console.log(result);

Is there any way to sum all sub array item and then multiply all sub arrays using a 'for' or 'for-of' loop?

i want to create a function using for() or for of() loop, which take an nested array as argument then add and multiply its item.
Suppose, myArray = [[5,6],[9,2],[4,8]]
Now i want to process it like: [[5+6] * [9+2] * [4+8]]
I solve it using .map() and .reduce(), but is there any way to do same using classic for() or for of() loop. this is my trial.
let myArray = [[1,2],[3,4],[5,6]]
function multyPlus(array) {
resul = 0
for (const subArray of array) {
for (const num of subArray) {
resul += num
}
resul *= subArray
}
return resul
}
console.log(multyPlus(myArray));
//Nan
I would try a two step system that first adds the numbers, then multiplies it to the previous numbers:
function sum(array) {
var total = 0;
for (var item of array)
total += item;
return total;
}
var myArray = [[5,6],[9,2],[4,8]];
var output = 1;
for (var item of myArray)
output *= sum(item);
Maybe Like This:
let myArray = [[1,2],[3,4],[5,6]]
function multyPlus(_array){
var out = 1;
for(var key1 in _array){
var out2 = 0;
for(var key2 in _array[key1]){
out2 += _array[key1][key2];
}
out = out * out2;
}
return out;
}
console.log(multyPlus(myArray));
You can define separate adder and multiplier functions -
const adder = (nums = []) =>
{ let r = 0
for (const n of nums)
r += n
return r
}
const multiplier = (nums = []) =>
{ let r = 1
for (const n of nums)
r *= n
return r
}
const myCalc = (input = []) =>
{ const r = []
for (const x of input)
r.push(adder(x))
return multiplier(r)
}
const result =
myCalc([[1,2],[3,4],[5,6]])
console.log(result) // 231
That said, I think the functional approach is superior when you use named functions. Each function is highly reusable and there's virtually no room for bugs to hide -
const add = (x = 0, y = 0) =>
x + y
const mult = (x = 0, y = 0) =>
x * y
const sum = (nums = []) =>
nums.reduce(add, 0)
const product = (nums = []) =>
nums.reduce(mult, 1)
const myCalc = (input = []) =>
product(input.map(sum)) // <-- easy peasy!
const result =
myCalc([[1,2],[3,4],[5,6]])
console.log(result) // 231
If you have something against map and reduce, you can write myCalc and sum by hand using simple recursion -
const sum = ([ x, ...more ]) =>
x === undefined
? 0
: x + sum(more)
const myCalc = ([ x, ...more ]) =>
x === undefined
? 1
: sum(x) * myCalc(more)
const result =
myCalc([[1,2],[3,4],[5,6]])
console.log(result) // 231

What's wrong in my code? It fails just 2 of the test cases without showing any error

I have started learning programming on my own just a few months back. So pardon me if my question sounds a bit silly.
One of the challenges on freeCodeCamp needs to define a function that takes an array with 2 values as an input and the function should return the LCM of all the numbers within that range inclusive of those 2 numbers.
My code below passes the tests number 1,2,3,6 given in the exercise. but somehow fails for the tests 4 & 5. Also freeCodeCamp is not showing any error! So I am unable to figure out what am I doing wrong in the below code.
function smallestCommons(arr) {
let allNum = [];
for (let i = Math.min(...arr); i <= Math.max(...arr); i++) {
allNum.push(i);
}
function findFactors(x) {
let allFactors = [];
for (let i = 1; i <= x; i++) {
if (x % i == 0) {
allFactors.push(i);
}
}
return allFactors;
}
function findGCF(a,b) {
return findFactors(a).filter(item => findFactors(b).includes(item)).reduce((p,q) => p*q);
}
return allNum.reduce((a,b) => ((a*b)/findGCF(a,b)));
}
The tests given in the exercise are as follows. My code passes 1,2,3 & 6 but fails 4 & 5.
smallestCommons([1, 5]) should return a number.
smallestCommons([1, 5]) should return 60.
smallestCommons([5, 1]) should return 60.
smallestCommons([2, 10]) should return 2520.
smallestCommons([1, 13]) should return 360360.
smallestCommons([23, 18]) should return 6056820.
function smallestCommons(arr) {
let allNum = [];
for (let i = Math.min(...arr); i <= Math.max(...arr); i++) {
allNum.push(i);
}
function findFactors(x) {
let allFactors = [];
for (let i = 1; i <= x; i++) {
if (x % i == 0) {
allFactors.push(i);
}
}
return allFactors;
}
function findGCF(a,b) {
return findFactors(a).filter(item => findFactors(b).includes(item)).reduce((p,q) => p*q);
}
return allNum.reduce((a,b) => ((a*b)/findGCF(a,b)));
}
console.log(smallestCommons([1, 5])); // should return a number.
console.log(smallestCommons([1, 5])); // should return 60.
console.log(smallestCommons([5, 1])); // should return 60.
console.log(smallestCommons([2, 10])); // should return 2520.
console.log(smallestCommons([1, 13])); // should return 360360.
console.log(smallestCommons([23, 18])); // should return 6056820.
Your findGCF function is off. To find the GCF of two numbers, you should find the largest factor which evenly divides both. Eg
findGCF(60, 6)
should be 6. (But yours returns 36)
function findFactors(x) {
// console.log(x);
let allFactors = [];
for (let i = 1; i <= x; i++) {
if (x % i === 0) {
allFactors.push(i);
}
}
return allFactors;
}
function findGCF(a, b) {
const bFac = findFactors(b);
return findFactors(a)
.filter(item => bFac.includes(item))
.reduce((p, q) => p * q);
}
console.log(findGCF(60, 6)); // should be 6
To reduce the computational complexity and fix it at the same time, make a Set of one of the factor collections, then iterate over an array of the other factor collections, starting from the largest factor and working your way downwards, and .find the first factor which is contained in the Set (it may end up being 1):
function findGCF(a, b) {
const bFacSet = new Set(findFactors(b));
return findFactors(a)
.reverse()
.find(item => bFacSet.has(item));
}
Fix that, and your smallestCommons function works as desired:
function smallestCommons(arr) {
const allNum = [];
for (let i = Math.min(...arr); i <= Math.max(...arr); i++) {
allNum.push(i);
}
function findFactors(x) {
const allFactors = [];
for (let i = x; i >= 1; i--) {
if (x % i === 0) {
allFactors.push(i);
}
}
return allFactors;
}
function findGCF(a, b) {
const bFacSet = new Set(findFactors(b));
return findFactors(a)
.find(item => bFacSet.has(item));
}
return allNum.reduce((a,b) => ((a*b)/findGCF(a,b)));
}
console.log(smallestCommons([2, 10])) // should return 2520.
console.log(smallestCommons([1, 13])) // should return 360360.

javascript least amount of elements from an integer array that can be used to get to a total value

please can somebody help?
If i have a total or a sum for instance 91
How can I create an array of the least amount of elements needed to get to the total value?
[50, 20, 10 , 5, 3, 2, 1] totaling this array will provide 91.
I know how to perform the opposite function using reduce or like so:
<script>
var numbers = [65, 44, 12, 4];
function getSum(total, num) {
return total + num;
}
function myFunction(item) {
document.getElementById("demo").innerHTML = numbers.reduce(getSum);
}
</script>
Greedy algorithm
Here is a solution using greedy algorithm. Note that this solution will work correctly in case when all the smaller numbers are divisors of all the bigger numbers such as in case [50, 10, 5, 1]. (see dynamic algorithm below this one for solution that can handle any input)
50 mod 10 = 0
50 mod 5 = 0
50 mod 1 = 0
10 mod 5 = 0
10 mod 1 = 0
5 mod 1 = 0
const sum = xs => xs.reduce((acc, v) => acc + v, 0);
function pickSubset(options, total, currentPick) {
if (sum(currentPick) === total) { return currentPick; }
if (options.length === 0) { return null; }
const firstVal = options[0];
let res = null;
if (sum(currentPick) + firstVal > total) {
res = pickSubset(options.slice(1), total, currentPick);
} else {
let opt1 = pickSubset(options, total, currentPick.concat(options[0]));
let opt2 = pickSubset(options.slice(1), total, currentPick.concat(options[0]));
if (opt1 && opt2) {
opt1.length < opt2.length ? res = opt1 : res = opt2
} else if (opt1) {
res = opt1;
} else {
res = opt2;
}
}
return res;
}
const total = 73;
const options = [50, 25, 10, 5, 2, 1];
console.log(pickSubset(options, total, []));
To handle unsorted input you can wrap it in another function and sort it prior to passing it to the main function.
const sum = xs => xs.reduce((acc, v) => acc + v, 0);
function pickSubset(options, total, currentPick) {
const sortedOptions = options.sort((a, b) => b - a);
function _pickSubset(options, total, currentPick) {
if (sum(currentPick) === total) { return currentPick; }
if (options.length === 0) { return null; }
const firstVal = options[0];
let res = null;
if (sum(currentPick) + firstVal > total) {
res = pickSubset(options.slice(1), total, currentPick);
} else {
let opt1 = pickSubset(options, total, currentPick.concat(options[0]));
let opt2 = pickSubset(options.slice(1), total, currentPick.concat(options[0]));
if (opt1 && opt2) {
opt1.length < opt2.length ? res = opt1 : res = opt2
} else if (opt1) {
res = opt1;
} else {
res = opt2;
}
}
return res;
}
return _pickSubset(sortedOptions, total, currentPick);
}
const total = 73;
const options = [50, 25, 10, 5, 2, 1].reverse();
console.log(pickSubset(options, total, []));
Dynamic programming (bottom-up natural ordering approach)
This solution works correctly for any type of input.
function pickSubset(options, total) {
function _pickSubset(options, change, minNums, numsUsed) {
for (let i = 0; i < change + 1; i++) {
let count = i;
let newNum = 1;
let arr = options.filter(v => v <= i);
for (let j of arr) {
if (minNums[i - j] + 1 < count) {
count = minNums[i - j] + 1;
newNum = j;
}
}
minNums[i] = count;
numsUsed[i] = newNum;
}
return minNums[change];
}
function printNums(numsUsed, change) {
const res = [];
let num = change;
while (num > 0) {
let thisNum = numsUsed[num];
res.push(thisNum);
num = num - thisNum;
}
return res;
}
const numsUsed = [];
const numsCount = [];
_pickSubset(options, total, numsCount, numsUsed);
return printNums(numsUsed, total);
}
const options = [50, 10, 5, 2, 1];
console.log(pickSubset(options, 73));
Dynamic programming (top-down memoization approach)
// helper function that generates all the possible solutions
// meaning, all the possible ways in which we can pay the provided amount
// and caches those solutions;
// returns the number of possible solutions but that is not neccessary
// in this case
const _pickSubset = (toPay, options, currentPick, cache) => {
if (toPay < 0) { return 0; }
if (toPay === 0) {
cache.add(currentPick);
return 1;
}
if (options.length === 0) { return 0; }
return _pickSubset(toPay - options[0], options, currentPick.concat(options[0]), cache)
+ _pickSubset(toPay, options.slice(1), currentPick, cache);
};
// memoize only with respect to the first two arguments - toPay, bills
// the other two are not necessary in this case
const memoizeFirstTwoArgs = fn => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args.slice(0, 2));
if (cache.has(key)) { return cache.get(key); }
const res = fn(...args);
cache.set(key, res);
return res;
};
};
// uses memoized version of makeChange and provides cache to that function;
// after cache has been populated, by executing memoized version of makeChange,
// find the option with smallest length and return it
const pickSubset = (toPay, options) => {
const cache = new Set();
const memoizedPickSubset = memoizeFirstTwoArgs(_pickSubset);
memoizedPickSubset(toPay, options, [], cache);
let minLength = Infinity;
let resValues;
for (const value of cache) {
if (value.length < minLength) {
minLength = value.length;
resValues = value;
}
}
return resValues;
}
const options = [50, 25, 10, 5, 2, 1];
const toPay = 73;
console.log(pickSubset(toPay, options));

Categories