Range1 caesarCipher(Range1, Range2)(Range1 input, Range2 output, int shift) if (isInputRange!Range1 && isRandomAccessRange!Range2 && hasLength!Range2) { auto rotAb = lowercase.dtext.dup; // rotated alphabet bool changeLength; shift %= lowercase.length.to!int; // bring the shift within the length of the alphabet if (output.empty) changeLength = true; if (shift < 0) bringToFront(rotAb[0 .. $ + shift], rotAb[$ + shift .. $]); else bringToFront(rotAb[0 .. shift], rotAb[shift .. $]); foreach (i, c; input) { if (changeLength) ++output.length; if (isAlpha(c)) if (isUpper(c)) output[i] = toUpper(rotAb[lowercase.countUntil(toLower(c))]).to!ubyte; else output[i] = rotAb[lowercase.countUntil(c)].to!ubyte; else output[i] = c; } return cast(Range1) output; }