Where is my implementation of rot13 in JavaScript going wrong?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
ROT13 shifts each letter by 13 positions in the alphabet, wrapping around from Z back to A. Common bugs in JavaScript implementations include not handling uppercase and lowercase separately, applying the shift to non-alphabetic characters (digits, punctuation), using incorrect character code ranges, and off-by-one errors in the wrapping logic. A correct implementation processes only A-Z and a-z while passing everything else through unchanged.
Correct Implementation
The key formula: ((charCode - base + 13) % 26) + base
- Subtract
baseto get 0-25 - Add 13
- Modulo 26 to wrap around
- Add
baseback to get the ASCII code
Bug 1: Not Preserving Case
Fix: Detect the case and use the appropriate base (65 for uppercase, 97 for lowercase):
Bug 2: Transforming Non-Alphabetic Characters
Fix: Check if the character is a letter before shifting:
Bug 3: Wrong Wrapping Logic
Without % 26, letters past M/m overflow into non-letter ASCII ranges. X (88) + 13 = 101 = e (wrong, should be K).
Bug 4: Off-by-One in Range Check
Use <= for inclusive ranges: code >= 65 && code <= 90.
Bug 5: Using charCodeAt Without Arguments
Alternative: Lookup Table
For clarity and performance, use a precomputed mapping:
Testing Your Implementation
ROT13 is its own inverse. Applying it twice returns the original:
Other Cipher Variants
Common Pitfalls
- Hardcoding ASCII values wrong:
'A'is 65,'Z'is 90,'a'is 97,'z'is 122. Off-by-one in these constants breaks the entire cipher. - Forgetting modulo 26: Without
% 26, letters in the second half of the alphabet (N-Z) produce character codes outside the letter range. - Treating uppercase and lowercase identically: Using a single base (65 or 97) for both cases corrupts the output. Detect the case per character.
- Mutating non-letter characters: Digits, spaces, and punctuation must pass through unchanged. Only match
[a-zA-Z]. - Not testing round-trip: ROT13 applied twice must return the original string. If
rot13(rot13(x)) !== x, the implementation is wrong.
Summary
- ROT13 shifts letters by 13 positions:
((code - base + 13) % 26) + base - Use
% 26to wrap around the alphabet boundary - Handle uppercase (base 65) and lowercase (base 97) separately
- Pass non-alphabetic characters through unchanged
- ROT13 is its own inverse, meaning
rot13(rot13(text)) === text - Use
str.replace(/[a-zA-Z]/g, fn)for the cleanest implementation
Related reading
- Where to put static files such as CSS in a spring-boot project?
- Which browsers support script asyncasync /?
- Which characters are valid in CSS class names/selectors?
- Which ORM should I use for Node.js and MySQL?
- where is rabbitmq config file?
- Where is the Docker daemon log?
- Which Radio button in the group is checked?
- Which would be better for concurrent tasks on node.js? Fibers? Web-workers? or Threads?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.