Is 7 l8r than 9? (Is seven later than nine?)

10

2

This is a fairly simple code golf challenge. Your program, given an ASCII string, is to parse that string into two strings, which it will evaluate. If the second string is "later" than the first one, it will return a 1, if it is "earlier" than the first one, it will return a -1, and if they are the same, it will return 0. To clarify what "later" and "earlier" mean, let's take a look at ASCII character codes. You need to compare each character of the string, treating each of them as digits of a number. Later refers to a larger number, occurring after a smaller number. Strings will be formatted with a hyphen character to separate the two input groups.

Take a look at this example:

7-9 as an input should return 1.

7 converts to ASCII code 55, and 9 converts to ASCII code 57.

As 57 occurs numerically after 55, 9 is later than 7.

Another example:

LKzb-LKaj as an input should return -1

The ASCII code sequences for this are 76-75-122-98 and 76-75-97-106

This is a code golf challenge, and byte count is how entries will be scored.

Any input from the 95 printable ASCII characters is accepted, excluding spaces, and hyphens for anything but separating the input. In addition, strings are not guaranteed to be the same length.

Good luck!

EDIT: To be more clear, each character is to be treated like a digit in a number. In the example LKzb-LKaj, though j is later than b, z is later than a, and since it is a more significant digit, it takes precedence. A string supplied will always be at minimum 3 characters, eliminating empty strings from the scope of this problem.

EDIT: Here are some more test cases, for your help:

  • A-9 -> -1
  • 11-Z -> -1
  • 3h~J*-3h~J* -> 0
  • Xv-Y0 -> 1

Sam Weaver

Posted 2015-07-30T18:54:56.533

Reputation: 453

1Are the two strings guaranteed to be the same length? – es1024 – 2015-07-30T19:01:21.647

No, they are not. A reasonable question. Will edit the question. – Sam Weaver – 2015-07-30T19:01:57.203

Are the numbers you're comparing in the second example 767512298 and 767597106, or are you doing character-by-character comparisons? If the former, shouldn't the second be "later" and return 1? If the latter, this looks a lot like a regular compareTo() function. – Geobits – 2015-07-30T19:04:17.540

The conversion is a bit confusing. If I understand correctly, are you essentially stringing together the character value of a string into one bigger integer? So "ABC" becomes the integer 979899? This would just mean to compare the two numbers then with a simple a>b. – Jwosty – 2015-07-30T19:05:46.950

You do not string together the character values, you treat them as one big base-127 (or however many character codes there are) number. The base isn't particularly important, you are doing character by character comparisons. – Sam Weaver – 2015-07-30T19:08:12.970

Can I create a function? – kirbyfan64sos – 2015-07-30T22:00:40.677

5Test case 11-Z->-1 makes no sense given the current wording of the question. Z (90) is greater than 1 (49) and is the most significant letter. Please clarify how strings of different lengths are compared. – George Reith – 2015-07-30T22:40:05.837

The most significant, in this case, refers to the letter with the most value. In binary, decimal, and most number systems, the most significant digit is the left most digit. – Sam Weaver – 2015-07-31T00:41:08.363

Yes @kirbyfan64sos, you can use a function. – Sam Weaver – 2015-07-31T00:41:28.013

2And what about A-AA? – None – 2015-07-31T04:32:12.367

2@SamWeaver I know leftmost is the most significant digit hence my confusion as to why 11>Z in your examples when 1<Z. There must be some undefined behaviour to do with strings of differing lengths or the example is wrong. – George Reith – 2015-07-31T08:23:16.100

3As previously explained: each string is to be treated as a digit in a base-127 number. If you were to count in this system, you would begin with a character, increment it up to the barrier of printable characters, ~ at 126, then would increment the next digit by one, returning the initial digit to !. Each increase in the most significant digit is equivalent to increment the second-most-significant digit by 127. – Sam Weaver – 2015-07-31T13:15:58.293

1So any string of length n is later than all strings of length less than n? – trichoplax – 2015-07-31T14:46:37.417

Correct. Excellent observation. – Sam Weaver – 2015-07-31T14:50:55.043

Answers

11

Pyth - 11 bytes

Easy, uses ._ sign to get the sign and C to get char codes.

._-F_CMcz\-

Try it online here.

Test suite.

._               Sign of number
 -F              Fold subtraction (this finds difference of a tuple)
  _              Reverse list to get correct order of operands when subtracting
   CM            Map char, already treats strings as digits of base256 number
    c \-         Split by "-"
     z           Input

