dev.to staff

Posted on

# Daily Challenge #35 - Find the Outlier

In this challenge, you'll be given an array with a length of at least three, containing (possibly quite large) integers. The array is either comprised of entirely odd integers or even integers with one exception. Write a method that returns the integer that is not like the others.

Example:
`findOutlier([2, 4, 0, 100, 4, 11, 2602, 36])` => `11`

[160, 3, 1719, 19, 11, 13, -21]
[4, 8, 15, 16, 24, 42]
[16, 6, 40, 66, 68, 28]

Good luck, happy coding~!

This challenge comes from user obnounce. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Sung M. Kim • Edited

JavaScript 😀

Not efficient, as it's iterating the array twice (I could've used `reduce` to iterate once but well... this looks more readable)

BTW, the last one looks weird, as it contains only even numbers.

``````const isEven = n => n % 2 === 0
const isOdd = n => n % 2 === 1
const findOutlier = arr => {
const odds = arr.filter(isOdd)
const evens = arr.filter(isEven)
return odds.length < evens.length ? odds[0] : evens[0]
}
[
[2, 4, 0, 100, 4, 11, 2602, 36],
[160, 3, 1719, 19, 11, 13, -21],
[4, 8, 15, 16, 24, 42],
[16, 6, 40, 66, 68, 28]
].map(findOutlier)
``````

Hao • Edited

There's a potential bug.

`-21` will fail both `isOdd` and `isEven` function.

The function `isOdd` should be

``````const isOdd = n => n % 2 !== 0
``````

Since negative odd numbers mod 2 equals to `-1` instead of `1`.

Sung M. Kim • Edited

Whoa.... you've just caught years worth of bugs I have possibly created... 😅

Thank you @Hao for finding the issue. 😀
I really didn't think that thru. 👍

Here is the updated code

``````let isEven = n => n % 2 === 0
let isOdd = n => n % 2 !== 0
const findOutlier = arr => {
const odds = arr.filter(isOdd)
const evens = arr.filter(isEven)
return odds.length < evens.length ? odds[0] : evens[0]
}
[
[2, 4, 0, 100, 4, 11, 2602, 36],
[160, 3, 1719, 19, 11, 13, -21],
[4, 8, 15, 16, 24, 42],
[16, 6, 40, 66, 68, 28],
[-21, 1, 2, 3]
].map(findOutlier)
``````

I think I would probably use `!isEven` next time 😎

Vincent Thibault

You only need to fetch the firsts 3 items to know what you are searching for.

``````function findOutlier (list: number[]): number | void {
const search = list.slice(0,3).filter(v => v % 2).length > 1 ? 0 : 1;
return list.find(v => v % 2 === search);
}
``````

Dane Hillard • Edited

This goes through the list of numbers only a single time, stopping early if possible. Could probably be code golfed further 😛

``````def find_outlier(nums):
odds = evens = 0
for num in nums:
is_even = num % 2 == 0
is_odd = not is_even

odds += 1 if is_odd else 0
evens += 1 if is_even else 0

# Two of one kind prove the other kind is the outlier
if (odds > 1 and is_even) or (evens > 1 and is_odd):
return num
``````

I have done a Ruby one, based on counting the number of even values in the first three elements of the array to switch the logic between finding the first even and the first odd element.

``````[
[2, 4, 0, 100, 4, 11, 2602, 36],
[160, 3, 1719, 19, 11, 13, -21],
[4, 8, 15, 16, 24, 42],
[16, 6, 40, 66, 68, 28]
].map do |array|
case array.first(3).select(&:even?).size
when 1
array.find(&:even?)
else
array.find(&:odd?)
end
end

=> [11, 160, 15, nil]
``````

Palash Bauri 👻

Atleast it works somehow 😅

``````given = [2, 4, 0, 100, 4, 11, 2602, 36] #input array
odds = evens = 0

if given[0]%2 == 0:
evens  += 1
else:
odds += 1

if given[1]%2 == 0:
evens  += 1
else:
odds += 1

if given[-1]%2 == 0:
evens  += 1
else:
odds += 1

if odds > evens:
for i in given:
if i%2==0:
print(i)

else:
for i in given:
if not i%2==0:
print(i)

``````

Jerome Cukier • Edited

in JavaScript. o(n), uses constant space.

in the worst case (outlier is at the end of the loop) it will go through all items. but if the outlier is found before, the loop stops.

``````function findOutlier(nums) {
let lastOddOrEven = [null, null];
for (let i = 0; i < nums.length; i++) {
const parity = nums[i] % 2;
if (lastOddOrEven[0] !== null && lastOddOrEven[1] !== null) {
// we've already seen one odd and one even number,
// so the outlier is the one number we've seen with a
// different parity
return lastOddOrEven[1 - parity];
}
lastOddOrEven[parity] = nums[i];
}
// if the loop can't return the outlier, this is because it's the last item
return nums[nums.length - 1];
}
``````

Ruby solution, I tried to do something different.

