Not really a one liner but still shorter than your original code and more understandable than the other answer:
static string Rot13(string input)
{
if(input == null)
return null;
Tuple<int, int>[] ranges = { Tuple.Create(65, 90), Tuple.Create(97, 122) };
var chars = input.Select(x =>
{
var range = ranges.SingleOrDefault(y => x >= y.Item1 && x <= y.Item2);
if(range == null)
return x;
return (char)((x - range.Item1 + 13) % 26) + range.Item1;
});
return string.Concat(chars);
}
Another version that even better expresses what happens in ROT13 is this:
static string Rot13(string input)
{
var lowerCase = Enumerable.Range('a', 26).Select(x => (char)x).ToArray();
var upperCase = Enumerable.Range('A', 26).Select(x => (char)x).ToArray();
var mapItems = new[]
{
lowerCase.Zip(lowerCase.Skip(13).Concat(lowerCase.Take(13)), (k, v) => Tuple.Create(k, v)),
upperCase.Zip(upperCase.Skip(13).Concat(upperCase.Take(13)), (k, v) => Tuple.Create(k, v))
};
var map = mapItems.SelectMany(x => x).ToDictionary(x => x.Item1, x => x.Item2);
return new string(input.Select(x => Map(map, x)).ToArray());
}
static char Map(Dictionary<char, char> map, char c)
{
char result;
if(!map.TryGetValue(c, out result))
return c;
return result;
}