Distribute list of bits into given amount of slots - javascript

Given a bitfield like the following (numbers can only be 1 or 0):
const bits = [1, 1, 0, 1, 0, 0, 0, 1]
I want to produce a list of N average values where N is an arbitrary number.
In our example above, given N is 4, the result would be [1, 0.5, 0, 0.5]. (group the array 2 by 2 and then calculate the average number of each group).
If, instead, N was 2, the result would be [0.75, 0.25].
I have been using the following code so far:
const average = (...args) => args.reduce((a, b) => a + b) / args.length;
const averageNumbers = Ramda.splitEvery(Math.floor(bits.length / N), bits).map(nums => average(nums))
The problem is that the above doesn't work in case my bits array is composed of 696 values and I need 150 average numbers, because I end up having 174 numbers instead of 150.
What am I doing wrong?

As mentioned in the comments, you end up with 174 numbers instead of 150 because floor(696 / 150) divides the bit field into 174 chunks of 4 bits.
To get an approximate value for the averages, you can first "expand" the bit field to a length that is a multiple of N before taking the averages.
// Factor is the lowest number to expand bits by for its length to be a multiple of N
const factor = lcm(bits.length, N) / bits.length;
// Expand bits by the factor
const expandedBits = bits.map(bit => Array(factor).fill(bit)).flat(1);
const averages = splitEvery(Math.floor(expandedBits.length / N), expandedBits).map(nums => average(...nums));
// averages.length should now always be N

Related

find the min and max values in javaScript, i get incorrect result, what is wrong?

Given five positive integers, find the minimum and maximum values that can be calculated by summing exactly four of the five integers. Then print the respective minimum and maximum values as a single line of two space-separated long integers.
the expected Output is
299 9271
my output is
299 9266
the input is
7 69 2 221 8974
this is my function
function miniMaxSum(arr) {
let panjang = arr.length,
max = arr.slice(0, panjang-1),
min = arr.slice(1, panjang),
maxSum = max.reduce((total, item) => total+item),
minSum = min.reduce((total, item) => total+item);
process.stdout.write(`${maxSum} ${minSum}`);
}
can someone help me please?
By slicing from 0 to 4, and from 1 to 5, you're assuming that the array is already sorted, and that the items at index 0 and 5 are the maximum and minimum - which they aren't.
Either sort the array first, or use Math.max / Math.min to identify the smallest and largest, and subtract from the sum.
const arr = [7, 69, 2, 221, 8974];
const sum = arr.reduce((a, b) => a + b, 0);
const min = Math.min(...arr);
const max = Math.max(...arr);
console.log(sum - max, sum - min);

How to get a stable random number in a range given a seed?

Suppose I have:
a seed – an integer number, e.g. 1200303
a range for target values [1, 20]
Is there a mathematical way to get a random number in the [1, 20] range that is determined by the seed?
i.e.
rand(seed int, range [int, int]);
rand(1, [1, 20]); // "4"
rand(1, [1, 20]); // "4" (if seed and range is the same, I expect the same value)
rand(1, [1, 21]); // "6" (changing range changes random number)
rand(2, [1, 20]); // "9" (changing seed changes random number)
Turns out, I have been looking for what is called a pseudorandom number generator (PRNG).
There are many PRNG implementations. Mersenne Twister is the most popular but also has fairly weak security properties.
I went with https://www.npmjs.com/package/seeded-rand
const SEED = 123,
const LOWER_RANGE = 1;
const UPPER_RANGE = 100;
const srand = new Srand(SEED_ID);
const gifId = srand.intInRange(LOWER_RANGE, UPPER_RANGE);
This will provide a number between 1 and 100 that is deterministic, i.e. multiple program executions will return the same number given the same seed.
Update
Turns out my original attempt is not as random as I thought it to be.
https://github.com/DomenicoDeFelice/jsrand/issues/3
The solution is to hash the seed first, e.g.
import {
createHash,
} from 'crypto';
import Srand from 'seeded-rand';
const seed = createHash('sha1').update(String(SEED)).digest().readUInt32BE();
new Srand(seed).intInRange(1, UPPER_RANGE);
If you only need 1 determinstically random value per seed, then you don't need the random function at all here. Just do seed % UPPER_RANGE (see below).
Many PRNGs allow you to specify an output range; if not, they are usually from 0 (inclusive) to 1 (exclusive) and it's sufficient to basically do:
let range = (max - min);
Math.floor(value * range) + min
If you are taking this path, make sure to double-check that the chosen implementation is not 1 inclusive because then it will very occasionally overshoot the max.
Also, if you are okay with a recognizable pattern of predictability, then you can just use SEED % UPPER_RANGE, i.e.
123 % 20; // "3"
124 % 20; // "4"
// ...
164 % 20; // "4"
Thanks to joepie91 from Freenode for his guidance. I am just documenting his advice.
I wrote a concept of how to do this using simple math and loops. I'm sure the details can be improved, but in general, did you want something like this?
// Seed random (pseudo-random)
const seedRand = (num, range) => {
// Generate number multiplication
num = String(num).split('').reduce((c, n) => (n != 0) ? c * n : c * c);
// Transform to match range
let s = range[0],
e = range[1]
while(num < range[0] || num > range[1]) {
if(num > range[1]) num = Math.floor(num / e--);
if(num < range[0]) num = Math.floor(num * s++);
}
// Return value
return num;
}
// Test
console.log(seedRand(1220501, [1, 20]));
console.log(seedRand(1520502, [1, 20]));
console.log(seedRand(1520502, [1, 20])); // Same seed as previous one
console.log(seedRand(1370503, [1, 20]));
console.log(seedRand(1370503, [1, 21])); // Same seed as previous one, different range

