function symmetricDifference(A, B) {
function relative_complement(A, B) {
return A.filter(function(elem) {
return B.indexOf(elem) == -1
});
}
function unique(ary) {
var u = ary.concat().sort();
for (var i = 1; i < u.length;) {
if (u[i - 1] === u[i])
u.splice(i, 1);
else
i++;
}
return u;
}
return unique(relative_complement(A, B).concat(relative_complement(B, A))).sort();
}
Iām not sure how to contribute to this, so I hope this is the right place. Symmetric difference turned out to be the hardest problem for me so far (went from very bruteforce to a respectable degree of cleverness).
Anyway, I think my solution is perhaps more readable as an Intermediate solution (Iām not confident enough to call it better, it may be less performant)ā¦ would you be so kind to have a look?
function sym() {
// get the arguments in a proper Array
var args = Array.prototype.slice.call(arguments);
// call reduce on the arguments using the diff function, and return the end-result
return args.reduce(diff);
}
// returns the unique elements in the union of the arrays
function diff(arrX, arrY){
// clean up both arrays, so we don't have duplicates in a set/array
arrX = sortAndClean(arrX);
arrY = sortAndClean(arrY);
// concatenate both arrays and sort
// then cleverly filter out elements that show up more than once (common elements)
// leaving us with the unique elements in the union
var result = arrX.concat(arrY).sort(function(a,b){
return a - b;
}).filter(function(x, i, arr){
return arr.indexOf(x) === arr.lastIndexOf(x);
});
return result;
}
// sortAndClean simply ends up giving us the unique elements in the Array
// i.e. it sorts and de-duplicates
function sortAndClean(arr){
arr = arr.sort(function(a,b){
return a - b;
}).filter(function(x, i, arr){
return x !== arr[i+1];
});
return arr;
}
//Test it
sym([1, 2, 5], [2, 3, 5], [3, 4, 5]);
I am confused when there are multiple values in a single set. Based on all the descriptions of Symmetric
Difference, the operation is a SET LEVEL comparison, not a comparison of ELEMENTS within a SET.
Thus I think the test is wrongā¦
For example is says this test ā "sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]) should return [1, 4, 5]."
I think it should actually return [1,1,2,4,5]
Specifically they first set contains four elements 1, 1, 2 & 5. Although the number 1 is duplicated, for Symmetric Difference you are comparing ALL ELEMENTS in the first set with all elements in sets two and three. Since neither sets two or three contain a number one, all ones are valid. Furthermore if set two had only a single 1, then it would eliminate 1 of the number ones but not both.
Now if you said, āUNIQUE SET ELEMENTSā then Iād agree that the answer would be [1,4,5]
ā¦two definitions of sets which differ only in that one of the definitions lists set members multiple times, define, in fact, the same set. Hence, the set {11, 6, 6} is exactly identical to the set {11, 6}. The second important point is that the order in which the elements of a set are listed is irrelevant (unlike for a sequence or tuple). We can illustrate these two important points with an example:
{6, 11} = {11, 6} = {11, 6, 6, 11} .
Javascript is consistent with this, e.g., new Set([11, 6, 6, 11]) results in creation of a set object {11, 6}
function sym() {
// Convert arguments into an array and eliminate duplicate elements
// within each argument.
return [...arguments].map(arg => [...new Set(arg)])
// concatenate successive arguments a and b
.reduce((a,b) => a.concat(b)
// elements that are in both a and b will appear twice, filter
// these out to get the Symmetric Difference
.filter((el, i, arr) =>
!(arr.indexOf(el) < i || arr.indexOf(el, i + 1) > -1)))
.sort((a,b) => a - b );
}
Thanks. I still recall from SAT and past problems describing a SET or (BAG) of ā12 BLUE and 6 RED MARBLESā and a SET of ā12 RED MARBLES and 6 BLUE MARBLESā with the Intersection being ā6 RED and 6 BLUEā
It seems there is a distinction (that is not clear in the problem description) that they are talking about a pure mathematical description of a setā¦for example mathematicians would describe the set of WHOLE NUMBERS, and as such there are no duplicates WHOLE NUMBERS., the number ONE is the number ONE no matter how many times is listed. But if Iām talking about the SET of THINGS (like COLORED MARBLES) if I have FIVE BLUE MARBLES, I do in fact have FIVE different things.
Hi, this problem wasnāt the most dificult to me, the āSmallest Common Multiple Completeā problem freaked me out, so Iāll put here my solution, but I donāt think that is better, just a little diferent from the others soluctions shown here:
function sym(args) {
var auxArguments = Array.from(arguments);
var auxArr = [];
for(var i = 1 ; i < auxArguments.length; i ++){
auxArr = auxArguments[i-1].filter(function (value, index){
return auxArguments[i].indexOf(value) === -1 && auxArguments[i - 1].indexOf(value, index + 1) === -1;
}).concat(auxArguments[i].filter(function(value1, index1){
return auxArguments[i - 1].indexOf(value1) === -1 && auxArguments[i].indexOf(value1, index1 + 1) === -1;
}));
auxArguments[i] = auxArr;
}
return auxArr;
}
Hereās what I came up with. it was hard, ,but not the hardest for me to solve. I agree with others, it threw me for a loop that repeats of the same value were not allowed.
function diffArray(arr1,arr2) {
console.log("starting to diff", arr1,arr2);
var unique1=[];
var unique2=[];
var kindOfUnique;
unique1=arr2.filter(function(val) {
return arr1.indexOf(val) === -1;
});
console.log("unique1=", unique1);
unique2=arr1.filter(function(val) {
return arr2.indexOf(val) === -1;
});
console.log("unique2=", unique2);
kindOfUnique=unique1.concat(unique2);
var noDup = kindOfUnique.filter (function (value, index, array) {
//console.log("value=", value, "index=", index);
// console.log(array);
return array.indexOf (value) == index;
});
console.log(noDup);
return noDup;
}
function sym(arg) {
var combined= Array.prototype.slice.call(arguments);
//console.log(combined);
//console.log(combined.reduce(diffArray,[]));
return combined.reduce(diffArray,[]);
}
sym([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]);
This problem is limited to diffing two arrays. It appears an earlier incarnation of the test allowed an arbitrary number of argument arrays.
For the given test input (both in the main challenge set and the new beta, which appear identical for this problem), the second filter is not necessary. But try diffArray([1, 1, 2], [2, 3 ]) to see why itās needed.
Here my solution too. Slightly different than the other solutions here.
function sym(args) {
var difference = [];
var unique = [];
for (var i=0; i<arguments.length; i++) {
/* Make each element in the individual array unique */
unique = arguments[i].filter(function(item, j, ar){ return ar.indexOf(item) === j; });
/* Compare each element for being in the difference-aray */
for (var y=0; y<unique.length; y++) {
pos = difference.indexOf(unique[y]);
if (pos == -1) {
difference.push(unique[y]);
}
else {
difference.splice(pos, 1);
}
}