47
\$\begingroup\$

Deleted questions on Stack Overflow sometimes make for great golf material.

Write a function that takes a nonnegative integer as input, and returns true if all the digits in the base 10 representation of that number are unique. Example:

48778584 -> false
17308459 -> true

Character count includes only the function.

If you choose to answer in C or C++: no macros, no undefined behaviour; implementation-defined behaviour and compiler warnings are fine.

\$\endgroup\$
2
  • \$\begingroup\$ I'd still be interested in other C or C++ solutions as per the question that inspired this one. \$\endgroup\$
    – Thomas
    May 21, 2014 at 19:59
  • 11
    \$\begingroup\$ Why no C or C++ macros or undefined behavior? That's oddly limiting to just two languages. \$\endgroup\$
    – dfeuer
    Apr 14, 2019 at 2:05

92 Answers 92

2
\$\begingroup\$

Julia, 25 bytes

the best I could come up with was the same as one of the top voted answers

n->10^length(Set("$n"))>n

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Vyxal , 3 bytes

U∑=

Try it Online!

\$\endgroup\$
2
\$\begingroup\$

Vyxal, 2 bytes

Þu

Try it Online!

\$\endgroup\$
1
\$\begingroup\$

Javascript 73 chars

function f(n){return !~(n+'').split('').sort().join('').search(/(\d)\1/)}
\$\endgroup\$
1
\$\begingroup\$

Befunge 98, 17 bytes

This is a non-competing answer because Befunge does not have functions.

