17
\$\begingroup\$

Given two strings of digits, determine which string, if any, has the earliest digit which is lower than the other string's digit at the same index.

Do note that this differs from alphabetization, as shown in the following examples:

Examples

Given inputs 12345000 and 1233999999, the second string would have the earliest lower digit.

12345000
1233999999
^          same value
 ^         same value
  ^        same value
   ^       second is lower
    ^^^^^^ irrelevant

Given strings 99 and 998, neither has the earliest lowest digit, since 99 equals 99, and the 8 has no digit to compare against.

99
998
^   same value
 ^  same value
  ^ irrelevant

Additional specification

  • Input/output can be taken/given in any reasonable format.
  • You can output any three consistent values to represent choosing the first input, the second input, or neither. (similar to )
  • Alternatively, you may use the standard output method of three-way comparison of your language of choice (if one exists)
  • You may assume that there will be no leading 0s in input.
  • This is , so shortest code in bytes wins.

Test cases

Output is in the form < for first input, > for second input, and = for equal.

 999   999 =
 115   116 <
 116   115 >
 870   789 >
  33  3333 =
3333    33 =
  20  2100 <
  19  1200 >
2100    20 >
1200    19 <
1234  1234 =
4321  5432 <
5678  5432 >
  99   998 =
12345000  1233999999 >   
\$\endgroup\$
11
  • 1
    \$\begingroup\$ Can I output an integer while positive means input1 > input2, negative means input1 < input2, and zero means equal? It is a common way to express cmp in many languages. \$\endgroup\$
    – tsh
    Commented Sep 5, 2023 at 2:29
  • \$\begingroup\$ @tsh if that's reasonably common in your language, that sounds fine. I'll add a clause to the extra spec, good question. \$\endgroup\$ Commented Sep 5, 2023 at 2:41
  • 1
    \$\begingroup\$ In the test cases, the second input is the longer one. Can I assume this, or can the first input be longer? \$\endgroup\$
    – pajonk
    Commented Sep 5, 2023 at 8:20
  • 1
    \$\begingroup\$ @noodleman that seems like reasonable enough I/O yea. As for not accounting for equal input... I feel like its a bit too ingrained into the challenge to remove at this point, with 14 answers, and its one of the few things that keeps this from just being a builtin check :P. I'm open to further commentary on that though \$\endgroup\$ Commented Sep 6, 2023 at 0:39
  • 1
    \$\begingroup\$ 116,115 returns >? Why is that? \$\endgroup\$
    – Value Ink
    Commented Sep 6, 2023 at 0:57

27 Answers 27

9
\$\begingroup\$

Python 2, 28 bytes

lambda*l:cmp(*zip(*zip(*l)))

Try it online!

Uses zip's truncating the to the shorter list. Test harness from @SuperStormer. Python 2 is needed for cmp.

\$\endgroup\$
9
\$\begingroup\$

Husk, 5 bytes

±ḟIz-

Try it online!

Input as lists of digits, output as -1 (first wins), 0 (neither wins) or 1 second wins.
Would be 1-byte shorter to output negative, zero or positive, but Husk doesn't have a 3-way comparison operator so it seems this is ruled-out...

   z   # zip digits from each pair of inputs together
    -  # by subtraction,
 ḟ     # get the first element that is 
  I    # itself truthy (non-zero),
±      # output the sign of that (-1 or 1) or zero if it's empty
\$\endgroup\$
6
\$\begingroup\$

Factor, 17 bytes

[ zip unzip <=> ]

Try it online!

Outputs +lt+ for first input, +gt+ for second input, or +eq+ for neither.

  • zip unzip Truncate the longer input to the same length as the shorter one.
  • <=> Compare.
\$\endgroup\$
6
\$\begingroup\$

JavaScript (ES6), 34 bytes

Expects two arrays of characters as (a)(b). Returns -2, -1 or 0 for <, > or = respectively.

a=>b=>-a.some((c,i)=>d=c-b[i])^d<0

Try it online!

Or 31 bytes if we output negative / zero / positive:

a=>b=>a.some((c,i)=>d=c-b[i])*d

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ We all forgot the simplest solution \$\endgroup\$
    – l4m2
    Commented Sep 23, 2023 at 4:50
5
\$\begingroup\$

R, 44 bytes

