I am trying to get my hand dirty with Javascript
I want to solve the following exercise (found on Codewars):
Given an array of integers, find the one that appears an odd number of times.
There will always be only one integer that appears an odd number of times.
[7] should return 7, because it occurs 1 time (which is odd). [0] should return 0, because it occurs 1 time (which is odd). [1,1,2] should return 2, because it occurs 1 time (which is odd). [0,1,0,1,0] should return 0, because it occurs 3 times (which is odd). [1,2,2,3,3,3,4,3,3,3,2,2,1] should return 4, because it appears 1 time (which is odd).
this is my code:
function findOdd(A) {
const isOdd = (x) => {
return x%2;
}
const counts ={};
for ( i of A)
{
counts[i]= counts[i] ? counts[i] 1:1;
}
const numOccurences = (Object.values(counts));
const occurences = Object.getOwnPropertyNames(counts);
let evenOccurence=0;
let oddOccurence;
for (let y=0;y<numOccurences.length;y )
{
if(isOdd(numOccurences[y]))
{
console.log("numOccurences[y] is equal to: ",numOccurences[y])
evenOccurence = numOccurences[y];
console.log(`value ${occurences[y]} is appearing ${numOccurences} times which is even`)
}
// }
// console.log("evenOccurence",evenOccurence);
// return evenOccurence;
}
return evenOccurence;
}
// console.log(findOdd([7]));
console.log(findOdd([7,7,8,8,7,5,5,5,5,5,5,5]));
my issue is the value I am putting in evenOccurrence, I would expect an integer, but it comes as 7,3,2 in the array given as an example.
could anyone help me please?
Thanks in advance
CodePudding user response:
You could take a bitwise XOR ^
which wipes out even count values.
const
odd = array => array.reduce((a, b) => a ^ b, 0);
console.log(odd([1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1]));
console.log(odd([7]));
console.log(odd([1, 1, 2]));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Another approach. With an object for keeping the state. The value is either true
or false
depending on the odd appearance of the value of the array.
Finally take all keys and find the one with the true
value.
const
odd = array => {
const states = {};
for (const value of array) states[value] = !states[value];
return Object.keys(states).find(k => states[k]);
};
console.log(odd([1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1]));
console.log(odd([7]));
console.log(odd([1, 1, 2]));
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Updated your answer with comment.
function findOdd(A) {
const isOdd = (x) => {
return x % 2;
}
const counts = {}; // key with will be unique set of A and value will be part will be occurence count
for (i of A) {
counts[i] = counts[i] ? counts[i] 1 : 1;
}
// const numOccurences = (Object.values(counts)); // her you are just getting list of how many time they occured, without any reference to A or their keys
// const occurences = Object.getOwnPropertyNames(counts);
let evenOccurence = []; // if you want to return a list, create a list and push values in it
for (let key of Object.keys(counts)) { // key is unique value of A
let occurenceCount = counts[key];
if (isOdd(occurenceCount)) {
console.log("numOccurences of key [", key,"] is equal to: ", occurenceCount, ' odd')
} else {
console.log("numOccurences of key [", key,"] is equal to: ", occurenceCount, ' event')
evenOccurence.push(key); }
}
return evenOccurence;
}
console.log(findOdd([7, 7, 8, 8, 7, 5, 5, 5, 5, 5, 5, 5]));
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
@Nina Scholz's first algorithm is a masterpiece. Basically it is very simple if you are ok with bitwise operations. I just would like to simplify the same thing down to daily math.
var odd = array => array.sort().reduce((a,b,i) => i%2 ? a-b : a b);
console.log(odd([1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1]));
console.log(odd([7]));
console.log(odd([1, 1, 2]));
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>