~:1g1`j@1\[email protected]

Prints a 1 if the number's digits are all unique; otherwise, it just ends.

This works by accessing a cell in the Funge space whose x coordinate is the ASCII value of the character inputted (takes input character by character) and whose y coordinate is 1. If the digit has not been seen before, the value of the cell is 32 (space character). If that is so, I set the value to 1.

As a bonus, this works for non-numbers as well.

\$\endgroup\$
1
\$\begingroup\$

PowerShell - 26

!($args|sls '(.)(?=.*\1)')
\$\endgroup\$
1
\$\begingroup\$

Perl 6 (19 bytes)

{.comb.uniq==.comb}

.comb splits a string into characters (for example, 42.comb gives "4", "2"). .uniq removes all non-unique characters. .comb characters in string (originally I used .chars, but .comb is shorter). == converts lists into number of elements in it, and compares the numbers. When . is used without object before, $_ which is default function parameter is assumed. {} are function literals.

\$\endgroup\$
1
\$\begingroup\$

C, 76

This is no where near winning, but I'll post it anyway just to show an alternative approach.

c;i;a[99];main(){while(~(c=getchar()))a[c]++;for(;i<99;)a[i++]>1&&puts("");}

Prints a new line if false, prints nothing if true.

\$\endgroup\$
3
  • \$\begingroup\$ This program has an undefined behavior. The correct signatures for main are int main(int, char **) or int main(void). int main(int) is not valid. \$\endgroup\$
    – 0..
    May 22, 2014 at 13:11
  • \$\begingroup\$ @xfix I assume main() is ok then? \$\endgroup\$
    – user12205
    May 22, 2014 at 13:22
  • \$\begingroup\$ Yes, it's fine. It means the same thing as main(void) (when used in definition, in declaration it declares a function with unknown parameter list). \$\endgroup\$
    – 0..
    May 22, 2014 at 13:22
1
\$\begingroup\$

k4 (8)

  {x=.?$x}48778584
0b
  {x=.?$x}17308459
1b

inspired by a combination of the J and Golfscript answers

\$\endgroup\$
1
\$\begingroup\$

Python 2.7 114 106 bytes

First golf, and this is no way going to win :P

def d(a):
    f=[];
    for i in str(a):
        if i in f:return False
        f.append(i)
    return True

Kinda want to see how other people would improve this :)

EDIT: With ProgramFOX's comments:

def d(a):
    f=[];
    for i in str(a):
        if i in f:return 1<0
        f+=[i];
    return 0<1
\$\endgroup\$
3
  • \$\begingroup\$ return True can be shortened to something like 0<1. And f.append(i) can be shortened to f+=[i]. \$\endgroup\$
    – ProgramFOX
    Dec 21, 2014 at 15:40
  • \$\begingroup\$ You're welcome! Also, you can save one more character by dropping the ; after f+=[i]. It is not necessary there. \$\endgroup\$
    – ProgramFOX
    Dec 21, 2014 at 19:03
  • \$\begingroup\$ Ugh... Too much php :) \$\endgroup\$
    – JamJar00
    Dec 21, 2014 at 19:04
1
\$\begingroup\$

Python, 40

f=lambda x:len(str(x))==len(set(str(x)))

The built-in set removes the duplicates, so if the length of a thing and the length of his set are equal, the thing does not have repeated elements.

\$\endgroup\$
1
\$\begingroup\$

Burlesque, 2 bytes

Using the Unique built-in:

blsq ) 17308459U_
1
blsq ) 48778584U_
0
\$\endgroup\$
1
\$\begingroup\$

Go, 138 bytes

Bad language choice.

run it like uniqchars 112345678

package main
import(."fmt"
."os"
."strings")
func main(){s:=Args[1]
f:=true
for _,e:=range s{if Count(s,string(e))>1{f=false}}
Println(f)}
\$\endgroup\$
1
  • 4
    \$\begingroup\$ This is post 65536 on the site! That's 2^16. \$\endgroup\$
    – wizzwizz4
    Jan 11, 2016 at 21:11
1
\$\begingroup\$

PARI/GP, 26 bytes

n->d=digits(n);#d==#Set(d)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python 3, 29 bytes

lambda x:10**len({*str(x)})>x

Inspired on this answer in Python 2; for Python 3 to only lag behind 2 by one byte is pretty rare :)

\$\endgroup\$
1
\$\begingroup\$

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

i=>(i+"").ToDictionary(c=>c)

Try it online!

This lambda uses presence or absence of an exception to determine whether a number has unique digits. If a digit occurs more than once, a duplicate key exception will be thrown when converting the string to a dictionary.

\$\endgroup\$
1
\$\begingroup\$

Braingolf, 12 bytes

dlMulMve1:0|

Try it online!

Explanation

dlMulMve1:0|  Implicit input from args

d             Split into digits
 lM           Push length of stack to next stack
   u          Keep only first occurrence of each unique digit
    lM        Push length of stack to next stack
      v       Switch to next stack
       e      If top 2 items are equal
        1      - Push 1
         :    Else
          0    - Push 0
           |  EndIf

              Implicit output of top of stack
\$\endgroup\$
1
\$\begingroup\$

Perl 6, 12 bytes

{!/(.).*$0/}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Jelly, 3 bytes

DQƑ

Try it online!

How it works

DQƑ - Main link. Takes n on the left
D   - Convert to digits
  Ƒ - Is it unchanged under:
 Q  -   Deduplication?
\$\endgroup\$
1
\$\begingroup\$

Husk, 4 bytes

S=ud

Try it online!

S           # Hook: S fgx means f x(gx)
 =          # are they equal:
            # x (implied by S)
            # and
  u         # unique elements of x
   d        # when x is the decimal digits of the input
\$\endgroup\$
1
\$\begingroup\$

Pyth, 2 bytes

q{

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Japt v2.0a0, 5 3 2 bytes

Takes input as a string.

¶â

Try it

\$\endgroup\$
1
\$\begingroup\$

Regex (ECMAScript / Perl / PCRE / Python / .NET), 66 61 bytes

^(?!((?=(x{10})*(x*))(^|(?=(x*)(\5{9}x*))\6)+){2}\B\2*\3$)|^$

Takes its input in unary, as the length of a string of xs.

Try it online! - ECMAScript
Try it online! - Perl
Try it online! - PCRE
Try it online! - Python
Try it online! - .NET

This regex apparently does not work in Java, Boost, or Ruby. The reasons are unknown as of yet.

^                          # tail = N = input number
(?!                        # Assert that there is no way for the below to match
    (
        (?=
            (x{10})*(x*)   # \2 = 10; \3 = tail % 10
        )
        (
            ^              # Allow the loop to iterate once without doing
                           # anything iff this is the first iteration of the
                           # main loop.
        |
            (?=
                (x*)       # \5 = floor(tail / 10)
                (\5{9}x*)  # \6 = tool to make tail = \5
            )\6            # tail = \5
        )+                 # Execute the above loop an arbitrary positive
                           # number of times.
    ){2}                   # Execute the above loop exactly twice, so that \3
                           # will contain the value it had at the beginning of
                           # the loop's second iteration.

    \B                     # Assert that we aren't at the beginning or end, or
                           # that N==0; the latter "or" part is undesirable,
                           # because it prevents this main algorithm from being
                           # able to match N==0, but even still, using "(?!^|$)"
                           # would be longer than "\B" and "|^$" combined.
    # Note that if (x{10})* repeated zero times, \2 will be a non-participating
    # capture group (unset). In ECMAScript this means it will behave as if \2=0.
    # In all other flavors, it means \2* will only be able to repeat zero times,
    # because \2 alone won't match anything. But this doesn't matter, since if
    # it was only able to match zero times before, it wouldn't be able to match
    # more than zero times now, anyway.
    \2*\3$                 # Assert tail % 10 != \3
)
|^$                        # Match N==0, which the main algorithm above can't.

See also my decimal regex answer. I feel that this unary version is more interesting, especially since unary is like a native integer data format for regex, whereas decimal is like passing an integer as a string, but it's definitely worth presenting decimal versions as well.

\$\endgroup\$
3
  • \$\begingroup\$ Wouldn't something naive like ^(?!0.*0|...|9.*9) be shorter? Haven't thought hard about this and obviously you have, so probably I'm missing something. \$\endgroup\$
    – Thomas
    Jun 30, 2022 at 18:06
  • \$\begingroup\$ @Thomas You're thinking of a regex that takes its input in decimal format. My regex takes it in unary, which is like a native integer format for regex. I have, however, now made a separate post taking decimal input. \$\endgroup\$
    – Deadcode
    Jun 30, 2022 at 19:20
  • 1
    \$\begingroup\$ Ahhhhh sorry I missed that. That is next level voodoo for sure! \$\endgroup\$
    – Thomas
    Jun 30, 2022 at 20:00
1
\$\begingroup\$

See also my unary regex answer. Although other posts have already used a regex that take decimal input, this post provides a unified presentation, and outgolfs some of the previous posts (including a language in which there wasn't previously any regex post).

Regex (ECMAScript or better), 13 bytes

^(?!(.)+.*\1)

Takes its input in decimal. Returns a match for numbers with all-unique digits.

Try it online!

Regex (ECMAScript or better), 7 bytes

(.).*\1

Takes its input in decimal. Returns a non-match for numbers with all-unique digits.

Try it online!

\$\large\textit{Anonymous functions}\$

R v3.5.2, 29 bytes

pryr::f(!grepl('(.).*\\1',n))

Try it online!

Uses the same regex as MickyT's R answer, but ,,T is unnecessary (the regex doesn't need to run in PCRE mode) and omitting it saves 3 bytes. Using pryr's lambda syntax saves another 2 bytes.

R v4.1.0+, 24 bytes

\(n)!grepl('(.).*\\1',n)

Attempt This Online!

PHP, 35 bytes

fn($n)=>!preg_match('/(.).*\1/',$n)

Try it online!

Java, 33 bytes

n->!(n+"").matches("(.)+.*\\1.*")

Try it online!

This uses a regex 1 byte shorter than barteks2x's answer.

Perl, 19 bytes

sub{pop!~/(.).*\1/}

Try it online!

Ruby, 23 bytes

->n{n.to_s !~/(.).*\1/}

Takes an integer as input. Returns a native boolean, true if the digits are unique.

Try it online!

Ruby, 18 bytes

->s{s !~/(.).*\1/}

Takes a string as input. Returns a native boolean, true if the digits are unique.

This is identical to John Feminella's 20 byte answer except for removing the unnecessary parentheses surrounding the function parameter, saving 2 bytes.

\$\large\textit{Full programs}\$

Retina, 12 bytes

A`(.).*\1
^.

