Caesar equivalence

CJam, 17 12 11 bytes

1 byte saved by Dennis.

ll.m26f%)-!

Test it here.

Expects the first string to be lower case and the second to be upper case. Prints 1 for Caesar-equivalent strings and 0 otherwise.

Explanation

ll           e# Read two lines of input.
  .m         e# Take the differences of corresponding characters.
    26f%     e# Take the differences modulo 26.
        )-   e# Remove all copies of the last difference from the array. This will 
             e# yield an empty array if and only if all differences are the same.
          !  e# Logical NOT, which yields 1 for an empty array and 0 otherwise.

The reason we require the first string in lower case and the second in upper case is to ensure that the difference is always positive. Otherwise taking the modulo might return something negative and would not necessarily be unique, even for Caesar-equivalent strings.


Pyth, 9 bytes

}wm=.rzGG

The two strings are expected in lowercase, newline separated.

Demonstration.

How it works:

.r is Pyth's rotary translation function. It maps each element in the first argument from its first occurance in the second argument to the next entry in the second argument. In this, case, the second argument is G, the lowercase alphabet, so this is equivalent to a Caesar shift of 1.

Putting an = in front of the function makes it in-place. Thus, =.rzG assigns the Caesar shift of z by one to z. Note that z is initialized to the first line of input in Pyth.

This expression is used inside a map. m=.rzGG applies this transformation to z 26 times, once for each element of G, and saves the results in a list. This gives the list of all possible Caesar shifts of z.

Finally, }w checks whether the next line of input is in that list.


Python2, 68 67 70 69 Bytes

print len({(ord(y)-ord(x))%26for x,y in zip(*raw_input().split())})<2

Python3, 67 66 Bytes

print(len({(ord(y)-ord(x))%26for x,y in zip(*input().split())})<2)

It's a bit hard to ungolf, so just explaining the pieces:

  • zip(*raw_input().split()) takes the input, splits it into a list of two words, assuming words are separated by whitespace. After that each word is passed as a parameter of the the zip function, by use of * operator. The zip function will create a list of letter-pairs, for letters in the same position.
  • (ord(y)-ord(x))%26for x,y in ... This just transforms the list of 2 letters to an generator expression of the distances between those letters.
  • {...} reduces this expression to a set, essentially throwing out duplicates
  • len(...)<2 checks if there is only one item left in the set (or 0 for empty strings), which essentially means all letters had the same distance.
  • print outputs that value

Thanks to xnor for reminding me set(...) can be replaced with {...} and the space before for is not required. Also thanks to Josay for the <=1 to <2 optimization.