2
\$\begingroup\$

this program has to take two strings and compare their length, then tell you which one is longer (string-a or string-b) and by how much

rules:

  • no using .length or other built-in length checking methods (duh!)
  • no using addition or subtraction, this includes improvised addition/subtraction, in case you find some sort of weird improvisation.
  • no > / < (greater then/less then) inside if / if-else statements (you can use them in loops though), this obviously includes >= etc. and no cheating (bool = a > b;if(bool))
  • emphasis is on short rather then efficient code
  • oh yeah almost forgot... good luck!
\$\endgroup\$

closed as unclear what you're asking by 12Me21, Stephen Leppik, Sriotchilism O'Zaic, Toto, mbomb007 Apr 30 '18 at 14:55

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ Is it code-golf? If so, tag it. If not, define the winning criteria. \$\endgroup\$ – ugoren Sep 29 '13 at 9:29
  • 2
    \$\begingroup\$ -1s are probably because your question is very unclear; you don't specify what format the strings are in, how to call the program, what the output should be, etc. \$\endgroup\$ – Doorknob Sep 29 '13 at 23:18
  • 5
    \$\begingroup\$ To Doorknob's comment I would add that questions of the form "Do a task that would normally be insanely trivial but with your hands cuffed behind your back" might make for amusing television, but in the context of programming challenges they largely come down to arguing that a particular language feature doesn't technically break the arbitrary restriction. \$\endgroup\$ – Peter Taylor Sep 30 '13 at 9:13
  • 1
    \$\begingroup\$ "no > / < (greater then/less then) inside if / if-else" while(a>b){ do_something(); break;} is equivalent to an if... \$\endgroup\$ – MrZander Sep 30 '13 at 17:32
  • 3
    \$\begingroup\$ @PeterTaylor: To be fair, doing things with your hands cuffed behind your back is the reason I mostly golf in sed :P \$\endgroup\$ – Hasturkun Oct 1 '13 at 10:05

21 Answers 21

12
\$\begingroup\$

SED, 45 (43 + 2 for the -n flag)

s/./a/g
h
n
s/./b/g
G
:a
s/b\(.*\)a/\1/
ta

Expects input as two separate lines, outputs the difference in unary, using "a" or "b" to indicate the longer string. run with sed -n.

\$\endgroup\$
5
\$\begingroup\$

Perl, 87 78 - tells which is longer and by how much

alternative:

  • 72 - tells which is longer and by how much, no special message if equal

Perl script expecting 2 strings as command line arguments. Tells which one is longer and by how much. This one I tried to make it readable and not short.

#!/usr/bin/perl
use warnings;
use strict;

my ($x,$y)=@ARGV;
$x=$x=~s/.//g;
$y=$y=~s/.//g;
my @z=($x..$y);
my @w=($y..$x);
if (@z) {
    if ($#z) { print "2nd longer than 1st by $#z" }
    else { print "Equal length" }
}
else {
    print "1st longer than 2nd by $#w"
}

Same code as a one liner, counting 78 characters (output now prints "a3" if a > b by 3 characters, "0" if equal):

perl -E'($x,$y)=@ARGV;$_=s/.//g for$x,$y;@z=$x..$y;@w=$y..$x;say@z?$#z?"b$#z":0:"a$#w"'

Finally, since OP clarified that when they are equal it is not really important what it will print, we can save 6 more characters:

perl -E'($x,$y)=@ARGV;$_=s/.//g for$x,$y;@z=$x..$y;@w=$y..$x;say@z?"b$#z":"a$#w"'
\$\endgroup\$
  • 1
    \$\begingroup\$ You don't need to count the perl -e (or -E), or the single-quotes around the program, so yes, your score is currently 78. \$\endgroup\$ – breadbox Sep 29 '13 at 21:23
5
\$\begingroup\$

Tcl 8.6, 90

lmap c [split $a {}] d [split $b {}] {puts [expr {{}eq$d?{A}:{}eq$c?{B}:[continue]}];exit}

If you run Tcl 8.5, use foreach instead lmap.

This shows a nice feature of Tcl's foreach/lmap: It can walk over several lists at once.

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

J 17

Since there is no output specification: the length difference is outputted at the location of the shortest string

    longest =: *&.^/"1@(=&' ')@,:
    'foobar' longest 'abc'
0 3 NB. Means abc is shorter by 3 chars.
\$\endgroup\$
4
\$\begingroup\$

Javascript 96 92

x=prompt;i=c=0;for(p=x();c=p[i=-~i];);q=x();for(j=0;c=q[i=~-i,j=-~j];);alert(0<i&&p+i||q+-i)

Note 0<i&& contains no if statement but a logical operator, which is not forbidden.

Input asd,asdfg Output asdfg2

Means asdfg is 2 characters longer.

\$\endgroup\$
  • \$\begingroup\$ this is a fair loophole, and you program is cute. \$\endgroup\$ – Math chiller Sep 30 '13 at 19:45
  • \$\begingroup\$ Could you explain how this works? c=p[i=-~i] would just be 1 wouldn't it? \$\endgroup\$ – tristin Oct 1 '13 at 21:10
  • \$\begingroup\$ @tristin I'm on mobile, but i'll try: ~ is the bitwise NOT operator and flips all bits. 0001 becomes 1110. So ~0 === -1 and - -1 === 1 -> ~1 === -2 and - -2 === 2 and so forth. I hope this was understandable :) \$\endgroup\$ – C5H8NNaO4 Oct 1 '13 at 21:44
  • \$\begingroup\$ @tryingToGetProgrammingStraight Thanks :) \$\endgroup\$ – C5H8NNaO4 Oct 1 '13 at 21:45