Find the maximum product that can be formed by taking any one element from each sub-array

I am trying to write an efficient algorithm in JavaScript to solve this task. Please see the next examples of input data and correct results:
Array: [ [-3,-4], [1,2,-3] ] Result: (-4)*(-3) = 12
Array: [ [1,-1], [2,3], [10,-100,20] ] Result: (-1)*3*(-100) = 300
Array: [ [-3,-15], [-3,-7], [-5,1,-2,-7] ] Result: (-15)*(-7)*1 = 105
It can be any number of sub-arrays and any number of elements in each sub-array. What I already found is that I probably should leave only min and max values in the each sub-array, I did it using .map(a => [Math.min(...a), Math.max(...a)]) and sort them using .sort((a, b) => a[0] - b[0]).
And now I am stuck. Probably there is a way to calculate all possible products but I am sure that it's not an effective way to solve this task.
Please help!
The problem you post can be solved with a simple algorithm. We just need to keep tracking the maximum/minimum when iterating over each sub-array. We can keep finding the next maximum/minimum by multiplying the current maximum/minimum with the max/min value in each sub-array. We pick the maximum when the iterating is over. Its time complexity is O(n) where n is total number of elements in an array (i.e. sum of number of elements in each sub-array).
Here's the complete code. find_maximum_product function keeps tracking the minimum/maximum and returns the maximum eventually, and it also keeps tracking the multipliers and return it:
/**
* arr: array of any number of sub-arrays and
* any number of elements in each sub-array.
* e.g. [[1, -1], [2, 3], [10, -100, 20]]
*/
function find_maximum_product(arr) {
let max = 1;
let min = 1;
let max_multipliers = [];
let min_multipliers = [];
for (let i = 0; i < arr.length; i++) {
const a = Math.max(...arr[i]);
const b = Math.min(...arr[i]);
const candidates = [max * a, max * b, min * a, min * b];
max = Math.max(...candidates);
min = Math.min(...candidates);
let new_max_multipliers;
let new_min_multipliers;
switch (max) {
case candidates[0]:
new_max_multipliers = max_multipliers.concat(a);
break;
case candidates[1]:
new_max_multipliers = max_multipliers.concat(b);
break;
case candidates[2]:
new_max_multipliers = min_multipliers.concat(a);
break;
case candidates[3]:
new_max_multipliers = min_multipliers.concat(b);
break;
}
switch (min) {
case candidates[0]:
new_min_multipliers = max_multipliers.concat(a);
break;
case candidates[1]:
new_min_multipliers = max_multipliers.concat(b);
break;
case candidates[2]:
new_min_multipliers = min_multipliers.concat(a);
break;
case candidates[3]:
new_min_multipliers = min_multipliers.concat(b);
break;
}
max_multipliers = new_max_multipliers;
min_multipliers = new_min_multipliers;
}
if (max >= min) {
return [max, max_multipliers];
}
return [min, min_multipliers];
}
const arrays = [
[
[-3, -4],
[1, 2, -3],
],
[
[1, -1],
[2, 3],
[10, -100, 20],
],
[
[-3, -15],
[-3, -7],
[-5, 1, -2, -7],
],
[
[14, 2],
[0, -16],
[-12, -16],
],
[
[-20, -4, -19, -18],
[0, -15, -10],
[-13, 4],
],
[
[-2, -15, -12, -8, -16],
[-4, -15, -7],
[-10, -5],
],
];
for (let i = 0; i < arrays.length; i++) {
const [max, max_multipliers] = find_maximum_product(arrays[i]);
console.log('Array:', JSON.stringify(arrays[i]));
console.log('Result:', `${max_multipliers.join(' * ')} = ${max}`);
console.log('');
}
UPDATE
Simpler version for just getting the maximum, not getting the multipliers:
/**
* arr: array of any number of sub-arrays and
* any number of elements in each sub-array.
* e.g. [[1, -1], [2, 3], [10, -100, 20]]
*/
function get_maximum_product(arr) {
return arr
.map((a) => [Math.min(...a), Math.max(...a)])
.reduce(
(acc, current) => {
const candidates = [
acc[0] * current[0],
acc[0] * current[1],
acc[1] * current[0],
acc[1] * current[1],
];
return [Math.min(...candidates), Math.max(...candidates)];
},
[1, 1]
)[1];
}
Here is a top-down recurrence that could be adapted to bottom-up (a loop) and utilises O(n) search space.
Until I can complete it, the reader is encouraged to add a third return value in the tuple, largest_non_positive for that special case.
// Returns [highest positive, lowest negative]
// Does not address highest non-positive
function f(A, i){
const high = Math.max(...A[i]);
const low = Math.min(...A[i]);
if (i == 0){
if (low < 0 && high >= 0)
return [high, low];
if (low <= 0 && high <= 0)
return [-Infinity, low];
if (low >= 0 && high >= 0)
return [high, Infinity];
}
const [pos, neg] = f(A, i - 1);
function maybeZero(prod){
return isNaN(prod) ? 0 : prod;
}
let hp = maybeZero(high * pos);
let hn = maybeZero(high * neg);
let ln = maybeZero(low * neg);
let lp = maybeZero(low * pos);
if (low < 0 && high >= 0)
return [Math.max(hp, ln), Math.min(hn, lp)];
if (low <= 0 && high <= 0)
return [ln, lp];
if (low >= 0 && high >= 0)
return [hp, hn];
}
var As = [
[[-3,-4], [1,2,-3]],
[[1,-1], [2,3], [10,-100,20]],
[[-3,-15], [-3,-7], [-5,1,-2,-7]],
[[-11,-6], [-20,-20], [18,-4], [-20,1]],
[[-1000,1], [-1,1], [-1,1], [-1,1]],
[[14,2], [0,-16], [-12,-16]],
[[-20, -4, -19, -18], [0, -15, -10],[-13, 4]]
];
for (let A of As){
console.log(JSON.stringify(A));
console.log(f(A, A.length - 1)[0]);
console.log('');
}
Sort values in arrays by their absolute value in descending order
Check the product of first array elements if its positive its the answer
Otherwise lets call product p and we know p < 0, so if we change some positive element to some negative element or vice verse we will improve answer
we can simply check all possible elements to change, for each array a element x we can check if p / a[0] * x is better than current result if it is we update our answer
*Special case: all elements in arrays are negative and we have odd number of arrays, then we simply sort in increasing order
Complexity: O(n log n) where n is total amount of elements across all arrays
Take the product of the highest number of all the arrays that have at least one positive number.
If there's an odd number of remaining arrays (with only negatives), find the one with the highest (closest to zero) negative number, and set its absolute aside.
Take the arrays that remain after step 2, take the product of their lowest number (furthest from zero), and multiply it by the products from step 1 and (if any) step 2.
(also, avoid 0 if it would be the chosen number)
The first thing to notice is that there are only two specific cases where it's not possible to get a positive product. So I think an algorithm should first check if those specific cases are happening, then call a different subalgorithm for each of the three possible situations:
it is possible to get a positive product, so we want to find the highest positive product;
one of the arrays is full of zeroes, so all products are zero;
it is impossible to get a positive product, because no array has both positive and negative numbers, and there is an odd number of arrays with only negative numbers, so we want to find the closest to zero negative product.
The second and third cases lead to trivial algorithms.
Let's consider the first case.
For every array, the only numbers that can be useful in the highest product are the highest positive number, and the lowest negative number. If an array only has positive numbers or only has negative numbers, then there is only one useful number in that array, which can be chosen immediately.
For all the remaining arrays, you have to choose whether to use the positive or the negative number. Ideally, you want to use the one with the highest absolute value; but if you do that for every array, then the result might be negative.
This leads to a linear algorithm:
For all of the remaining arrays, initially select the number with the highest absolute value
If the resulting product is positive, you're done.
If the resulting product is negative, then a compromise has to be done in one of the arrays. For every array, compute the "cost" of this compromise (equal to the difference between the absolute values of the two interesting numbers in that array, multiplied by the product of all the other selected numbers).
Finally, choose the array whose cost is the lowest, and change the chosen number in that array.
Here is an example execution of the algorithm on the list of arrays [[18,19,20,-23], [12,-10,9,8],[-10,-3],[5,3],[-10,-5]].
Here we notice that it is possible to find a positive solution, because at least one of the arrays contains both negative and positive numbers.
For the last three arrays we have no choice between positive and negative: so we can already choose -10, 5 and -10 as the three numbers for these three arrays. For the first array, we'll have to choose between 20 and -23; and for the second array we'll have to choose between 12 and -10.
So the final product will be: (20 or -23) * (12 and -10) * (-10) * 5 * (-10).
Ideally, we would prefer 23 to 20, and 12 to 10. That would result in:
(-23) * 12 * (-10) * 5 * (-10)
Unfortunately, this is negative. So the question is: do we replace -23 with 20, or 12 with -10?
The cost of replacing -23 with 20 would be (23-20) * 11 * (10*5*10) = 33 * (10*5*10).
The cost of replacing 12 with -10 would be (12-10) * 21 * (10*5*10) = 42 * (10*5*10).
Finally, we choose to replace -23 with 20, because that is the less costly compromise.
The final product is 20 * 12 * (-10) * 5 * (-10).