``````def findOutlier numbers
sum = numbers.sum
if sum.odd?
numbers.find(&:odd?)
else
numbers.find(&:even?)
end
end

puts findOutlier([2, 4, 0, 100, 4, 11, 2602, 36])
puts findOutlier([160, 3, 1719, 19, 11, 13, -21])
puts findOutlier([4, 8, 15, 16, 24, 42])
puts findOutlier([16, 6, 40, 66, 68, 28])
puts findOutlier([5, 9, 4, 155, 7])
``````

When the list has no exception, the first element is returned; except when `numbers` looks like `[3,3]` (bug that you can fix by adding `.uniq` when computing the sum.)

Dane Hillard

I believe this would fail if the outlier is even and the rest are an odd number of odd numbers. The examples all have an even number of odd numbers. Can you check that?

Tanguy Andreani

It seems that I can’t make it right and as simple as it was. So I’ll stick with this solution:

``````def findOutlier numbers
if numbers.first(3).count(&:even?) > 1
numbers.find(&:odd?)
else
numbers.find(&:even?)
end
end

puts findOutlier([2, 4, 0, 100, 4, 11, 2602, 36])
puts findOutlier([160, 3, 1719, 19, 11, 13, -21, 33])
puts findOutlier([160, 3, 1719, 19, 11, 13, -21])
puts findOutlier([4, 8, 15, 16, 24, 42])
puts findOutlier([16, 6, 40, 66, 68, 28])
puts findOutlier([3,3])
``````

willsmart • Edited

A javascript one that has pretty reasonable complexity

``````function findOutlier(integers){
// The first three ints can be used to determine whether we are
// looking for an odd or an even
// If at least two are even, then we're looking for the odd integer
const typicalIntegerIsEven = isEven(integers[0]) + isEven(integers[1]) + isEven(integers[2]) >= 2
// Return the first integer that is non-typical
return integers.find(v => isEven(v) != typicalIntegerIsEven)

// Helper function to determine if a number is even or odd
// Note that (-1)%2 === -1 and some integers might be negative.
// (-2)%2 === -0 and -0 === 0, so this check will work for any integer.
// v&1 is better in many ways, but only goes up to 32 bit ints
function isEven(v) {return v%2 === 0}
}
``````

Oleksii Filonenko

Elixir:

``````defmodule Outlier do
require Integer

def find(list) do
if list
|> Enum.take(3)
|> Enum.filter(&Integer.is_even/1)
|> Enum.count() == 1,
do: Enum.find(list, &Integer.is_even/1),
else: Enum.find(list, &Integer.is_odd/1)
end
end
``````

Mat-R-Such

Python

``````def find_outlier(integers):
a= sum(map(int,[integers[0]%2,integers[1]%2,integers[2]%2]))
if a == 0 or a== 1:
for i in integers:
if i % 2 == 1:   return i
else:
for i in integers:
if i % 2 == 0:   return i
``````

official_dulin

Go:

``````func FindOutlier(integers []int) int {
var m = map[string][]int{
"odd": []int{},
"even": []int{},
}
for _, i := range integers {
if i % 2 == 0 {
m["even"] = append(m["even"], i)
} else {
m["odd"] = append(m["odd"], i)
}
}
if len(m["even"]) == 1 {
return m["even"][0]
}
return m["odd"][0]
}
``````

peter279k

Here is the simple solution with PHP:

``````function find(\$integers) {
\$evenArray = [];
\$oddArray = [];

foreach (\$integers as \$integer) {
if (\$integer % 2 === 0) {
\$evenArray[] = \$integer;
} else {
\$oddArray[] = \$integer;
}
}

if (count(\$evenArray) === 1) {
return \$evenArray[0];
}

return \$oddArray[0];
}
``````

With JS

``````function findOutlier(arr){
let checker = {even:[],odd:[]}
arr.forEach((item) => item%2==0 ? checker['even'].push(item) : checker['odd'].push(item));
return checker['even'].length < checker['odd'].length ? checker['even'][0] : checker['odd'][0];
}

findOutlier([2, 4, 0, 100, 4, 11, 2602, 36])

``````

Explanation:

1. Using an object which stores `even` and `odd` numbers.
2. just returning the one with less number.

Ayogu Blossom Israel

array = [500,502,1002,1234,601]
odd = even = i = 0
oddValue = evenValue = 0
a = len(array)
while (i < a):
if (array[i] % 2):
oddValue = array[i]
odd += 1
else:
evenValue = array[i]
even += 1
i += 1
if (odd > even == 1):
print(evenValue)
elif (odd == 1):
print(oddValue)
else:
print("Wrong list of numbers")

Alexander Garcia

Not elegant, but it'll do the job.

``````const findOutlier = (arr) => {
const firstPass = arr.filter(el => el % 2 === 0)
const secondPass = arr.filter(el => el % 2 !== 0)

if(firstPass.length === 1) {
return firstPass[0]
}
return secondPass[0]
}
``````