3
\$\begingroup\$

Bringing up the rear as always with the verbose language. :)

Java - 278

import java.util.*;class b{public static void main(String[]a){Stack z=new Stack(),y=new Stack();for(String q:a[0].split(""))z.push(q);for(String q:a[1].split(""))y.push(q);while(!z.empty()&&!y.empty()){z.pop();y.pop();}System.out.print(y.empty()?"1-"+z.size():"2-"+y.size());}}

With line breaks and tabs

import java.util.*;
class a{
    public static void main(String[]a){
        Stack z=new Stack(),y=new Stack();
        for(String q:a[0].split(""))z.push(q);
        for(String q:a[1].split(""))y.push(q);
        while(!z.empty()&&!y.empty()){
            z.pop();
            y.pop();
        }
        System.out.print(y.empty()?"1-"+z.size():"2-"+y.size());
    }
}
\$\endgroup\$
3
\$\begingroup\$

Ruby, 66 52 (shows only which one is longer)

f=->{gets.gsub(/./,?1)}
a=f[]
b=f[]
puts'sab'[a<=>b]

Prints s for same, a for string a, and b for string b.

Ruby, 184 173 146 143 139 140 (also shows how much longer it is)

f=->{gets.gsub(/./,?1)}
a=f[]
b=f[]
d=->e{Math.log10(e.to_i).floor.next.to_s}
puts(a==b ? ?s:(c=a.sub(b,''))!=a ? ?a+d[c]:?b+d[b.sub(a,'')])

Sample run:

c:\a\ruby>stringcmp
testing123
testing
a3

c:\a\ruby>stringcmp
codegolf.SE
code golf . stack exchange
b15

c:\a\ruby>stringcmp
test
test
s

c:\a\ruby>
\$\endgroup\$
  • \$\begingroup\$ second example contains +'s \$\endgroup\$ – ljs.dev Oct 1 '13 at 13:12
  • \$\begingroup\$ @lalalalalalalambda For string concatenation, not addition. \$\endgroup\$ – Doorknob Oct 1 '13 at 13:13
  • \$\begingroup\$ OK, I removed mine thinking concatenation would also count as addition, requiring strings to be joined via adding/removing elements to an array... just nit-picking though because mine is so darn long :P I don't think there is any hard n fast rule about it \$\endgroup\$ – ljs.dev Oct 1 '13 at 13:15
  • \$\begingroup\$ @Doorknob This + is not string concatenation: Math.log10(e.to_i)+1 (second version, third line). You can use integer's .next or .succ though. \$\endgroup\$ – daniero Oct 10 '13 at 12:47
  • \$\begingroup\$ @daniero Whoops, missed that. Fixed (only +1 char) \$\endgroup\$ – Doorknob Oct 10 '13 at 13:01
