# Odd'em out: letters

## Objective

Write a program or function (or equivalent) that sorts out and returns the odd letter in the matrix of random size.

## Details

You will be passed a matrix (as a string) as input of random dimensions such as this.

bbbbbbbbbb
bbbbbdbbbb
bbbbbbbbbb
bbbbbbbbbb
bbbbbbbbbb

Your job is to find the letter that doesn't match the rest (in this case, it is d, found at line 2, col 6) and to return that letter as output. The matrix will consist of letters A-Z, a-z, newlines (\n, only on ends of rows) and have dimensions ranging from 5x5 to 10x10 (25-100 letters).

Standard loopholes apply. This is a code golf challenge; entry with code of least bytes wins.

## Input

Input will be passed in through standard input as a string if it is a program or as an argument if a function (or similar).

## Output

A single character that is the "odd" in the matrix or None, nil, NUL, or the string "None" if there is no "odd" character.

AAAAAAA
AAAAAAA
AAAAAAA
AAAIAAA
AAAAAAA

vvqvvvvvvv
vvvvvvvvvv
vvvvvvvvvv
vvvvvvvvvv
vvvvvvvvvv

puuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu
uuuuuuuuu

## Generator

Here is a random matrix generator written in Python that you can use to test your program. Note: There is a slight chance that it could make a mistake and not put in an odd letter.

Instructions

1. Copy this code into a file called matrix_gen.py.
2. Run it with python matrix_gen.py.

---

from random import randint

rows = randint(5,10)
cols = randint(5,10)

charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
neg = charset[randint(0,51)]
pos = charset[randint(0,51)]
p_used = 0

comp = 0
matrix = ""

while comp < rows:
row = ""
while len(row) < cols:
if not p_used and not randint(0,10):
p_used = 1
row = row + pos
else:
row = row + neg
row = row + "\n"
matrix = matrix + row
comp += 1

print matrix[:-1]

• Here is a literal translation of your Python code into JS. Nov 28, 2017 at 10:09
• @juniorRubyist "removing the bonus" isn't the same as "making the bonus mandatory". By moving the part that was optional so far into the requirements of the challenge, you've invalidated a large part of the existing answers. Nov 30, 2017 at 8:50
• Just let people output whatever if there's no character. Aug 13, 2023 at 12:51

# Python 3, 27 bytes

lambda x:min(x,key=x.count)

Try it online!

# J, 12 10 7 bytes

-.}./.~

Try it online!

/.~        Group identical items together
}.           Remove one item from each group
-.             Remove the rest from the input

### 10 byte version