How to sort an array of integers based on its binary representation in JavaScript?

Problem title: Binary Sort Ascending:
I have a task which consists of creating a function in JavaScript which orders an array that receives a list of unordered integers. The function must return an ordered array of integers according to the following criteria:
The greater number of ones in the binary representation of the integer, the closer to the index 0 the element should be.
In case two or more numbers have the same number of ones in their binary representation, the decimal number
of lesser value will be closer to the beginning.
Example:
For the entry: [1, 15, 5, 7, 3]
The return should be: [15, 7, 3, 5, 1]
Explanation:
Decimal = Binary
1 = 1
15 = 1111
5 = 101
7 = 111
3 = 11
The decimal number whose binary representation contains plus ones is 15 (1111 in binary), so it will go first in the array (index = 0). Then go on the 7, with three (111) ones in its binary representation.
Then there are 2 numbers whose binary representation contains
the same number of ones, these decimals are 5 (101) and 3 (11), both with 2 ones. In this case, it will go first (closer to index = 0) the 3, because it's decimal representation is smaller (3 < 5).
Solution:
Finally, I have found a way to solve this task:
const binaryOnes = integerArr => {
let binaryArray = integerArr.map(num => num.toString(2))
binaryArray.sort((a, b) => {
let regEx = /1/g
let A = a.match(regEx).length
let B = b.match(regEx).length
if (A < B) return 1
else if (A > B) return -1
else {
let binaryToIntegerA = parseInt(A, 2)
let binaryToIntegerB = parseInt(B, 2)
if (binaryToIntegerA < binaryToIntegerB) return -1
else return 1
}
})
return binaryArray.map(num => parseInt(num, 2))
}
binaryOnes([1,15,5,7,3]) // [ 15, 7, 3, 5, 1 ]
Please if anyone finds a better way to solve it, I will appreciate.
Also some feedback of this post (is my first question on StackOverflow)
Thanks!
You can convert a number into binary (string type) with something like
var binary = 134.toString(2);
Then, implement the comparison function between two numbers with
function binaryCompare(a, b) {
a = a.binary;
b = b.binary;
//...
}
After that, just call
[1,2,34,342]
.map( a => ({value:a, binary: a.toString(2))
.sort(binaryCompare)
.map( v => v.value );
As I don't understand your goal, I cannot implement the sort function.
Hope it helps

How To Get The Largest Sum From An Array With Iteration Funcrtion?

Hello Every one i want to solve this problem with javascript and es6 the problem is
if i have an array like that [1,2,3,4] so i want to check every probability like the following and return the greatest number
1--> (1*2) + (3*4) = 14
2--> (1*3) + (2*4) = 11
3--> (1*4) + (2*3) = 10
then the greatest number is 14 as a return result ---> how can i do that using function and keep in mind if the array have 100 number how can i do the 99 probabilities dynamically
notes : maybe the array is not sorted and it may be an odd not only even thank u
Multiplying the largest numbers with each other results in a larger sum than multiplying a large number with a low number and then sum them up (compare given a circumference a square is the rectangle with the largest surface area). One therefore only has to calculate [0]*[1] + [2]*[3] + [4]*[5] + ...
(assuming that the array length is even):
const array = [4,2,1,3].sort();
let sum = 0;
for(let i = 1; i < array.length; i += 2)
sum += array[i - 1] * array[i];
Edit: For that calculation with consecutive numbers starting from 1 one doesn't even need JS, the closed form for the sum is 1/3 * (n - 1)(4*n² - 5*n) (with n being the largest (even) number).
I agree with Stephen, Multiplying the largest numbers with each other results in a larger sum than multiplying a large number with a low number and then sum them up. And also you should be multiplying consecutive numbers in the array like (1*2)+(3*4)+(5*6)+...+(99*100)etc.
You don't need all the combinations.
Mathematically, you will always yield the highest values by multiplying the highest available numbers.
So, it would be pointless to multiply an high number with anything other then the second highest number.
const arr = [4, 3, 2, 5, 6, 7]
let sum = arr.sort().reduce((sum, val, idx) => sum += (idx % 2 !== 0) ? arr[idx - 1] * arr[idx] : 0 , 0)

Categories

Resources