\(x,n=nchar(x))sign(diff(x%/%10^(n-min(n))))

Attempt This Online!

\$\endgroup\$
4
\$\begingroup\$

Python 2, 37 bytes

lambda s,t:cmp(s[:len(t)],t[:len(s)])

Attempt This Online!

\$\endgroup\$
4
\$\begingroup\$

Nibbles, 4.5 bytes (9 nibbles)

`$/|!$_-*

Attempt This Online!

Input as lists of digits, output as 1 (first wins), 0 (neither wins) or -1 second wins. Would be 1-byte (2 nibbles) shorter to output negative, zero or positive.

`$/|!$_-*       # full program
`$/|!$_-*$$$    # with implicit args (I think*):
    !           # zip together
     $_         # arg1 & arg2
       -        # by subtraction,
   |            # filter the resulting list
        *$$     # by each element multiplied by itself
                # (zero and negatives are falsy in nibbles),
  /             # now fold over this list
           $    # returning the left-hand element each time
                # (so returning the first element),
`$              # and return the sign of this
                # (or zero if empty)

*I'm not quite sure why $$$ is chosen for implicit args (here for the documentation), but happily it is and it works here...

\$\endgroup\$
1
  • \$\begingroup\$ Nibbles! That's clever. \$\endgroup\$ Commented Sep 6, 2023 at 8:03
4
\$\begingroup\$

Charcoal, 24 bytes

≔✂θ⁰Lη¹θ≔✂η⁰Lθ¹ηI⁻›θη›ηθ

Try it online! Link is to verbose version of code. Explanation: Charcoal doesn't have any relevant builtins, so it struggles even to port @SuperStormer's Python 2 answer.

≔✂θ⁰Lη¹θ

Truncate the first string to the length of the second.

≔✂η⁰Lθ¹η

Truncate the second string of the length of the first.

I⁻›θη›ηθ

Compare the strings.

\$\endgroup\$
4
\$\begingroup\$

C (clang), 64 63 62 bytes

c;f(*a,*b){for(c=1;(*a&&*b)&c;c+=*a++>*b++)c-=*a<*b;return c;}

Try it online!

Saved a bytes thanks to ceilingcat!!!

Inputs the digits as two wide-character strings.
Returns \$0\$ for <, \$2\$ for >, or \$1\$ for =.

\$\endgroup\$
1
  • \$\begingroup\$ @ceilingcat Nice one - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Sep 6, 2023 at 9:22
4
\$\begingroup\$

Pip, 20 17 12 bytes

-5 bytes by Dlosc

Returns -1 for first element, 1 for second and nothing if equal.

SG@FI_-BMZab

Attempt This Online!

SG@FI_-BMZab­⁡​‎‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏⁠‎⁡⁠⁣⁣‏⁠‎⁡⁠⁣⁤‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏⁠‎⁡⁠⁢⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁣‏⁠‎⁡⁠⁤‏⁠‎⁡⁠⁢⁡‏‏​⁡⁠⁡‌­
        MZab  # ‎⁡For each pair of digits in a, b
     _-B      # ‎⁢Return difference of digits
SG            # ‎⁣Push sign of
  @FI         # ‎⁤First truthy element
💎
\$\endgroup\$
1
  • \$\begingroup\$ MapZip and lambda expressions are your friends here: 12 bytes \$\endgroup\$
    – DLosc
    Commented Sep 28, 2023 at 20:59
3
\$\begingroup\$

sed -E, 92 bytes

s/^(.*)(.).* \1(.).*/\2\30123456789/;s/^(.)(.).*\1.*\2.*/</;s/^(.)(.).*\2.*\1.*/>/;s/...*/=/