3
\$\begingroup\$

Mathematica 40

f = #~Count~0 & /@ PadLeft[Characters /@ {##}] &

Output is similar to the J version.

Example Usage:

f["looooong", "short"]

{0, 3}

f["short", "thisstringisveryverylong"]

{19, 0}

f["equal", "equal"]

{0, 0}

\$\endgroup\$
3
\$\begingroup\$

PHP (44)

-r'list(,$a,$b)=$argv;echo strcmp($a^$a,$b^$b);'
  • The -r argument and single quotes are not counted in the score.
  • string-a and string-b are accepted as command-line arguments.
  • The magnitude of the decimal number printed is the difference in length.
  • The sign indicates which string is longer. A positive number means string-a is longer. A negative number means string-b is longer. Zero means the strings are the same length.

PHP 5.4 (96)

Here, strcmp is avoided in favor of other string functions that are not so cheap.

-r'list(,$a,$b)=$argv;echo@strtr(explode(${"\3"^$c=trim(($a^=$a).b^($b^=$b).a)},$$c,2)[1],"\0",$c);'
  • Scoring and input format remain the same.
  • The difference in length is printed in unary.
  • The symbol a is used if string-a is longer; b is used if string-b is longer.
  • Nothing is printed if the strings are the same length (except in the commented version, which omits the error suppression operator @ and thus may report PHP notices and warnings).

Commented code:

<?php

list(, $a, $b) = $argv;

// Replace all bytes in both $a and $b with null bytes
// (Anything XORed with itself is zero.)
$a ^= $a;
$b ^= $b;

// PHP's bitwise XOR truncates its output to the shorter string's length,
// so only the marker ('a' or 'b') appended to the shorter string will
// remain after the null bytes in common are trimmed off. If $a is shorter,
// 'b' remains; likewise, if $b is shorter, 'a' remains.
$longer = trim($a . 'b' ^ $b . 'a'); // $c in the golfed code

// Flip bits 0 and 1 to switch 'a' to 'b' (or 'b' to 'a')
// ('a' === chr(0b1100001); 'b' === chr(0b1100010); "\3" === chr(0b11))
$shorter = "\3" ^ $longer;

// Remove the shorter string from the longer string
// $$shorter refers to $a if $shorter === 'a' or $b if $shorter === 'b'.
// $$longer works the same way.
$difference = explode($$shorter, $$longer, 2)[1];

echo strtr($difference, "\0", $longer);
\$\endgroup\$
2
\$\begingroup\$

JavaScript (prompt for input) - 128

I golfed it 2 more characters.

p=prompt,f=alert,i='lastIndexOf'
a=p().replace(/./g,'.')
b=p().replace(/./g,'.')
j=a[i](b),k=b[i](a)
~j&&f('a '+j)
~k&&f('b '+k)
\$\endgroup\$
  • \$\begingroup\$ "this program has to take two strings" \$\endgroup\$ – Math chiller Sep 29 '13 at 17:49
  • \$\begingroup\$ You supply two strings a and b to a function F. Do you want command line style? \$\endgroup\$ – tristin Sep 29 '13 at 17:50
  • \$\begingroup\$ its not a stand-alone program, it doesnt matter how you get the strings, prompting or inputs or whatever is fine, it just has to be stand-alone. \$\endgroup\$ – Math chiller Sep 29 '13 at 17:56
2
\$\begingroup\$

Python - 291 261 244 223 220 210 206

I got 206

import sys,itertools
q=sys.argv
h=[]
i=0
for k,g in itertools.groupby(map(lambda f,b:2 if f is None else 1 if b is None else 0,q[1],q[2])):h.append(list(g))
for i,a in enumerate(h[1],1):0
print q[h[1][0]],i

Sample Run

C:\pjs\codegolf>python last.py bananas apples
bananas 1
C:\pjs\codegolf>python last.py bananas hazlenuts
hazlenuts 2
\$\endgroup\$
  • 1
    \$\begingroup\$ Lots of room for golfing still. e.g. single-line blocks can go immediately after the colon on the previous line, like this: "if u:print [sys.argv[1],str(u)]". You can omit all of the indentation whitespace this way. \$\endgroup\$ – breadbox Oct 1 '13 at 17:46
  • \$\begingroup\$ thanks @breadbox, I pinched this for mine, too. was trying break if e to no avail, so if e:break saved me another 12 :) \$\endgroup\$ – ljs.dev Oct 1 '13 at 17:54
  • 1
    \$\begingroup\$ You can replace pass with 0 (or any other 1-character-Expression). Also, space after , and space before [ is unnecessary. (On the other hand, you don't even need the brackets in the print statements.) Oh, and the calls to list should be unnecessary (untested). I'll stop now :-) \$\endgroup\$ – WolframH Oct 1 '13 at 21:19
  • \$\begingroup\$ @WolframH I changed a little, but thank you about replace pass by 0 \$\endgroup\$ – Doug Correa Oct 1 '13 at 22:44
  • \$\begingroup\$ well done Doug and thanks to @WolframH, this CG thing is really educational! \$\endgroup\$ – ljs.dev Oct 2 '13 at 2:51
2
\$\begingroup\$

Bending the rules some...

JavaScript (92)

p=prompt
~function f(a,b) {
   a && !b && alert(0)
  !a &&  b && alert(1)

  f(a.slice(1), b.slice(1))
}(p(),p())

(Minified: p=prompt;~function f(a,b){a&&!b&&alert(0);!a&&b&&alert(1);f(a.slice(1),b.slice(1))}(p(),p()))

Takes two strings via prompts. Alerts the difference in unary (as with Hasturkun's solution), using 0s if the first string is longer and 1s if the second string is longer. Outputs each digit in a separate alert (ow), and terminates eventually when the call stack runs out (owww).

If we ignore the rule about no addition or subtraction, we could easily have the number be a nice (base 10) number whose sign denotes which string is longer:

p=prompt
alert(function f(a,b,n) {
  return a || b? f(a.slice(1), b.slice(1), n - !a + !b)
       :         n
}(p(),p(),0))

This version doesn't even wait for the call-stack to overflow!

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

Perl, 69 characters

sub l{l(map{substr$_,1}@_)if$_[0]&&$_[1];say pop()?2:1;die}l(<>,<>)

The gist is, recurse until one string is empty, then print the other. Run with perl -e CODE 2> /dev/null

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

Python 3: 125 91 90

Finally beat the JavaScript solutions :)

Prints both which is longer, and by how much.

Current (90 and Python 3):

I=input
q=a,b=I(),I()
while a+b:s=q[b!=""];a=a[1:];b=b[1:];i=a and b and-1or-~i
print(s,i)

Example output:

rees@Rees-Ubuntu:~/Python/CodeGolf$ python3 StringComparer.py
hi <- input one
hello <- input two
hello 3 <- output

Old (125 and Python 2):

r=raw_input
q=a,b=r(),r()
while a and b:a=a[1:];b=b[1:]
s=(q[0],q[1])[a==""]
i=0
while a or b:a=a[1:];b=b[1:];i=-~i
print s,i
\$\endgroup\$
1
\$\begingroup\$

Python, 708, 570, 566, 462, 492, 481, 480, 475, 363, 357, 354, 346, 343, 341, 340, 327, 315 (with whitespace)

My first CG, be gentle:

import sys
c=[1,2]
a=o=[]
l=d=e=v=0
s=sys.argv
r=range(0,99)
a=[zip(list(s[x]),r[1:]) for x in c]
a.insert(0,0)
for x in c:
    for p in a[x]:
        try:
            v=a[x==2 and 1 or 2][p[1]]
        except:
            l=s[x]
            o.append(1)
            e=1
    if e:break
o=zip(o,r)
print[l,o.pop()[1]]

Sample run:

me@home:~$ python diff.py bananas apples
['bananas', 1]
me@home:~$ python diff.py bananas hazlenuts
['hazlenuts', 2]
\$\endgroup\$
1
\$\begingroup\$

C, 230 200 193 characters

EDIT: Shortened it from 230 to 193 characters.

My first golf attempt. Maybe not a hole-in-one, but it works. Not being allowed to use strlen for this forces it to be fairly verbose in C. Maybe it can be shortened a bit?

a,b,w,i,l;
int main(int c,char **v){
    for(;a<256||b<256;i++){
        if(!v[1][i])a|=256;
        if(!v[2][i])b|=256;
        if(!(a&256))a++;
        if(!(b&256))b++;
    }
    a&=255;b&=255;
    w=a>b?0:1;
    l=w?b-a:a-b;
    printf("%s %i\n",v[w+1],l);
}

Or the uglier version:

a,b,w,i,l;int main(int c,char **v){for(;a<256||b<256;i++){if(!v[1][i])a|=256;if(!v[2][i])b|=256;if(!(a&256))a++;if(!(b&256))b++;}a&=255;b&=255;w=a>b?0:1;l=w?b-a:a-b;printf("%s %i\n",v[w+1],l);}

Example output:

N:\>golf.exe everything works
everything 5
\$\endgroup\$
  • \$\begingroup\$ it has to tell you how much it is longer by not how long the longer one is. \$\endgroup\$ – Math chiller Oct 17 '13 at 9:37
  • \$\begingroup\$ Some tips: int in variable declarations is optional. No need for parentheses around a<256. if(!x)y -> x||y. i is initialized by default. \$\endgroup\$ – ugoren Oct 17 '13 at 19:29
  • \$\begingroup\$ Whoops, it outputs the difference now instead. Thanks for the tips ugoren. I knew "i" was initialized too, but I'm just so used to trying to write clear code! Like I said, my first golf. :) \$\endgroup\$ – Mike C Oct 18 '13 at 1:49
1
\$\begingroup\$

Powershell 140 (assumes a max difference of 999)

$c=@(compare($args[0]-split'.')($args[1]-split'.'))
$n=[collections.stack]@(999..1)
$c|%{$n.pop()}
if($c){$args[$c[0].sideindicator-eq'=>']}

Outputs nothing if the string lengths are equal. If the string lengths are not equal, the longer string is displayed; the last number is the difference.

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

C (gcc), 89 bytes

i;c;q;j;f(a,b)char*a,*b;{for(i=j=c=0;a[i]||b[j];a[i]&&++i,b[j]&&++j)a[i]&&b[j]?:++c;a=c;}

Try it online! I think this has room for improvement, but I'm not sure where. Abuses undefined behaviour, but it it Works On TIO™. Simply starts increment c when one of a[i] or b[j] is the null byte (the end of the string); i and j are incremented until they hit this null byte.

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

Clojure - 206

(defn is-longer [first second first-left second-left]
  (defn remaining [current count]
    (if (empty? current)
      (/ (Math/log count) (Math/log 2))
      (remaining (rest current) (bit-shift-left count 1))))
  (cond
   (empty? first-left) [2 (remaining second-left 1)]
   (empty? second-left) [1 (remaining first-left 1)]
   :else (is-longer first second (rest first-left) (rest second-left))))

Or minified:

(defn y [a b al bl] (defn x [u t] (if (empty? u) (/ (Math/log t) (Math/log 2)) (x (rest u) (bit-shift-left t 1)))) (cond (empty? al) [2 (x bl 1)] (empty? bl) [1 (x al 1)] :else (y a b (rest al) (rest bl))))

Or in prettierific:

Returns: [1|2 count]

Getting around not using + was a fun challenge.

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

Python, 194

import sys,itertools as T
A=sys.argv
B=[]
N,i=None,0
for k,g in T.groupby(map(lambda f,b:[[0,1][b is N],2][f is N],A[1],A[2])):B.append(list(g))
for i,j in enumerate(B[1],1):0
print A[B[1][0]],i
\$\endgroup\$
0
\$\begingroup\$

R - 120/114

Shows difference:

a=strsplit(scan(what='c'),"")
c=0
for(i in 1:2){for(y in a[[i]]){if(i-1)c=c+1 else c=c-1}}
d=abs(c)
cat(a[[(c==d)+1]],d)

Shows just the longer:

a=strsplit(scan(what='c'),"")
c=0
for(i in 1:2){for(y in a[[i]]){if(i-1)c=c+1 else c=c-1}}
cat(a[[(c==abs(c))+1]])
\$\endgroup\$

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