-._1 1{\:~

hisss...

\:~        Sort down
_1 1{           Take the last character (which is a newline) and the second one.
-.                Remove those from the input
• @ FrownyFrog This is a clever way to find the odd character Nov 28, 2017 at 8:25
• can’t decide what i like better: this lovely hook or your dragon joke... Nov 28, 2017 at 13:46

# Brachylog, 8 4 bytes

oḅ∋≠

Try it online!

## Explanation

I haven't used Brachylog before, so this may not be optimal.

oḅ∋≠  Input is a string.
o     Sort the input.
ḅ    Split it into blocks of equal elements.
∋   There is a block
≠  whose elements are all different.
That block is the output.
• That use of ∋≠ after to get the results of length 1 is very clever. You should definitely post it in the Brachylog tips question. Nov 30, 2017 at 7:28
• @Fatalize Thanks, I added the tip. Nov 30, 2017 at 8:28

# 05AB1E,  4  2 bytes

Saved 2 bytes thanks to Adnan

.m

Try it online!

Explanation

.m   # push a list of the least frequent character(s) in input
• Do you need to remove the newlines, seeing as we're guaranteed the input will be at least 5 lines long? Nov 28, 2017 at 8:19
• @Shaggy: No I don't. That was to handle 2x2 matrices. I missed the part about 5x5 and up. Thanks! Nov 28, 2017 at 8:44
• It has to return nil if it doesn't have an "odd one out" doesn't it? Nov 30, 2017 at 0:49
• @MagicOctopusUrn That part was optional when this answer was posted. I guess that change invalidates most answers now... Nov 30, 2017 at 8:49

# K (oK), 7 6 bytes

Solution

*<#:'=

Try it online!

Example:

*<#:'="vvqvvvvvvv\nvvvvvvvvvv\nvvvvvvvvvv\nvvvvvvvvvv\nvvvvvvvvvv"
"q"

Explanation:

Found a slightly shorter approach: Evaluated right-to-left:

*<#:'= / the solution
= / group matching items together
#:'  / count (#:) each (')
<     / sort ascending
*      / take the first one

Notes:

Whilst I'm expecting the bonus aspect of this challenge to get dropped, this solution will return the newline character \n if there is no odd character:

*<#:'="vvvvvvvvvv\nvvvvvvvvvv\nvvvvvvvvvv\nvvvvvvvvvv\nvvvvvvvvvv"
"\n"

# Prolog (SWI), 46 bytes

p(L):-select(X,L,Y),\+member(X,Y),writef([X]).

Try it online!

Or if the standard true output from prolog queries is not okay:

# Prolog (SWI), 48 bytes

Z*L:-select(X,L,Y),\+member(X,Y),char_code(Z,X).

Try it online!

Explanation

Find the first element X in the input
that when removed, results in output
that does not contain X

then depending on the version above either:
print X as a character
or
return X as an atom

# C (gcc), 93929066 62 Bytes

Much shorter as a function

t;f(char*p){for(t=*p;*p;)t^*p++?putchar(*p^*--p?*p:t),*p=0:0;}

Try it online!

test code

main()
{
char s[99];
for(;gets(s);)f(s);
}

old version is a program

# C 86 Bytes

char*p;s[9];main(t){for(;p=gets(s);)for(t=*p;*p;)t^*p++?putchar(*p^*--p?*p:t),*p=0:0;}

Outputs the odd character, or nothing. run like this;

C:\eng\golf>python matrix_gen.py | a.exe
X
C:\eng\golf>python matrix_gen.py | a.exe
G
C:\eng\golf>python matrix_gen.py | a.exe
x
C:\eng\golf>python matrix_gen.py | a.exe

C:\eng\golf>python matrix_gen.py | a.exe
J
• I don't know that it is quite fair to put the gets() into the test driver as it is sanitizing the input by removing the \n chars for you. That's doing some work so that your function is not working on the original input. Nov 29, 2017 at 23:10
• @MichaelDorgan It works with the piped input from the python script as well as input on TIO. Others simply hard-coded the input which didn't seem with the spirit of the challenge. Nov 30, 2017 at 13:45
• Suggest *p=!putchar(*p^*--p?*p:t) instead of putchar(*p^*--p?*p:t),*p=0 Aug 5, 2020 at 23:24

## Retina, 13 bytes

s(O.
(.)\1+

Try it online!

### Explanation

s(O.

Sort all characters.

(.)\1+

Remove any characters that appear at least twice.

# Husk, 2 bytes

◄=

Try it online!

This is a function taking a string as input and returning a character. It takes the minimum of the input string when comparing characters for equality (i.e. it returns the character that is equal to the least number of other characters).

# C, 94 bytes

Return by pointer. If none, return \0.

This will cause memory leaks. Assuming int is 4 bytes.

*t;f(c,p,i)char*c,*p;{t=calloc(64,8);for(*p=-1;*c;c++)t[*c]--;for(i=0;++i<128;)!~t[i]?*p=i:0;}

Try it online!

• Nov 28, 2017 at 8:21
• @Shaggy Actually, I don't know how to interpret that rule, as I see some (other) users explicitly know about that rule but still post such answers like this one. Nov 28, 2017 at 9:44
• @user202729, just because others do it doesn't mean it's right ;) If you spot such solutions, best to point it out to them. Nov 28, 2017 at 9:46
• @Shaggy Well, I explicitly pointed the rule but that user said "the rule explicitly says that this one is valid". I don't know what to say. | In this case the function require the array t be zeroed before calling each time not the first time. Nov 28, 2017 at 9:50
• @Shaggy Thanks, fixed. Nov 28, 2017 at 11:05

# Mathematica, 27 bytes

Last@*Keys@*CharacterCounts

Try it online!

-1 byte from Martin Ender

# Bash, 15 20 bytes

fold -1|sort|uniq -u

Try it online!

Explanation: folds the input to 1 character per line, sorts it into groups of matching letters, then prints only lines that are unique.

Thanks @Nahuel Fouilleul for catching and helping fix a problem with this approach.

• doesn't work if the odd character is the second or the penuitlimate Nov 29, 2017 at 14:45
• @NahuelFouilleul Good catch... I'm unsure of how to fix that at the moment, but I will fix or delete later unless you had a suggested fix. Nov 29, 2017 at 14:50
• it can be simply fix with |sort| but there may be a better solution Nov 29, 2017 at 15:38
• also found a solution with grep but it's longer grep -oP '^(.)((?=(?!\1).){2}|.*\K(?!\1).)' Nov 29, 2017 at 16:17
• @NahuelFouilleul I'm going with the sort fix, thanks. You could always post that grep answer as your own if you want to, though. Nov 29, 2017 at 19:56

# Pyth, 4 bytes

ho/Q

Try it here!

• .m/Q is 4 bytes as well
– Dave
Nov 30, 2017 at 12:56
• @Dave That outputs as a list though, I chose this because it was more elegant ;-) Nov 30, 2017 at 12:57

# Perl 5, 17 + 3 (-00p) -25% = 15 bytes

/(.)\1/;s/
|$1//g try it online # Matlab, 25 Bytes a=input('');a(a~=mode(a)) The input "a" where "a" isn't the mode of "a". Outputs empty array for no oddball. # Java 8, 85 bytes This is a lambda from String to String (e.g. Function<String, String>). It's essentially a copy of Luca's solution, but I've pared down the string sorting a bit. s->new String(s.chars().sorted().toArray(),0,s.length()).replaceAll("(.)\\1+|\\n","") Try It Online ## Haskell, 33 * 0.75 = 24.75 bytes f s=[c|[c]<-(filters).(==)<$>s]

Returns an empty list if there's no odd character.

Try it online!

For each char c in the matrix (given as a string s) make a string of all chars in s that are equal to c and keep those of length 1.

# JavaScript (ES6), 37 bytes

Returns null if there's no odd letter.

s=>s.match([^
${s.match(/(.)\1/)}]) ### Test cases let f = s=>s.match([^${s.match(/(.)\1/)}])

console.log(f(
'bbbbbbbbbb\n' +
'bbbbbdbbbb\n' +
'bbbbbbbbbb\n' +
'bbbbbbbbbb\n' +
'bbbbbbbbbb'
))

console.log(f(
'AAAAAAA\n' +
'AAAAAAA\n' +
'AAAAAAA\n' +
'AAAIAAA\n' +
'AAAAAAA'
))

console.log(f(
'vvqvvvvvvv\n' +
'vvvvvvvvvv\n' +
'vvvvvvvvvv\n' +
'vvvvvvvvvv\n' +
'vvvvvvvvvv'
))

console.log(f(
'puuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu\n' +
'uuuuuuuuu'
))

console.log(f(
'AAAAA\n' +
'AAAAA\n' +
'AAAAA\n' +
'AAAAA\n' +
'AAAAA'
))

# Common Lisp, 47 bytes

(lambda(s)(find-if(lambda(x)(=(count x s)1))s))

Try it online!

Returns the odd letter or NIL if it does not exist.

# Jelly, 4 bytes

ċ@ÐṂ

Try it online!

Return \n (a single newline) in case there is no odd character. Obviously \n is not a printable character.

Coincidentally this is exactly the same algorithm as Mr.Xcoder Python answer. (I came up with it independently)

Explanation:

ÐṂ    Ṃinimum value by...
ċ@      ċount. (the @ switch the left and right arguments of ċ)

That works because in a m×n matrix:

• If there exists odd character: There are m-1 newlines, 1 odd characters and m×n-1 normal character, and 1 < m-1 < m×n-1 because 5 ≤ m, n ≤ 10.
• If there doesn't exist odd character: There are m-1 newlines and m×n normal character, and m-1 < m×n.

# C# (.NET Core), 54 bytes

i=>i.GroupBy(x=>x).FirstOrDefault(g=>g.Count()<2)?.Key

Try it online!

• You are right, my answer was wrong. I have deleted it. But you are missing the 18 bytes from the using statement in the byte count. Nov 29, 2017 at 13:03

# C (gcc), 91868279 71 bytes

f(char*s){for(;*++s==10?s+=2:0,*s;)if(*s^s[-1])return*s^s[1]?*s:s[-1];}

Try it online!

• Thanks to Gastropner for the xor and ? tricks (-3 bytes)
• Reworked the compare version to fix bugs and used Gastropner magic from comments.

Explanation:

Compare current and previous char while skipping newlines. If different, compare to next char. This tells us if we return current or previous char. The function returns the "odd" char value if it exists or 0 if the array is not odd. We get away with the "next" char check because there is always a newline before the \0 char. If there is no odd char, we intrinsically return the \0 from the for loop.

Older, sexier xor code Explanation:

Make a running xor mask of the next 3 string values. If they are all the same, then the value will be equal to any of the three. If they are different, then the 2 identical will cancel each other out leaving the unique.

Must factor /n before the xor or it gets messy. Also have to check 2 chars for inequality in case s[0] is the odd value. This costs the extra || check.

v;f(char*s){while(s[3]){s[2]==10?s+=3:0;v=*s^s[1]^s[2];if(v^‌​*s++||v^*s)break;}}
• 79 with a few tweaks. The fall-through return does not agree with my compiler, so only tested on TIO: v;f(char*s){while(s[3]){s[2]==10?s+=3:0;v=*s^s[1]^s[2];if(v^*s++||v^*s)break;}} Nov 29, 2017 at 22:12
• For the crap I am writing, TIO is what I stick with. Thanks! Nov 29, 2017 at 22:59
• Rearranging some expressions allows another -2 for 77: v;f(char*s){while(s[2]==10?s+=3:0,v=*s^s[1]^s[2],s[3])if(v^*s++||v^*s)break;} However your winning horse is the other one, if you fiddle with it a bit, for 73: v;f(char*s){for(v=-1;*++s==10?s+=2,v--:0,*s;v=0)if(*s^s[-1])return s[v];} Nov 29, 2017 at 23:36
• Yeah, but the xor seems so sexy. :) Nov 29, 2017 at 23:39
• Suggest s+=*++s-10?0:2 instead of *++s==10?s+=2:0 Aug 2, 2019 at 20:33

# Octave, 26 25 bytes

1 byte saved thanks to @Giuseppe

@(x)x(sum(x(:)==x(:)')<2)

Anonymous function that takes a 2D char array as input, and outputs either the odd letter or an empty string if it doesn't exist.

Try it online!

|!

Run and debug it

# Japt-h, 6 4 bytes

ü l1

Try it

ü l1     :Implicit input of multiline string
ü        :Group & sort
l1     :Filter elements of length 1
:Implicit output of last element

# Alice, 16 * 75% = 12 bytes

/-.nDo&
\i..*N@/

Try it online!

Outputs Jabberwocky if there is no duplicate character.

### Explanation

/...@
\.../

This is a framework for linear programs that operate entirely in Ordinal (string processing mode). The actual code is executed in a zigzag manner and unfolds to:

i..DN&-o

..  Make two copies.
D   Deduplicate one copy, giving only the two letters and a linefeed.
N   Multiset difference. Removes one copy of each letter and one linefeed.
Therefore it drops the unique letter.
&-  Fold substring removal over this new string. This essentially removes
all copies of the repeated letter and all linefeeds from the input,
leaving only the unique letter.
.   Duplicate.
n   Logical NOT. Turns empty strings into "Jabberwocky" and everything else
into an empty string.
*   Concatenate to the previous result.
o   Print the unique letter or "Jabberwocky".

Instead of &-, we could also use ey (transliteration to an empty string). Alternatively, by spending one more character on stack manipulation, we could also deduplicate the input which lets us remove the unwanted characters with N, but it's still the same byte count:

i.D.QXN.n*o@

## Alice, 13 bytes

/N.-D@
\i&.o/

Try it online!

This is the solution without the bonus, it's simply missing the .n*.

# Retina, 22 bytes

!`(.)(?!.*\1)(?<!\1.+)

Try it online! Only requires height and width of at least 3, rather than 5.

# APL+WIN, 16 bytes

(1=+/a∘.=a)/a←,⎕

Prompts for screen input and either outputs odd letter or nothing if there is no odd letter

• a/⍨1=+/a∘.=a←,⎕ for a byte Nov 28, 2017 at 15:16
• @Uriel Thanks but I am afraid the operator ⍨ is not available in my old APL+WIN version 5 :( Nov 28, 2017 at 15:35

# PowerShell, 39 bytes

([char[]]"$args"|group|sort c*)[0].Name Try it online! Takes input as a string with newlines (as specified in the challenge), converts it to a char-array. We then Group-Object the characters, so that characters are grouped together by their names, then sort based on the count. This ensures that the lonely character is first, so we take the [0] index and output its .Name. If newline is acceptable for "nothing" then this qualifies for the bonus. • I was hoping sort c*)[0] could be shortened, but what I came up with was the same number of bytes, ? c* -eq 1). – root Nov 28, 2017 at 21:03 • can be shortened by removing the double quotes around$args. Also it is more accurate to do ([char[]]$args|group|? c* -eq 1).Name as it will accurately return null when there is no odd character (instead of new line). However in terms of bytes this still won't bring you below 37. Nov 29, 2017 at 10:15 • @cogumel0 Doesn't run without double quotes. – root Nov 29, 2017 at 13:11 • @root you're correct. However to pass one of the requirements (A single character that is the "odd" in the matrix or None, nil, NUL, or the string "None" if there is no "odd" character.) it should still be changed. Newline is not part of the acceptable answers. Nov 29, 2017 at 14:12 • @cogumel0 Ah, the challenge was changed since I posted my answer. The "None / nil / whatever" used to just be a bonus rather than mandatory. I'm going to keep my answer as-is. Nov 29, 2017 at 14:16 # Perl 6, 27 24 -25% = 18 bytes *.comb.Bag.min(*.value).key Test it {%(.comb.Bag.invert){1}} Test it This will return an undefined value when given an input that doesn't have an odd character out. ## Expanded: { # bare block lambda with implicit parameter ｢$_｣

%(        # coerce into a Hash

.comb   # split the input into graphemes (implicit method call on ｢\$_｣)
.Bag    # turn into a weighted Set
.invert # invert that (swap keys for values) returns a sequence

){ 1 }    # get the character that only occurs once
}