Maltysen

Posted 2015-07-30T18:54:56.533

Reputation: 25 023

Very nice! Performs as expected. – Sam Weaver – 2015-07-30T20:43:13.913

7

CJam, 12 bytes

l'-/esfb~\-g

Try it online in the CJam interpreter.

How it works

l   e# Read a line from STDIN.
'-/ e# Split it at spaces.
es  e# Push the current time (milliseconds since epoch).
fb  e# Consider each string as digits in base huge-number.
~\  e# Dump the results and reverse their order.
-g  e# Subtract and apply sign function.

Dennis

Posted 2015-07-30T18:54:56.533

Reputation: 196 637

Excellent! This passes all test cases. – Sam Weaver – 2015-07-30T21:00:46.887

6

Java, 86 118

int f(String...s){return(int)Math.signum((s=s[0].split("-"))[1].compareTo(s[0])*(s[0].length()==s[1].length()?1:-1));}  

A very strange way of comparing strings. Made a quick fix so it passes additional test cases, will look for more golfiness later.

Thanks to Vartan in comments for signum suggestion

Geobits

Posted 2015-07-30T18:54:56.533

Reputation: 19 061

Doesn't java's compare return 1,0,-1 anyways? I know it's not guaranteed to, but is there any case of it not? in which case return s[0].compareTo(s[1]); – Vartan – 2015-07-30T20:38:13.790

This is nice, but it does not pass the test case of 11-Z returning -1, it returns 1. – Sam Weaver – 2015-07-30T20:58:58.647

Ah, this wasn't clear to me before those test cases were added. Fixed. – Geobits – 2015-07-30T21:25:09.610

@Vartan No, it returns the difference in value at the first non-matching position (or the difference in length if there is one and all characters match). For example, "A".compareTo("Z") returns -25. Unfortunately.

– Geobits – 2015-07-30T21:47:02.463

Can you explain this line? i = a!=b ? b-a : s[1].compareTo(s[0]); I don't seem to get it... Also, you could maybe use Math.signum and save yourself declaring i; – Vartan – 2015-07-30T21:58:15.327

If the lengths (a and b) aren't equal, the diff in lengths is the right sign. Otherwise, use compareTo (no strings of equal lengths need to be compared, longer numbers are always bigger since no leading zeroes are possible). It's going to change in a bit once I golf it down a bit more, I think I can rewrite it so it works differently. – Geobits – 2015-07-30T22:03:23.843

Looks like it's functioning well now! Excellent work! – Sam Weaver – 2015-07-31T00:44:07.790

4

Perl, 31 bytes

#!/usr/bin/perl -p
/-/;$_=($`.$'^$`)cmp($'.$`^$')

30 bytes + 1 byte for -p. Accepts input on STDIN.

Explanation

When the operands to cmp have different lengths, like chicken and egg, they are aligned like this:

c  h  i  c  k  e  n
e  g  g  \0 \0 \0 \0

so that egg > chicken (\0 is a null byte). But we want them to be aligned like this:

c  h  i  c  k  e  n
\0 \0 \0 \0 e  g  g

so that chicken > egg.

To do this, we concatenate them, once with chicken before egg and once with egg before chicken:

c  h  i  c  k  e  n  e  g  g
e  g  g  c  h  i  c  k  e  n

Now that our two strings are the same length, we remove the leading word using an XOR to get:

\0 \0 \0 \0 \0 \0 \0 e  g  g
\0 \0 \0 c  h  i  c  k  e  n

And now we can use cmp to find which came first. (There, I said it!)

ThisSuitIsBlackNot

Posted 2015-07-30T18:54:56.533

Reputation: 1 050

Very clever- Bravo! – Sam Weaver – 2015-08-02T17:47:08.950

3

Python 2, 88 characters

a=raw_input().split('-');print-cmp(*(map(ord,s.rjust(max(map(len,a)),'\0'))for s in a))

cmp doesn't do the right thing when you have two different length strings, so I have to pad both of them with the null character (which ord converts to 0) to handle that case. Unfortunately, that added about 35 characters, plus it's now two lines instead of one because I need both the length of the input and to iterate over it.

Alex Van Liew

Posted 2015-07-30T18:54:56.533

Reputation: 473

Unfortunately, this is not a valid solution. The following test case: 1-2, which should return 1 returns -1. Clever work though. – Sam Weaver – 2015-07-31T00:48:42.397

Whoops, it appears the operands are swapped. That's super weird, I tested it with a couple of your test cases and I thought it worked fine! No matter, I can change it without changing the character count. Give it a shot now. – Alex Van Liew – 2015-07-31T15:07:17.013

Your edit did fix that case, but it now fails the 11-A case, which should return -1, instead of returning 1 in this example. – Sam Weaver – 2015-07-31T15:11:22.830

I don't like your rules for length. I fixed it at the cost of about 35 characters, and I don't think I could make it better. – Alex Van Liew – 2015-07-31T17:53:50.917

Yeah, it's a tricky one. This edit accomplishes it though- well done. – Sam Weaver – 2015-07-31T18:27:11.333

1I managed to get a shorter answer than yours by encoding the string into hex format then parsing that string as an int. In python 2, it seems to default to big-endianness for this. Thus, the 0 padding is no longer required. – Dunes – 2015-07-31T19:30:10.737

No way? I'm surprised that works! Well done. – Alex Van Liew – 2015-07-31T19:55:47.477

2

R, 54 Bytes

This requires the pracma library. It splits the input string on the -. Right justifies the strings. Ranks them and does a diff.

So for 11-7 we end up with the strings "11" and " 7". The rank of these is [2, 1]. The difference is -1. For 3h~J*-3h~J* we get "3h~J*" and "3h~J*". The rank of these is [1.5, 1.5] with a diff of 0.

diff(rank(pracma::strjust(scan(,'',sep='-'),"right")))

Test Examples

> diff(rank(pracma::strjust(scan(,'',sep='-'),"right")))
1: LKzb-LKaj
3: 
Read 2 items
[1] -1
> diff(rank(pracma::strjust(scan(,'',sep='-'),"right")))
1: A-9
3: 
Read 2 items
[1] -1
> diff(rank(pracma::strjust(scan(,'',sep='-'),"right")))
1: 11-Z
3: 
Read 2 items
[1] -1
> diff(rank(pracma::strjust(scan(,'',sep='-'),"right")))
1: 3h~J*-3h~J*
3: 
Read 2 items
[1] 0
> diff(rank(pracma::strjust(scan(,'',sep='-'),"right")))
1: Xv-Y0
3: 
Read 2 items
[1] 1

MickyT

Posted 2015-07-30T18:54:56.533

Reputation: 11 735

Clever. Nice work :) – Alex A. – 2015-07-31T16:06:54.993

2

PERL, 46 36 Bytes

print$2cmp$1if"@ARGV"=~/(\S+)-(\S+)/

Converts the argv list into a string, splits by the hyphen into a left and right sided no spaces arg, then returns a cmp call.

Eric

Posted 2015-07-30T18:54:56.533

Reputation: 37

I suspect you can get rid of a number of spaces and the ; – MickyT – 2015-07-30T22:30:49.753

Should be able to get away with: "@ARGV"=~/-/;print$`cmp$'

(untested) – Jarmex – 2015-07-31T06:43:25.643

1Good idea to use cmp, but it doesn't work when the string lengths are different. "A" cmp "9" is 1 while "11" cmp "Z" is -1, even though both inputs should return the same value for this challenge. – ThisSuitIsBlackNot – 2015-07-31T15:05:24.360

2

CoffeeScript, 143 140 139

f=(s)->[a,b]=((t=s.split '-').map (y)->Array((m=Math.max) 1, 1+(m ((l=(c)->c.length) t[0]),l t[1])-l y).join('\u0000')+y);`b<a?-1:(b>a?1:0)`

Here is a jsfiddle with the results (look in the console)

danielrw7

Posted 2015-07-30T18:54:56.533

Reputation: 21

1

perl5, 64

perl -aF- -pe '@f=map{length}@F;$_=$f[1]<=>$f[0]||$F[1]cmp$F[0]'

Just run it from the commandline. although it would look better with a new line but that costs 1 char.

perl -laF- -pe '@f=map{length}@F;$_=$f[1]<=>$f[0]||$F[1]cmp$F[0]'

This longer version handles mismatched lengths correctly.

hildred

Posted 2015-07-30T18:54:56.533

Reputation: 1 329

/-/,$_=$\cmp$'would be easier, and you can skip the-aF-bit. Also, I count this a 20 (16 for$_=$F[1]cmp$F[0], and 4 forpaF-, saved to a file and run asperl -paF- file.pl`). – primo – 2015-07-31T15:36:56.643

1

As I noted on Eric's answer, cmp doesn't work when the two strings are of different lengths, like with 11-Z.

