Reputation: 152
I am looking to play around with probability that involves a lot if big numbers. To save computing time, I was thinking about having the computer cross out terms like you do in regular math. For example:
(2*3*7*3) / (3*2*3*3)
Can be simplified to 7/3
If I were to create a Javascript function and pass it two arrays containing multiplication numbers to cross out, how would I go about doing this?
Just to be clear:
If I passed in [3, 4, 6, 4]
and [4, 7, 3, 2]
, it would return two arrays: [4, 6]
and [7, 2]
Upvotes: 3
Views: 108
Reputation: 32831
Yes, or:
var arr1 = [5,2,3,7,8];
var arr2 = [3,5,2,3];
arr1.sort();
arr2.sort();
var i = 0, j = 0;
while (i < arr1.length && j < arr2.length) {
if (arr1[i] < arr2[j]) {
++i;
} else if (arr1[i] > arr2[j]) {
++j;
} else {
arr1.splice(i, 1);
arr2.splice(j, 1);
}
}
alert(arr1.toString() + "/" + arr2.toString());
UPDATE: to display a fraction
function prod(arr) {
var res = 1, i;
for (i = 0; i < arr.length; ++i) {
res *= arr[i];
}
return res;
}
alert(prod(arr1) + "/" + prod(arr2));
Upvotes: 2
Reputation: 1111
If you do not require cancellation beyond exact numbers, this should do:
var x = [3, 4, 6, 4];
var y = [4, 7, 3, 2];
for(var i in x)
{
for(var j in y)
{
if(x[i]==y[j])
{
x.splice(i,1);
y.splice(j,1);
}
}
}
console.log(x);
console.log(y);
But in case you are interested in further cancellation take this:
var x = [3, 4, 6, 4];
var y = [4, 7, 3, 2];
for(var i in x)
{
for(var j in y)
{
if(x[i]%y[j] == 0)
{
if(x[i]/y[j] > 1)
{
x[i] = x[i]/y[j];
}
else{
x.splice(i,1);
}
y.splice(j,1);
}
}
}
console.log(x);
console.log(y);
Upvotes: 2
Reputation: 15435
Here's a method to do this that has no dependencies. There's a couple of assumptions made that might bite you.
It tests numbers based on equality. In your use case (probability), this will bite on floating point values.
It might just be better to run the calculations. For all we know the JavaScript engine of choice is doing better optimizations anyhow.
Here's the code and example usage:
var numerator = [2,3,7,3],
denominator = [3,2,3,3],
numerator2 = [3,4,6,4],
denominator2 = [4,7,3,2];
function simplify(num, den) {
var value = {
numerator: num.slice(),
denominator: den.slice()
},
done = false,
remove = function (a, b) {
for (var aIdx = 0; aIdx < a.length; aIdx++) {
for (var bIdx = 0; bIdx < b.length; bIdx++) {
if (a[aIdx] === b[bIdx]) {
a.splice(aIdx, 1);
b.splice(bIdx, 1);
return;
}
}
}
done = true;
};
while (!done) {
remove(value.numerator, value.denominator);
}
return value;
}
simplify(numerator, denominator);
simplify(numerator2, denominator2);
Upvotes: 1
Reputation: 19750
Another method is to use a version of inArray (taken from jQuery), then check each element and remove elements as necessary. I'm not sure how well this would perform compared to just doing the calculations though, it would be worth testing on jsPerf.
For example:
removeDuplicates([3, 4, 6, 4], [4, 7, 3, 2]);
function removeDuplicates( array_1, array_2 ) {
array_1.forEach(function(value, index) {
var in_array = inArray( value, array_2 );
if ( in_array !== false ) {
array_1.splice( index, 1 );
array_2.splice( in_array, 1 );
}
});
console.log(array_1); // [4, 6]
console.log(array_2); // [7, 2]
}
// from jQuery
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return i;
}
return false;
}
jsFiddle: http://jsfiddle.net/tj6crcdt/
Upvotes: 2
Reputation: 152
After doing quite a bit of more research I found a way of doing it.
var arr1 = [5,2,3,7,8];
var arr2 = [3,5,2,3];
var extraVals = _.intersection(arr1,arr2);
var arr1Simp = _.difference(arr1, extraVals);
var arr2Simp = _.difference(arr1, extraVals);
Or as a function
var likeTerms = function(num, down){
var extraVals = _.intersection(num,down);
var numSimp = _.difference(num, extraVals);
var downSimp = _.difference(down, extraVals);
if(numSimp.length==0){
numSimp.push(1);
}
if(downSimp.length==0){
downSimp.push(1);
}
return {
num: numSimp,
down: downSimp
};
};
Upvotes: 0