# Determine if all decimal digits are unique

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.

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

# Julia, 25 bytes

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

# Perl 6 (19 bytes)

{.comb.uniq==.comb}

0b

Try it online!

# 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?

# 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

q{

Try it online!

# Japt v2.0a0, 53 2 bytes

Takes input as a string.

¶â

Try it

# 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.

• 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. Jun 30, 2022 at 18:06
• @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. Jun 30, 2022 at 19:20
• Ahhhhh sorry I missed that. That is next level voodoo for sure! Jun 30, 2022 at 20:00

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!

# 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.

A(.).*\1
^.

Try it online!

<?=!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. # 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

# Arturo, 2726 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. # 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 # Julia 1.0, 23 18 bytes ~x=allunique("$x")

Try it online!

-5 bytes thanks to MarcMush: replace digits(x) with "$x" • -5 bytes: allunique("$x") Feb 24, 2023 at 12:45

# Excel, 47 bytes

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

Input in cell A1.

• 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 =)
– JvdV
Mar 1, 2023 at 13:47
• @JvdV Excellent construction! Mar 1, 2023 at 13:55

# 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
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: