29
\$\begingroup\$

Your task is simple. Determine if one string equals the other (not address, the value) without the use of equality operators (such as ==, ===, or .equal()) or inequality (!=, !==) anything similar for other languages. This means anywhere! You may not use these operators anywhere in the code. You may however, you use toggles such as !exp as you're not directly comparing the exp != with something else.

In addition, you may not use any functions such as strcmp, strcasecmp, etc.

As for comparison operators (>=, <=, >, <), they are also disallowed. I realize that some answers include this, but I'd really like to see more answers that don't borderline the equality operator.


An example using PHP is shown:

<?php

$a = 'string';
$b = 'string';

$tmp = array_unique(array($a, $b));

return -count($tmp) + 2;

Simply return true or false (or something that evaluates in the language to true or false like 0 or 1) to indicate if the strings match. The strings should be hardcoded seen in the above example. The strings should not be counted in the golf, so if you declare the variable before hand, don't count the declaration.

\$\endgroup\$
  • 1
    \$\begingroup\$ Is it necessary to output the result, or simply write a function to return a bool? If writing a complete program is required, that could make-or-break answers in languages with (relatively) significant boilerplate to create a functioning executable like Java and C# (such is the nature of the beast, but this challenge has little in the way of concrete guidelines, leaving much to interpretation/choice). And how are we to take the strings? Hardcoding, reading from STDIN, pass as command-line arguments? \$\endgroup\$ – Tony Ellis Mar 12 '14 at 14:23
  • \$\begingroup\$ Is this [code-golf] or a [popularity-contest]? It can't be both. \$\endgroup\$ – Gareth Mar 12 '14 at 14:23
  • \$\begingroup\$ Sorry, I have modified my questions to reflect both comments. \$\endgroup\$ – David Chen Mar 12 '14 at 14:32
  • \$\begingroup\$ So inequality is allowed? \$\endgroup\$ – user80551 Mar 12 '14 at 14:41
  • \$\begingroup\$ If the strings are to be hardcoded more than once(each) , do i have to count their length? \$\endgroup\$ – user80551 Mar 12 '14 at 15:13

78 Answers 78

1
\$\begingroup\$

C++: 104 105 characters

#include<string>
#include<set>
template<typename T>
int f(T a,T b){std::set<T>S={a};return S.count(b);}

EDIT: Saved a character by making it a template function.

Function itself is 51 characters. Other C++ answers already posted are shorter, but I wanted to try one that wasn't also pure C. In fact, this requires C++11. For earlier versions of C++ you can replace std::set<T>S={a}; with std::set<T>S(&a,&a+1); at the expense of an extra 5 characters.

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

Excel VBA

Function stringmatch()
a = ""
b = ""
For i = 1 To Len(a)
If Asc(Right(Left(a, i), 1)) - Asc(Right(Left(b, i), 1)) Or Len(a) - Len(b) Then
debug.print "string unnmatch"
Exit Function
End If
Next
debug.print  "string match"
End Function
\$\endgroup\$
  • \$\begingroup\$ I think your <> is classified as an inequality operator, which is not permitted by the rules. \$\endgroup\$ – user12205 Mar 13 '14 at 21:43
  • \$\begingroup\$ @Ace oh thx, seeing "=" is allowed I thought "<>" is also allowed \$\endgroup\$ – Alex Mar 13 '14 at 21:49
  • 1
    \$\begingroup\$ = is allowed as an assignment operator. If your language uses this symbol as an equality operator you still cannot use it. (This applies to Visual Basic .NET, I don't know about Excel VBA.) \$\endgroup\$ – user12205 Mar 13 '14 at 21:57
  • \$\begingroup\$ Oh ok thanks, I have used another expression (edited code) \$\endgroup\$ – Alex Mar 13 '14 at 22:03
1
\$\begingroup\$

Groovy 347

def compare(str1,str2){
    def str1val = 0
    def str2val = 0

    MessageDigest md5 = MessageDigest.getInstance("MD5")
    md5.digest(str1.getBytes("UTF-8")).each{ str1val += it*2 }
    md5.digest(str2.getBytes("UTF-8")).each{ str2val += it*2 }

    if(!(str1val-str2val)) {
        return true    
    } else {
        return false
    }
}
\$\endgroup\$
1
\$\begingroup\$

Python, 7 chars.

b in[a]

Where b and a are strings.

\$\endgroup\$
  • \$\begingroup\$ You can write this b in[a] with one less character. \$\endgroup\$ – r.e.s. Mar 20 '14 at 18:14
1
\$\begingroup\$

Perl - 10

/^\Q$w\E$/

The input is in $_ and $w. The output is stored in $&.

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

R (4 chars)

'string1'%in%'string2'

Or, for an actual function,

(6 chars)

`%in%`

which is called with

`%in%`(x,y)

As R is a vector-based language, is treated as a string and b is treated as a vector of one string, so this is similar to the elem a[b]/a in b in a/a in[b] solutions in spirit.

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

Java (235 characters for golfed version at bottom).

Strings are not hardcoded, but this is a trivial change.

   public boolean areEqual(String a, String b) {
    int[] q = new int[1];
    int i = 0;
    try {
        while (true) {
            noOp(q[(int) a.charAt(i) - (int) b.charAt(i)]);
            i++;
        }
    } catch (Error e) {
        try {
            a.charAt(i);
        } catch (Error e2) {
            try {
                b.charAt(i) {catch(Error e3){
                    return true;
                }
                }
            }


            return false;
        }
        return true;
    }
}

public void noOp(int i) {
}

Traverses both strings, using the difference in chars to select an array index (which is 0-based). No in-loop comparisons or Math.max used. Using Error as a throwable instead.

Golfed for use under certain circumstances (instantiated class, used from same package):

boolean a(String a,String b){boolean t=true,f=!t;int[]q={1};int i=0;try{while(t){q[(int)a.charAt(i)-(int)b.charAt(i)];i++;}}catch(Error e){try{a.charAt(i);}catch(Error z){try{b.charAt(i){catch(Error g){return t;}}}return f;}return t;}}
\$\endgroup\$
  • \$\begingroup\$ Any purpose for noOp? \$\endgroup\$ – Cole Johnson Mar 13 '14 at 23:24
  • \$\begingroup\$ The golfed and ungolfed code don't compile... \$\endgroup\$ – Poke Mar 26 '17 at 1:47
  • 1
    \$\begingroup\$ @ColeJohnson I'm guessing the noOp function is because array[i] isn't a statement by itself. Rather than calling a function OP could just set the value of that array index since it's not used anyway. \$\endgroup\$ – Poke Mar 26 '17 at 1:48
0
\$\begingroup\$

Python, 79

a=list(a)
b=list(b)
for i in range(len(a)):
 if ord(a[i])-ord(b[i])<0:
  print 'n'
\$\endgroup\$
  • \$\begingroup\$ The question has been edited: the strings should be hard-coded, though I think your approach is better (golfier). \$\endgroup\$ – 11684 Mar 12 '14 at 14:37
  • \$\begingroup\$ It will print n multiple times \$\endgroup\$ – user80551 Mar 12 '14 at 14:43
  • \$\begingroup\$ At the cost of a few chars, I could make it better \$\endgroup\$ – TheDoctor Mar 12 '14 at 14:47
  • \$\begingroup\$ Your program does not return whether the strings are equal or not, although it could be changed trivially to suit the rules. \$\endgroup\$ – Hosch250 Mar 12 '14 at 16:20
0
\$\begingroup\$

Python - 52 chars without strings (76 with strings)

The in operator might be skirting the edges, but the rules disallow strict equality comparison, not similarity comparison.

a="string"
b="string"
x=a in b and not(len(a)-len(b)>0 or len(a)-len(b)<0)
\$\endgroup\$
0
\$\begingroup\$

Perl, 24 bytes

$r=!(-1+keys{$a,1,$b,1})

The two strings are given in $a and $b. The result is stored in $r.

The trick is using a hash array. If the strings are equal, then only one hash entry is created.


A standalone variant that gets the string from STDIN and returns 0, if the strings match and 1 otherwise:

$h{<>}=$h{<>}=1;exit -1+keys%h
\$\endgroup\$
  • \$\begingroup\$ @DaveChen: Thanks, == is now removed. \$\endgroup\$ – Heiko Oberdiek Mar 12 '14 at 14:57
0
\$\begingroup\$

Ruby, 21

Online version

Strings have to be stored in a and b:

!!(a+b=~/^(#{a})\1$/)

Checks if the concatenation of a and b contains a twice.

\$\endgroup\$
  • \$\begingroup\$ Insufficient. Gives true for a="string"; b="stringstring". You have to anchor the regular expression to the start of string too with ^. \$\endgroup\$ – manatwork Mar 12 '14 at 15:37
  • 1
    \$\begingroup\$ I feel like =~ needs to be forbidden, or you can just do !!(a=~/^#{b}$/) \$\endgroup\$ – histocrat Mar 12 '14 at 16:50
  • \$\begingroup\$ Well, it's just an abbreviation for .match(x): !!(a+b).match(/^(#{a})\1$/) - but yes, it somehow is an equality operator... \$\endgroup\$ – David Herrmann Mar 12 '14 at 17:22
0
\$\begingroup\$

D 30

string a="somestring";
string b="somestring";

return !reduce!"a|b"(a[]^b[]);
\$\endgroup\$
  • \$\begingroup\$ I think !reduce! falls under the banned equality operators. \$\endgroup\$ – Hosch250 Mar 12 '14 at 16:31
  • \$\begingroup\$ it negates the integer result, no different than the C solution using the same xor trick \$\endgroup\$ – ratchet freak Mar 12 '14 at 16:32
0
\$\begingroup\$

Python 15 - 2( if you hard code the string in the solution) = 13

>>> s = 'string'
>>> t = 'string'
>>> 1 is len({s,t})
True
>>> s = 'string1'
>>> t = 'string2'
>>> 1 is len({s,t})
False

Python 17

>>> s = 'string'
>>> t = 'string'
>>> s in t and t in s
True
>>> s = 'string1'
>>> t = 'string2'
>>> s in t and t in s
False
\$\endgroup\$
0
\$\begingroup\$

Perl, 25 bytes

$r="$a$b"=~/^(\Q$a\E)\1$/

The input is expected in variables $a and $b. The result is stored in $r. It uses a regular expression to check, whether the concatenation "$a$b" is a duplicate of $a.

\$\endgroup\$
  • \$\begingroup\$ Does that answer allow for "regex-special" charaters in either $a or $b? (will it still match properly if $a contains a .? \$\endgroup\$ – IQAndreas Mar 14 '14 at 15:29
  • \$\begingroup\$ @IQAndreas: Yes, the special characters are disabled by \Q...\E. \$\endgroup\$ – Heiko Oberdiek Mar 14 '14 at 20:45
0
\$\begingroup\$

Python (7)

Assuming strings are stored in variables a and b:

a<=b<=a
\$\endgroup\$
0
\$\begingroup\$

Emacs Lisp

(split-string-and-unquote a b)

returns nil when a == b, something else when a != b

(print (if (split-string-and-unquote a b) "not equal..." "equal!"))

If I'm doing string work in elisp I use the popular package s.el in which it could be written a little shorter and without a negated output

(not (s-split a b t))
\$\endgroup\$
0
\$\begingroup\$

Java - 193

new int[]{0,1,0}[new BigInteger(a.getBytes()).subtract(new BigInteger(b.getBytes())).signum()+1]

No comparison operators at all, not even a < or >.

\$\endgroup\$
  • \$\begingroup\$ This is just a code snippet. The consensus for challenges on PPCG is that a full program or function is required unless explicitly stated in the question. Moreover 1 and 0 are not truthy and falsey in java so I'm not sure this is allowed. Finally you're making use of Java's BigInteger but you're not taking the byte count hit for the import of that class. \$\endgroup\$ – Poke Mar 26 '17 at 2:00
0
\$\begingroup\$

C - 45 characters

r;main(){ // 9 chars here
    char *a = "str2";
    char *b = "str1";
while(r+=*a^*b,*a++**b++);return!r;} // 36 more here
\$\endgroup\$
  • \$\begingroup\$ Fails if: a="str1"; b="str1b" \$\endgroup\$ – Emmet Mar 13 '14 at 17:49
  • \$\begingroup\$ Works for me. The catch is when run from terminal, "equal" means "failure" (non-zero return code). \$\endgroup\$ – aragaer Mar 13 '14 at 18:02
  • \$\begingroup\$ You're right. My apologies. When I ran it, I was inconsistently thinking of the shell's idea of true/false and C's, which are the opposite way around. \$\endgroup\$ – Emmet Mar 13 '14 at 18:29
0
\$\begingroup\$

C++ 30

#include<string>
std::string a = "test", b = a;
int main(){return!(a<b||a>b);}

I'm not counting the first two lines because:

The strings should not be counted in the golf.

And here are some tests.

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

Delphi (412 83 75)

Can probably be done shorter but was fun to do, going to see if i can get some off.
412 -> 83 Cant believe I missed this... Checks if s1 is in s2 and if s2 is in s1. Saved 329 chars Cheers
83 -> 75 Thanks to Manatwork. Changed check if s1 is in s2 and other way around. Saved 8 characters

const s1='string12';s2='string12';begin Write(Pos(s1,s2)*Pos(s2,s1)>0);end.

Ungolfed

const
  s1='string12';
  s2='string22';
begin
  Write(Pos(s1,s2)*Pos(s2,s1)>0);
end.
\$\endgroup\$
  • 1
    \$\begingroup\$ A few tests I made shows that Pos(s1,s2)*Pos(s2,s1)>0 would also do it. \$\endgroup\$ – manatwork Mar 13 '14 at 10:33
0
\$\begingroup\$

Dart - 15

Strings are stored in a en b.

[a].contains(b)

[a] creates a List with a.

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

Python 2 - 50 54 (including strings)

Thanks to Ace for way around the "==" issue

a='string'
b='string'
not(len(''.join(set(a+b)))-len(a))

Output

True

Non-equal strings

a='string'
b='String'
not(len(''.join(set(a+b)))-len(a))

Output

False
\$\endgroup\$
  • 2
    \$\begingroup\$ Can't use ==, even if you're not comparing the strings. \$\endgroup\$ – David Chen Mar 12 '14 at 15:32
  • \$\begingroup\$ You may wish to use not (len(''.join(set(a+b)))-len(a)) instead. \$\endgroup\$ – user12205 Mar 12 '14 at 19:35
0
\$\begingroup\$

C++ - 66 57 53

int c(char*a,char*b){return *a-*b?0:*a?c(++a,++b):1;}

with the ungolfed version:

int mystrcmp( char* a, char* b )
{
  // If the characters don't match, we're done
  if( *a - *b )
  {
      return 0;
  }

  // If they do match, and both were nulls, we are done 
  if( !*a )
  {
      return 1;
  }

  return mystrcmp( ++a, ++b );
}

Driver program in original post below.


Old version: The golfed version:

int c(char*a, char*b){while(*a|*b)if(*a++-*b++)return 0;return 1;}

Here is a full driver program with comments:

#include <iostream>

using std::cout;
using std::endl;

int mystrcmp( char* a, char* b ) {
   // The comparison will continue as long as both *a and *b are not '\0'.
   // If one of them goes '\0' but the other does not, the strings are not 
   // of equal length and at that point we will return 0.
   while( *a | *b ) {
     // Compare the current character and return 0 if they are not equal.
     // *a++ will return the value of *a and then increment the pointer -
     // see http://stackoverflow.com/questions/9255147/does-p-increment-after-dereferencing
     if(*a++ - *b++) {
       return 0;
     }
   }

   // If we got here, both strings are equal up to and including the last '\0'.
   return 1;
}

int main()
{   
   // Prints 1
   cout << mystrcmp("Hello.", "Hello.") << endl;

   // Prints 1       
   cout << mystrcmp("Hello, world!", "Hello, world!") << endl;

   // Prints 0
   cout << mystrcmp("Hello", "Hello.") << endl;

   // Prints 0       
   cout << mystrcmp("Hello.", "Zello.") << endl;

   // Prints 0
   cout << mystrcmp("Hello", "Hallo") << endl;

   // Prints 0
   cout << "Hello World" << endl; 

   return 0;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ You can drop the parentheses: *a-*b?0:*a?c(++a,++b):1 \$\endgroup\$ – n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Mar 13 '14 at 10:59
  • \$\begingroup\$ Thanks @n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, for some reason I thought there would a problem with the precedence. \$\endgroup\$ – CompuChip Mar 13 '14 at 14:40
0
\$\begingroup\$

C#

I know there's already a C# answer, I just wanted to show other options. :)

boolean:

  • 51

    !Convert.ToBoolean(new[]{a,b}.Distinct().Count()-1)
    

1 or 0:

  • 32

    -new[]{a,b}.Distinct().Count()+2
    
\$\endgroup\$
0
\$\begingroup\$

Q - [3 bytes]

a:"string"
b:"string"

a~b

I think this is a valid answer as ~ isn't an equals operator. From a Q tutorial:

~ asks whether two entities have the same contents.

http://kx.com/q/d/primer.htm

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

C#

void Main()
{
    Console.WriteLine(StringEqual("pie","pie")); // true
}

bool Equals(int a,int b)
{
    var aBytes = BitConverter.GetBytes(a);
    var bBytes = BitConverter.GetBytes(b);

    return aBytes.SequenceEqual(bBytes);
}

bool StringEqual(string a,string b)
{
    int i = 0;
    return a.All((c) => Equals((int)c,(int)b[i++]));
}
\$\endgroup\$
  • \$\begingroup\$ why not just a.SequenceEqual(b) ??? \$\endgroup\$ – Habib Mar 13 '14 at 16:58
  • \$\begingroup\$ @Habib I'm stupid. :D \$\endgroup\$ – Raz Megrelidze Mar 13 '14 at 17:18
0
\$\begingroup\$

Javascrpt: 38 chars (without a-b declarations) || 31 without alert()

a="string";
b="string";

o={};o[a]=0;alert(o.hasOwnProperty(b))

sets an object key named the value of a -- checks for a key named the value of b in that object.

without alert:

o={};o[a]=0;o.hasOwnProperty(b)
\$\endgroup\$
0
\$\begingroup\$

J - 6 char

A J expression which tests for string equality without testing for string equality? Here's one:

e./a;b        NB. is a boxed in b boxed?

Not good enough? Want some more options? Go ahead, have some more, J has plenty.

<:#~.a;b      NB. (the number of the unique items among the two) - 1
1-{:~:a;b     NB. 1 - (whether the second item is unique, given the first)
2-#]/.~a;b    NB. 2 - (the number of piles the strings will sort themselves into)
+/(/:*\:)a;b  NB. is sorting them forwards the same as sorting them backwards?
A.|./:\:~a;b  NB. will sorting them forwards after sorting them backwards do anything?

The common subexpression here, a;b, is a linked to b. It puts a and b into boxes before appending them into a list. This is J's closest approximation to non-rectangular arrays: if you just tried to put the two strings in a 2-item list, the shorter would be padded with spaces on the right, which could result in you comparing 'a' and 'a ' as equal.

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

C#

I already posted the answer But just found a number of ways in C#

 var b = "abcdef";
 var a = "abcdef";
 // the best one is this.
 bool repace = a.Replace(b, "").Length < 1 && b.Replace(a, "").Length < 1;
 bool contsins = ("a" + a).Contains(b) && ("b" + b).Contains(a);
\$\endgroup\$
  • \$\begingroup\$ forget to mention considering string are not empty. \$\endgroup\$ – sm.abdullah Mar 13 '14 at 18:42
0
\$\begingroup\$

C#, pretty straightforward.

static bool equal(string s1, string s2)
{
    int i = 0;
    try { while (true) if (!isZero((int)s1[i] - (int)s2[i++])) return false; }
    catch { }
    return isEnd(s1, i) && isEnd(s2, i);
}

static bool isEnd(string s, int i)
{
    try { char c = s[i]; return false; }
    catch { }
    return true;
}

static bool isZero(int x)
{
    try { int y = 1 / x; return false; }
    catch { }
    return true;
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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