Assuming, that both numbers are in one line, space separated. Unfortunately, sed doesn't know how compare numbers, so we need to add the digit list and do some regexp backreferencing stuff. Option -E used for extended regular expressions to avoid twelve more bytes for escaping:

  • ^(.*)(.).* \1(.).*/\2\30123456789/ removes everything but the first differing digit and adds the ordered digits, so 42 43000 would turn into 230123456789
  • s/^(.)(.).*\1.*\2.*/</ turn the whole line into <, if the first digit appears in the digit list before the second one
  • s/^(.)(.).*\2.*\1.*/>/ does the opposite with >
  • s/...*/=/ cares for the rest (all legal lines that have not been replaced by < or > contain at least two characters (..* is one byte shorter than .{2,})
\$\endgroup\$
2
  • \$\begingroup\$ You don’t need to add the -E to your byte count, just add it to your header before the byte count \$\endgroup\$ Commented Sep 7, 2023 at 12:29
  • \$\begingroup\$ @noodleman Thank you. Corrected and explanation added. \$\endgroup\$
    – Philippos
    Commented Sep 7, 2023 at 13:21
3
\$\begingroup\$

Julia, 93 77 54 bytes

Port of @Dominic van Essen' R answer in Julia.

Saved 39 bytes thanks to the comment of @MarcMush


Golfed version. Try it online!

x->(n=ndigits.(x);sign(diff(@.x÷10^(n-min(n...)))[]))

Ungolfed version. Try it online!

f=function(x)
    n=length.(digits.(x));
    return Int(sign(first(diff(x.÷10 .^(n.-minimum(n))))))
end
\$\endgroup\$
2
  • \$\begingroup\$ Use an anonymous function or ! to save a bunch of bytes. tips for golfing in Julia \$\endgroup\$
    – MarcMush
    Commented Sep 23, 2023 at 14:35
  • \$\begingroup\$ Nice improvement, here is 54 bytes \$\endgroup\$
    – MarcMush
    Commented Sep 24, 2023 at 8:18
3
\$\begingroup\$

Pip, 9 bytes

$CM Z:aZb

Attempt This Online! Outputs -1 for <, 1 for >, and 0 for =.

Explanation

      aZb  ; Zip the input numbers together, giving a list of pairs of digits
    Z:     ; Transpose into a pair of (equal-length) lists of digits
$CM        ; Fold on numeric comparison

The CM operator, when given two lists of digits, does almost what we want, but not if the lists are of unequal lengths. (If the shorter list is a prefix of the longer list, the longer list is considered to be greater.) So we zip the numbers together to clip to the length of the shorter one, then zip back again and compare.

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

Excel, 70 bytes

=@IFERROR(SIGN(TOCOL(1/(MID(A1,ROW(1:99),1)-MID(B1,ROW(1:99),1)),2)),)

Inputs in cells A1 and B1.

Outputs 1 for first input, -1 for second input and 0 for equal.

Assumes maximum string length of 99 characters.

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

Retina 0.8.2, 56 bytes

^(.+)(.*¶)\1
$2
^(¶.*|.*¶)$

(.).*
$1$*
(1*)¶\1
-
1+-?
1

Try it online! Takes input on separate lines but link is to test suite that splits on spaces for convenience. Outputs -1 for the first input and 1 for the second input having the earliest lower digit. Explanation:

^(.+)(.*¶)\1
$2

Remove any matching leading digits.

^(¶.*|.*¶)$

If at least one string is empty, then the there is no earliest lower digit. The rest of the program has no effect now that the output is empty.

(.).*
$1$*

Convert the first remaining digit of each number to unary, discarding the rest.

(1*)¶\1
-

Subtract the two unary numbers.

1+-?
1

Take the sign.

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

Julia 1.0, 23 bytes

port of l4m2's answser

a+b=(a>"$b:")-(b>"$a:")

Try it online!

nice solution but longer, 28 bytes

the same as xnor's answer i swear i found it on my own

a+b=cmp(zip(zip(a,b)...)...)

Try it online!

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

JavaScript (Node.js), 21 bytes

f=a=>b=>[a>b+f,b>a+f]

Try it online!

<!-- Before IO tweak: -->

JavaScript (Node.js), 22 bytes

f=a=>b=>a>b+f|-(b>a+f)

Try it online!

Same length as a=>b=>a>b+{}|-(b>a+!0)

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

Haskell + hgl, 9 bytes

fo<<zW cp

Attempt This Online!

Outputs as a native comparison value.

This zips the lists together comparing their values pairwise, then folds the results to get the answer.

Reflection

This is rather short, however I have found myself desiring to zip and fold at once before, and so I might actually make a way to combine fo and zW.

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

Haskell, 49 bytes

 ((head.(++[EQ]).snd.span(EQ==)).).zipWith compare

Attempt This Online!

\$\endgroup\$
1
  • \$\begingroup\$ You would actually save bytes to do import Data.Foldable;(fold.).zipWith compare here. \$\endgroup\$
    – Wheat Wizard
    Commented Oct 1, 2023 at 1:53
1
\$\begingroup\$

Ruby, 32 bytes

->a,b{a[0,b.size]<=>b[0,a.size]}

Attempt This Online!

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

TypeScript's Type System, 128 bytes

type F<A>=A extends[[infer G,...infer N],[infer H extends 1[],...infer M]]?G extends[...H,...infer R]?R extends[]?F<[N,M]>:2:1:0

Try it at the TypeScript Playground!

Generic type F takes type A which is a tuple of two lists of unary digits. Output is 0 for equal, 1 for first is lower, 2 for second is lower.

Explanation

type F<A>=
  // match the first item (G or H) and rest (N or M) of each list in A
  A extends[[infer G,...infer N],[infer H extends 1[],...infer M]]
    ?G extends[...H, // if H fits in G,
      ...infer R]    //   let R be the difference.
      ?R extends[]   //   if R is empty,
        ?F<[N,M]>    //     recurse with N and M.
      :2             //   otherwise, 2 is smaller
    :1               // if H doesn't fit in G, 1 is smaller
  :0 // if neither has been chosen yet, they're equal
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 74 bitsv2, 9.25 bytes

Z~AEv¯fꜝh±

Returns -1 for first element, 1 for second and 0 for equal.

Try it Online!

Z~AEv¯fꜝh±
­⁡​‎‎⁡⁠⁡‏⁠‎⁡⁠⁢‏⁠‎⁡⁠⁣‏‏​⁡⁠⁡‌⁢​‎‎⁡⁠⁤‏‏​⁡⁠⁡‌⁣​‎‎⁡⁠⁢⁡‏⁠‎⁡⁠⁢⁢‏⁠‎⁡⁠⁢⁣‏‏​⁡⁠⁡‌⁤​‎‎⁡⁠⁢⁤‏⁠‎⁡⁠⁣⁡‏⁠‎⁡⁠⁣⁢‏‏​⁡⁠⁡‌­

Z~A         # ‎⁡Zip and filter out falsy elements (trim numbers)
   E        # ‎⁢Covert string input to integers
    v¯f     # ‎⁣Calculate differences and flatten
       ꜝh±  # ‎⁤Output sign of first truthy element
💎

Created with the help of Luminespire.

\$\endgroup\$
4
  • \$\begingroup\$ Vyxal, 70 bits2, 8.75 bytes: Z~AEv¯ꜝh± (vyncoded) \$\endgroup\$
    – lyxal
    Commented Sep 6, 2023 at 13:48
  • \$\begingroup\$ @lyxαl ah right forgot about string input + ~. I believe you do need to flatten it though. \$\endgroup\$
    – math scat
    Commented Sep 6, 2023 at 14:10
  • \$\begingroup\$ What's up with the diamond? I'm noob asking \$\endgroup\$ Commented Sep 7, 2023 at 16:34
  • 1
    \$\begingroup\$ @thejonymyster that's just a thing luminspire does :P \$\endgroup\$
    – math scat
    Commented Sep 7, 2023 at 16:52
1
\$\begingroup\$

BQN, 12 bytes

(⊑⍋-⍒)⌊○≠↑¨⋈

¯1:<, 0:, 1:>

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

Arturo, 43 bytes

$[a b]->compare take a size b take b size a

Try it!

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

05AB1E, 5 bytes

.S0Ûн

I/O as two lists of digits. Outputs -1 if the second is lower; 1 if the first is lower; and nothing if they're 'the same'.

Try it online or verify all test cases.

Explanation:

.S    # Compare the digits at the same positions in the two (implicit) input-lists,
      # ignoring any trailing digits if the lists are of unequal lengths
      #  -1 if a<b; 0 if a==b; 1 if a>b
  0Û  # Trim all leading 0s
    н # Pop and push the first item, or an empty string if the list is now empty
      # (which is output implicitly as result)
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 9 bytes

Z~A∩÷₌><-

Try it Online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript, 62 bytes

(but outputting the actual comparison characters instead of numbers, because... (that's the challenge spec??)) More like I was stupid and didn't read the comments and thought that that was necessary and didn't want to rewrite the code

a=>b=>a.split``.find((u,i)=>u>b[i]?b=">":b[i]>u?b="<":0)?b:"="

Try it online!

\$\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.