Try it online!

PHP, 37 bytes

<?=!preg_match('/(.).*\1/',$argv[1]);

Try it online!

Perl, 16 bytes

say<>!~/(.).*\1/

Try it online!

This uses a regex 1 byte shorter than Tal's answer. Another 2 bytes are saved by using say (requiring Perl v5.010+) instead of print.

\$\endgroup\$
1
\$\begingroup\$

K (ngn/k), 13 bytes

{(#t)=#?t:$x}

Try it online!

I think there's a way this one could be a train...

Explanation:

{(#t)=#?t:$x}  Main function. x is input
          $x   Convert x to string
        t:     Assign it to variable t
       ?       Unique
      #        Length
     =         Equal to
 (#t)          The length of t
\$\endgroup\$
1
\$\begingroup\$

Arturo, 27 26 21 bytes

$=>[=unique<=digits&]

Try it

-1 byte from abusing Arturo's hidden stack features. >:)

-5 bytes from using a tacit function and using the dup operator over the function.

Checks whether the list of digits of the input number is equal to itself when uniquified.

\$\endgroup\$
1
\$\begingroup\$

Thunno, \$ 6 \log_{256}(96) \approx \$ 4.94 bytes

dDZUA=

Attempt This Online!

Explanation

dDZUA=  # Implicit input
dD      # Cast to digits and duplicate
  ZU    # Uniquify this list
    A=  # Are they equal?
        # Implicit output
\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, 23 18 bytes

~x=allunique("$x")

Try it online!

-5 bytes thanks to MarcMush: replace digits(x) with "$x"

\$\endgroup\$
1
  • 1
    \$\begingroup\$ -5 bytes: allunique("$x") \$\endgroup\$
    – MarcMush
    Feb 24, 2023 at 12:45
1
\$\begingroup\$

Excel, 47 bytes

=LET(a,ROW(1:10)-1,COUNT(SEARCH(a&"*"&a,A1))=0)

Input in cell A1.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This could be 43 bytes using =ROWS(UNIQUE(MID(A1,ROW(A:A),1)))=LEN(A1)+1 perhaps. Unless the input is 1048576 characters long =) \$\endgroup\$
    – JvdV
    Mar 1, 2023 at 13:47
  • \$\begingroup\$ @JvdV Excellent construction! \$\endgroup\$ Mar 1, 2023 at 13:55
1
\$\begingroup\$

x86-16 machine code, 11 bytes

FC 51 AC 8B FE F2 AE 59 E0 F7 C3

Listing:

    SEARCH:
FC      CLD                 ; string direction forward
51      PUSH CX             ; save loop counter 
AC      LODSB               ; load next digit from SI into AL, advance SI 
8B FE   MOV  DI, SI         ; DI is offset of next digit 
F2/ AE  REPNZ SCASB         ; search until match, ZF=1 if found 
59      POP  CX             ; restore loop counter 
E0 F7   LOOPNZ SEARCH       ; loop until match found or CX is 0
C3      RET                 ; return to caller
        ENDM

Callable function, input as digit array at DS:SI, length in CX. Output ZF=0 if unique, ZF=1 if not unique.

Test program in IBM PC DOS that reads input from command line args, displays T or F:

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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