– ThisSuitIsBlackNot – 2015-07-31T16:04:49.103

@ThisSuitIsBlackNot, fixed. – hildred – 2015-08-02T06:54:09.350

Nice. You can golf that down to 39 with /-/;$_=length$'<=>length$\||$' cmp$`` and -p. ($\`` stores everything before the regex match,$'stores everything after.) Usingmapactually costs more bytes than just callinglength` twice. – ThisSuitIsBlackNot – 2015-08-02T13:17:50.393

1

Python 3, 84 bytes

x,y=[int.from_bytes(i.encode(),"big")for i in input().split("-")];print((x<y)-(y<x))

Split the string input by "-". Convert the unicode strings to bytes strings, then interpret these byte strings as big-endian integers. Finally do the comparison -- (un)fortunately cmp is no longer available in Python 3.

Python 2, 69 bytes

print -cmp(*[int(i.encode("hex"),16)for i in raw_input().split("-")]) 

Dunes

Posted 2015-07-30T18:54:56.533

Reputation: 111

You can shave off a character by removing the space between print and cmp. – Alex Van Liew – 2015-07-31T19:54:31.040

1

Python 2, 79 bytes

Pretty simple solution, and it's easy to understand. Compares string lengths, then compares the strings lexigraphically.

Try it here

s,t=raw_input().split('-')
x,y=len(s),len(t)
print(x<y)*2-1if x-y else cmp(t,s)

mbomb007

Posted 2015-07-30T18:54:56.533

Reputation: 21 944

0

05AB1E, 12 11 9 bytes

'-¡₄ö¥0.S

Try it online or verify all test cases.

Explanation:

'-¡          # Split the (implicit) input on '-'
             #  i.e. 'LKzb-LKaj' → ['LKzb','LKaj']
   ₄ö        # Convert both parts to a Base-1000 number
             #  i.e. ['LKzb','LKaj'] → [21020061037,21020036045]
     ¥       # Push the deltas (subtraction between each sub sequential pair) of the list
             #  i.e. [21020061037,21020036045] → [-24992]
      0.S    # Get the sign [1 for a>0; -1 for a<0; 0 for a==0] (and output implicitly)
             #  i.e. [-24992] → [-1]

Kevin Cruijssen

Posted 2015-07-30T18:54:56.533

Reputation: 67 575

0

JavaScript ES6, 46 43 bytes

f=s=>((a=s.split('-'))[1]>a[0])-(a[1]<a[0])

George Reith

Posted 2015-07-30T18:54:56.533

Reputation: 2 424

Good work, but this does not accomplish test case 2: 11-Z should return -1 but it returns 1. – Sam Weaver – 2015-07-30T21:03:18.483

1@SamWeaver Indeed, that was added after the answer and breaks other answers also. Can you explain why '11'>'Z' when '11'<'ZZ' there is nothing in the question about how to compare string of different lengths or what value an empty string has. – George Reith – 2015-07-30T21:14:13.770

The intent of the question never changed, I only added those test cases and clarification because I realized I was not clear enough in the beginning. You are right that I never defined the value of an empty string, and I will update the question accordingly. Those test cases did not change the behavior or goal of the question, merely clarified it. The examples you named function as such because each character must be treated as an individual "digit" in a number who's base is equivalent to all printable ASCII characters. This mechanic of the question never changed, simply became more clear. – Sam Weaver – 2015-07-30T21:42:47.280

1@SamWeaver Changing from undefined behaviour to defined does change it. Nothing is not a character. Unless its the null character, which this handles. – George Reith – 2015-07-30T21:45:27.510

0

F#, 53

fun s->let[|a;b|]=s="";s.Split[|'-'|]in b.CompareTo a

This is in the form an anonymous function (lambda), so you have to paste it and provide the parameter directly after is (or, using the piping notation). For example (in FSI):

> "7-9" |> fun s->let[|a;b|]=s="";s.Split[|'-'|]in b.CompareTo a
1
> "abc-abc" |> fun s->let[|a;b|]=s="";s.Split[|'-'|]in b.CompareTo a
0
> "LKzb-LKaj" |> fun s->let[|a;b|]=s="";s.Split[|'-'|]in b.CompareTo a
-1

Jwosty

Posted 2015-07-30T18:54:56.533

Reputation: 3 530

0

Ruby, 59 bytes

a,b=gets.chomp.split ?-
p (b.size<=>a.size).nonzero?||b<=>a

daniero

Posted 2015-07-30T18:54:56.533

Reputation: 17 193