34
\$\begingroup\$

Surprisingly we haven't had a simple "find the highest digit" challenge yet, but I think that's a little too trivial.

Given input of a non-negative integer, return the highest unique (ie not repeated) digit found in the integer. If there are no unique digits, your program can do anything (undefined behaviour).

The input can be taken as a single integer, a string, or a list of digits.

Test cases

12         -> 2
0          -> 0
485902     -> 9
495902     -> 5
999999     -> Anything
999099     -> 0
1948710498 -> 7

This is so fewest bytes in each language wins!

\$\endgroup\$
  • 2
    \$\begingroup\$ Can we take input as a string instead? \$\endgroup\$ – user41805 Jun 28 '17 at 8:13
  • 3
    \$\begingroup\$ Given the last test case, I think we are forced to take input as a string... (leading zeroes can't be represented in integers) \$\endgroup\$ – Leo Jun 28 '17 at 8:14
  • \$\begingroup\$ @Leo that was my bad actually, basically mashed the numbers on my keyboard, didn't notice the leading zero. But yes, input can be taken as a string \$\endgroup\$ – Skidsdev Jun 28 '17 at 8:17
  • 26
    \$\begingroup\$ @Adám "undefined behaviour" generally means you can do anything, including summoning nameless horrors from the void if that saves bytes. \$\endgroup\$ – Martin Ender Jun 28 '17 at 8:22
  • 22
    \$\begingroup\$ @MartinEnder in fact I'll happily knock off 50% of your bytes if your code successfully summons cthulhu upon there being no unique digits ;) \$\endgroup\$ – Skidsdev Jun 28 '17 at 8:31

63 Answers 63

1
\$\begingroup\$

Perl 5, 59 bytes

for$x(split//,<>){$d[$x]++};for($x=11;--$d[--$x];){}print$x

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Shortened to 40 bytes: Try it online!. (you can look up -F flag on perlrun if needed) \$\endgroup\$ – Dada Jul 27 '17 at 11:51
1
\$\begingroup\$

Pyth, 8 7 6 bytes

1 byte thanks to isaacg.

1 byte thanks to FryAmTheEggman.

e{I#.g

Test suite.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Octave, 31 bytes

@(a)find(hist(a,0:9)==1)(end)-1

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Python 2, 41 bytes

lambda s:max(s,key=lambda o:s.count(o)<2)

Accepts input as string or list of strings

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Pyth -- 8 bytes

eSf!t/QT

And also

eS-Q.-Q{

Try it here and here

Explanation:

eSf!t/QT  # Takes string
  f       # Filter characters T of implicit input
     /QT  # by counting occurrences of that character in the input
   !t     # keeping only characters that occur once (i.e., !(# occurrences - 1)
 S        # Sort (puts them in ascending order
e         # Take the last (highest)

And

eS-Q.-Q{  # Takes list of digits
       {  # Deduplicate the list
    .-Q   # Take the original list, and remove each element in the deduplicated list once (so only duplicated digits are left)
  -Q      # Remove these duplicated digits from the list
eS        # As before, sort and take the last element
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Perl 6,  33  25 bytes

{max keys .comb∖.comb.repeated}

input is either an Int or Str.

Test it

{max keys $_∖.repeated}

input is a list of digits.

Test it

Expanded:

{ # bare block lambda with implicit parameter 「$_」

  max                  # the maximum from
    keys               # the keys (digits) out of the following Set

        $_             # the Input list of digits
      ∖                # Set minus (not 「\」)
        .repeated      # the repeated digits (implicit method call on 「$_」)
}
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog), 11 bytes

⌈/{⍺×2-≢⍵}⌸

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Java, 70 bytes

Input is taken as a List of digits, as per question parameters.

n->n.stream().reduce(0,(p,q)->p>q||n.indexOf(q)!=n.lastIndexOf(q)?p:q)

The power of Streams in the palm of your hand!

The secret here is the beautiful reduce function. Starting with a 0, we walk through our list of digits and perform a retaining algorithm, keeping the one we've got (?p:q) if it's bigger than the new one (p>q) or if the new one isn't unique (n.indexOf(q)!=n.lastIndexOf(q))

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ You can save a byte by changing || to |. \$\endgroup\$ – Kevin Cruijssen Nov 13 '17 at 15:23
1
\$\begingroup\$

CJam, 13 bytes

9A,sqfe=W%X#-

Try it Online

9    e# Push 9 to stack
A,s  e# Push "0123456789" to stack
q    e# Push input to stack ("1948710498")
fe=  e# Create array containing number of occurences of each digit in input number ([1,2,0,0,2,0,0,1,2,2])
W%   e# Reverse that array ([2,2,1,0,0,2,0,0,2,1])
X#   e# Get index of 1 in that array (2)
-    e# Calculate 9 - returned index to get highest unique digit (7)
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

C# (Visual C# Interactive Compiler), 38 bytes

n=>n.Max(x=>n.Count(a=>a==x)<2?x:0)-48

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

J, 16 12 bytes

0{\:~-.}./.~

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ This is really nice, and since "The input can be taken as a single integer, a string, or a list of digits." you can actually do 0{\:~-.}./.~ for 12: Try it online! \$\endgroup\$ – Jonah Jun 2 '19 at 1:29
  • 1
    \$\begingroup\$ @Jonah thank you! \$\endgroup\$ – FrownyFrog Jun 2 '19 at 20:40
1
\$\begingroup\$

Wolfram Language (Mathematica), 43 29 28 bytes

Max@*Cases[{d_,1}->d]@*Tally

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Removed 14 bytes by skipping IntegerDigits: according to the comments, the function can be given a list of digits instead of a number. \$\endgroup\$ – Roman Jun 5 '19 at 10:27
  • \$\begingroup\$ Removed 1 byte by using the operator form of Cases. \$\endgroup\$ – Roman Jun 8 '19 at 12:34
1
\$\begingroup\$

Husk, 8 bytes

▲fȯ¬←LgO

Try it online!

Input is list of digits.

▲fȯ¬←LgO
▲           # maximum value of
 f          # filter list to retain only truthy values
      gO    # list: sort digits and group equal values together
  ȯ         # filter condition: combine functions:
    ←L      # length minus one (so length 1 = FALSE)
   ¬        # NOT (so length 1 = TRUE)
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ 5 bytes I think \$\endgroup\$ – Razetime Nov 5 at 3:55
  • \$\begingroup\$ 3 bytes but this one's very different \$\endgroup\$ – Razetime Nov 5 at 3:57
  • \$\begingroup\$ @Razetime - That's much, much, better than mine! Post it! \$\endgroup\$ – Dominic van Essen Nov 5 at 7:09
0
\$\begingroup\$

Clojure, 52 bytes

#(last(sort(for[c % :when(=((frequencies %)c)1)]c)))

Input is a string, returns a char, or nil if all digits are repeated.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Actually, 16 bytes

╗1╤rR⌠$╜c⌡M1@í9-

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

C (gcc), 76 bytes

d[58],i;main(){while((i=getchar())>0)++d[i];for(i=58;--d[--i];);putchar(i);}

Try it online!

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Suggest d[58];main(i) instead of d[58],i;main(). Also, suggest (~(i=getchar())) instead of ((i=getchar())>0) \$\endgroup\$ – ceilingcat Aug 21 '18 at 1:02
0
\$\begingroup\$

PHP, 79 76 bytes

Try it online!

foreach(array_count_values(str_split($n))as$x=>$i){$h=($i==1&&$x>$h)?$x:$h;}

Use with $n = 495902; it will print 5.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

PowerShell v3+, 58 bytes

$i|% ToCharA*|sort|group|? count -lt 2|select -l 1 -exp N*

Assumes $i contains a string of digits.

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

F#, 67 bytes

let f s=Seq.countBy id s|>Seq.filter(snd>>(=)1)|>Seq.maxBy fst|>fst

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Kotlin, 53 Bytes

val f={a:String->a.filter{a.count{b->it==b}<2}.max()}

Declares a lambda, f that takes in a string; same algorithm as the python answer. it is the implicit iterator of a.filter, and b is the explicitly declared iterator of a.count (because we can't use it again).

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Pip, 11 bytes

MX:_Na=1FIa

Takes input as a command-line argument. Try it online!

Explanation

          a  1st cmdline arg
        FI   Filter digits by this function:
   _Na        Count of digit in a
      =1      equals 1 (i.e. keep only digits that appear exactly once)
MX:          Max of resulting list (using : to lower precedence)
             Autoprint (implicit)
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

CJam, 15 bytes

r$e`{0=1=},e~W=

Explanation:

r    e# Read token:          "2515"
$    e# Sort:                "1255"
e`   e# Run-length encode:   [[1 '1] [1 '2] [2 '5]]
{    e# Filter where:
 0=  e#   The first element: [1 1 2]
 1=  e#   Equals one:        [1 1 0]
},   e# End filter:          [[1 '1] [1 '2]]
e~   e# Run-length decode:   "12"
W=   e# Last digit:          '2
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

jq, 47 characters

(43 characters code + 4 characters command line options)

[./""|group_by(.)[]|select(length<2)[]]|max

Sample run:

bash-4.4$ jq -Rr '[./""|group_by(.)[]|select(length<2)[]]|max' <<< 1948710498
7

bash-4.4$ jq -Rr '[./""|group_by(.)[]|select(length<2)[]]|max' <<< 999999
null

Try on jq‣play

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Braingolf, 15 bytes

k&gG{!L1-?$_|}X

Try it online!

Takes input as a list of digits

Explanation

k&gG{!L1-?$_|}X  Implicit input from commandline args
k                Sort in descending numerical order
 &g              Combine into single integer
   G             Split into digit runs
    {........}   Foreach loop..
     !L1-?       ..If length of item is greater than 1..
          $_     ....Remove item
            |    ..Endif
              X  Select highest value
                 Implicit output

To help visualize it a little, here's a run through showing the stack with input 122355567679

k&gG{!L1-?$_|}X  [1,2,2,3,5,5,5,6,7,6,7,9]
k                [9,7,7,6,6,5,5,5,3,2,2,1]
 &g              [977665553221]
   G             [9,77,66,555,3,22,1]
    {!L1-?$_|}   [9,3,1]
              X  [9]
| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Ruby, 42 bytes

Same byte count as the other Ruby answer, but different approach.

->x{x.chars.group_by{|d|x.count d}[1].max}

Crashes when there are no unique digits.

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

x86 Machine Code (32-bit, requires built-in FPU), 35 bytes

C8 10 00 00 D9 EE DD 14 24 DD 5C 24 08 8B 01 FE 04 04
83 C1 04 4A 75 F5 6A 0A 58 48 FE 0C 04 75 FA C9 C3

The above code defines a function in 32-bit x86 machine code that finds the unique highest digit in an array of integer values. (The question says we can take the input as a "list of digits", and assembly language is like C in that it lacks a built-in list/array type, but rather represents them as a pointer and length. Therefore, the function is prototyped in C as follows:

int __fastcall FindHighestUniqueDigit(const int * ptrDigits, int count);

As the prototype suggests, this function is written to follow Microsoft's fastcall calling convention, which passes arguments in registers. The first parameter (ptrDigits) is passed in ECX, and the second argument (count) is passed in EDX. The return value is, as always, returned in EAX.

Try it online!

Here are the ungolfed assembly mnemonics:

FindHighestUniqueDigit:
   enter  16, 0                  ; reserve 16 bytes of space on the stack for a table
   fldz                          ; load 0 in the first x87 FPU register (st0)
   fst    QWORD PTR [esp+0]      ; store value in st0 on the stack, at offset 0
   fstp   QWORD PTR [esp+8]      ; store value in st0 on the stack, at offset 0, and pop st0
ReadDigits:
   mov    eax, DWORD PTR [ecx]   ; read next digit from array
   add    ecx, 4                 ; increment pointer to reference next digit (ints are 4-bytes long)
   inc    BYTE PTR [esp + eax]   ; increment value in table for this digit
   dec    edx                    ; decrement counter (length of array)
   jne    ReadDigits             ; keep looping as long as there are more digits to read
   push   10
   pop    eax                    ; space-efficient way to put '10' in EAX so we start with highest digit
ProcessDigits:
   dec    eax                    ; decrement EAX
   dec    BYTE PTR [esp + eax]   ; decrement value in table for this digit
   jnz    ProcessDigits          ; if that table value is now zero, we found a match; otherwise, keep looping
   leave                         ; undo effects of ENTER instruction
   ret                           ; return, with result in EAX (digit ID)

I suppose the code requires a bit of explanation…

Basically, what we do is create a table in memory, with enough space to store a unique count for each of the 9 possible digits (0 through 9).

| esp+0 | esp+1 | esp+2 | esp+3 | esp+4 | esp+5 | esp+6 | esp+7 | esp+8 | esp+9 | unused |
|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|--------|
|   9   |   8   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |   ??   |

The first ENTER instruction is responsible for allocating this space on the stack. We allocate 16 bytes because it's good practice to keep this a power of 2 for alignment purposes, 8 bytes isn't enough, and it doesn't hurt or cost anymore code bytes to allocate more than we need. The next three instructions are responsible for zeroing out all entries in this array. It's basically equivalent to memset in C, but shorter. We could have used the x86's REP STOSD string instruction, but that requires some setup (getting the right values in the right registers), and it turned out that (ab)using the x87 FPU to do 8-byte stores was shorter (required fewer bytes of code). All we do is load 0 at the top of the x87 FPU stack, which is pseudo-register st0. Then, we store that value across the first 8 bytes of the table, and finally, we store that value across the next 8 bytes of the table, popping it off of the x87 FPU stack at the same time.

The next section of the code is ReadDigits. This just iterates through the array of digits that we were passed, one digit at a time, and increments the unique counter for that digit in our table. You should be able to figure out exactly how this works by reading the comments for each of the instructions.

Finally, we come to the final phase, ProcessDigits. Actually, the PUSH+POP instructions right above this label are conceptually part of this phase, too. They just initialize EAX with 10 so that we'll start processing the table values for the highest possible digit, 9. Inside of the ProcessDigits loop, we eagerly decrement EAX, and then decrement the value in the table for the corresponding digit. If the resulting table value/counter is 0, then we've found our match, and we exit the loop. Otherwise, we keep looping and trying smaller digits. (Note that we could have done a comparison here—e.g., cmp BYTE PTR [esp + eax], 1+jnz—and in fact that's what we're logically doing, but the decrement was shorter to encode.)

Notice that if we never find a matching digit, then the code exhibits undefined behavior: it just keeps looping through memory, decrementing values and waiting until one is non-zero. When it finally finds one, it will terminate and return the ID, but the ID will be meaningless, and more importantly, it will have stomped all over the stack, decrementing values aimlessly!

The very last two instructions just clean up the stack (LEAVE) and return, with the return value (the highest unique digit that we found) left in EAX.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

k, 12 bytes

|/@&:1=#:'=:

Example:

k)F:|/@&:1=#:'=:
k)F "1948710498"
"7"
k)F "99999"
"\000"
k)F "mississippi"
"m"

The translation to q as explanation

max where 1 = count each group@

Interpreter available here

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I think this can be simplified to |/&1=#:'=: (provided it's run as k4 code). \$\endgroup\$ – coltim Nov 4 at 21:40
0
\$\begingroup\$

J, 19 bytes

[:>./(".*1=#)/.~@":

Explanation:

": converts the number to a string
@ propagates the result (composes the verbs)
/.~ classifies items of the list into partitions of identical items
". * 1=# - fork of 3 verbs:
   1=# - 1 if the key is unique, else 0
   ". converts the keys back to digits
   * multiplies the key values by 1 or 0 depending on their uniqueness
>./ finds the max digit
[: caps the fork, since we have 2 verbs only for the key operator

Example:

   a=.123456547
     ": a
    123456547  NB. string
    </.~@": a
    ┌─┬─┬─┬──┬──┬─┬─┐
    │1│2│3│44│55│6│7│          NB. keys
    └─┴─┴─┴──┴──┴─┴─┘

(1=#)/.~@": a
1 1 1 0 0 1 1                  NB. mask for unique digits

(".*1=#)/.~@": a
1 2 3 0 0 6 7                  NB. digits multiplied by the mask, rendering
                                   duplicates to 0

([:>./(".*1=#)/.~@":) a        NB. finds the max nonrepeating digit
7

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -pF, 36 bytes

$_=join'',sort@F;s/(.)\1+//g;$_=chop

Try it online!

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Stax, 4 bytes

|!|M

Run and debug it

This program takes an array of digits. It works by calculating the maximum "anti-mode". I'm not sure if anti-mode is a real thing outside of stax, but it refers to the rarest element in list.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.