# Letters to numbers to letters (poorly)

Every now and again, I'll encounter a large string of alphabetical text encoded as numbers from 1-26. Before I knew that I could just google a translator online, I had to personally, painstakingly copy and paste the entirety of the encoded text into a text document and translate it myself.

Thankfully, I did know about find-and-replace features, which I used to search for all copies of each number and convert them to their corresponding characters. Only one problem... If you do this in numerical order, it will come out garbled.

This is because the single digit numbers used to encode a-i also appear as part of the remaining two digit numbers encoding j-z. For example, 26 should decode to z, but since both 2 and 6 are less than 26, we decode those first. 2 becomes b, and 6 becomes f, so 26 becomes bf.

Note also that for 10 and 20, there is no conversion for 0, so we end up with a0 and b0 respectively.

## Challenge

Given a string of alphabetical characters (abcdefghijklmnopqrstuvwxyz), output the result of converting to numbers and back again using the algorithm described above. You may assume input is all lowercase or all uppercase. This is , so shortest code in bytes wins.

Important: You may not zero index.

Full conversion list:

a: a
b: b
c: c
d: d
e: e
f: f
g: g
h: h
i: i
j: a0
k: aa
l: ab
m: ac
o: ae
p: af
q: ag
r: ah
s: ai
t: b0
u: ba
v: bb
w: bc
x: bd
y: be
z: bf


## Examples

xyzzy => bdbebfbfbe
caged => caged
jobat => a0aebab0
swagless => aibcagabeaiai

• sorry bout the sudden title change. Turns out im stutpid Jul 21 at 16:42
• Not really impacting the question, but if you don't do it in numerical order it will still come out garbled unless you have separated your numbers somehow. For instance if you go in reverse order you will replace 26 while these may actually have been a 2 and a separate 6. Jul 22 at 19:34

# Retina 0.8.2, 32 bytes

[j-s]
a$& [t-z] b$&
Tj-z0a-i0l


Try it online! Link includes test cases. Explanation:

[j-s]
a$& [t-z] b$&


Precede the letters j-z with an a or b as appropriate.

Tj-z0a-i0l


Translate them to 0 or a-i as appropriate. (l expands to a-z but only a-f get used as the replacement list gets truncated to the length of the translation list.)

# Vyxal, 8 bytes

øAṅ₄ɾkaĿ


Try it Online!

# JavaScript (Node.js), 70 bytes

s=>s.replace(r=/./g,c=>parseInt(c,36)-9).replace(r,i=>'0abcdefghi'[i])


Try it online!

# R, 75 bytes

\(s,[=gsub)chartr("j-z","0a-i0a-i","([j-s])"["a\\1","([t-z])"["b\\1",s]])

Attempt This Online!

Straightforward replacement.

### R, 84 81 bytes

Edit: -3 bytes thanks to @Dominic van Essen.

\(s)gsub("",0,intToUtf8(strtoi(unlist(strsplit(paste(utf8ToInt(s)-96),"")))+96))

Attempt This Online!

Going with the algorithm.

• as.double -> strtoi for the second one... Jul 22 at 11:53
• See here for a shorter approach: codegolf.stackexchange.com/a/250188/55372 Jul 22 at 14:25

# Charcoal, 13 bytes

⭆⭆Ｓ⊕⌕βι§⁺β0⊖ι


Try it online! Link is to verbose version of code. Explanation:

  Ｓ             Input string
⭆              Map over characters and join
⌕           Index of
ι         Current character
β          In lowercase alphabet
⊕            Incremented
⭆               Map over characters and join
β      Lowercase alphabet
⁺       Concatenated with
0     Literal string 0
§        Indexed by
ι   Current character
⊖    Decremented (auto-casts to integer)


# JavaScript (ES6), 71 bytes

s=>s.replace(/[j-z]/g,c=>"ab"[c>'s'|0]+"abcdefghi0"[parseInt(c,36)%10])


Try it online!

# Burlesque, 25 bytes

)**96?-imXX@azr@'0+]jsi\[


Try it online!

)**   # Map ord(a)
96?-  # Subtract 96 (get index into alphabet)
imXX  # Concat and separate by digit
@azr@ # Alphabet [a,b,..,z]
'0+]  # Prepend [0,a,b,..,z]
jsi   # Select indices
\[    # Concat


# Python 3, 79 bytes

lambda s:s.translate({n:'AB'[n>83]+'0ABCDEFGHI'[n%74%10]for n in range(74,91)})


Try it online!

s/./-96+ord$&/ge;y/1-9/a-i/  Try it online! # 05AB1E, 10 8 bytes A0ìDIkSè  I/O as lowercase list of characters. -2 bytes thanks to @CommandMaster Explanation: A # Push the lowercase alphabet 0ì # Prepend a leading "0" D # Duplicate it I # Push the input character-list k # Get the (0-based) index of each character in the "0abc...xyz" string S # Convert it to a flattened list of digits è # (0-based) index each into the "0abc...xyz" string # (after which the result is output implicitly)  If None is a valid output for 0, builtin .b could be used for an alternative 8-byter in the legacy version of 05AB1E, with uppercase character-lists as I/O: try it online. (The .b results in "@" in the new version of 05AB1E for 0: try it online.) • A0šDIkSè seems to work for 8 bytes? Jul 22 at 12:43 • @CommandMaster Ah, of course.. Why not just prepend instead of append so fixing the 0-based to 1-based indexing manually with >/< isn't necessary. It looks so simple now that I see it.. Thanks. Jul 22 at 13:28 # Pyth, 16 bytes sm@+G0tsdjkmhxGd  Try it online! # Husk, 14 bytes m!₁ṁod€₁ …"az0  Try it online! Inspired by Kevin Cruijssen's approach, although comes-out a bit longer in Husk... … # Fill-in the gaps with character ranges "az0 # in the string "az0" # (fill-in works both backwards & forwards, resulting in: # "abcde...vwxyzyxwv...edcba_^]\...43210") # = assign this as '₁' ṁo # Now, for each input letter €₁ # get the index of first occurence in ₁ (=index in alphabet) d # and split the decimal digits; m # Then, for each digit !₁ # retrieve the element in ₁ using modular 1-based indexing # (so zero retrieves the last element)  # Python 3.8 (pre-release), 76 bytes f=lambda s:s and'ba'[2-(q:=ord(s[0])%32)//10::2]+'0abcdefghi'[q%10]+f(s[1:])  Try it online! # R, 68 bytes \(x,y=utf8ToInt(x)-96)intToUtf8(rbind(y/10+96*(y>9),48--y%%10%%-58)) Attempt This Online! Calculates 2 decimal digits for each letter, and then calculates the corresponding codepoint values, setting unused values (leading zeros) to zero, which is not output by the intToUtf8 function. # R, 54 bytes \(x)chartr('1-9','a-i',Reduce(paste0,utf8ToInt(x)-96)) Attempt This Online! Port of Kjetil S's Perl answer. # C (GCC), 10188 87 bytes f(char*s){for(char*x;*s;)for(asprintf(&x,"%d",*s++-64);*x;)putchar(*x+(*x++^48?16:0));}  Attempt This Online! Prints to standard out. Uses asprintf, which is a GNU-specific function and may or may not require a definition in the header, so I don't know if it's okay. This is basically the first C function I've ever written, so there are almost certainly ways this can be improved. -13 bytes from @c-- by iterating one character at a time, removing parens, and changing the ternary -1 bytes from @ceilingcat by moving the char*x declaration into the for statement # Piet + ascii-piet, 129 bytes (5×27=135 codels) uqijsvudnbddt feussskiu L?q sa dttlvqfeumdctss?Lr????saa???????????????s Lkjftrqavqcefcnbftmnkss K ssvc  Try Piet online! Input the string in upper-case with the sentinel value @. Explanation Read char from input, subtract 64 and check if it is greater than 9. If c<=9: check if its check if it is greater than 0 (else terminate). Add 64, print char and start over. If c>9: duplicate, push 10 on stack, duplicate, roll, divide, print char, modulo and check if it is greater than 0. If c>0: print char (as above) and start over. If c=0: print number and start over. # Factor, 53 bytes [ 96 v-n [ >dec ] map-concat 48 v+n "" "0" replace ]  Needs modern Factor for >dec but here's a version that works on TIO for +1 byte: Try it online! # Batch, 432 Bytes SETLOCAL ENABLEDELAYEDEXPANSION&(CMD /U /C^"<NUL SET /P=abcdefghijklmnopqrstuvwxyz^"|FIND /V ""|FINDSTR /N "^")>a&(CMD /U /C^"<NUL SET /P=%s%^"|FIND /V "")>t&FOR /F %%Q in (t)DO (FOR /F "tokens=1-2 delims=:" %%A in ('FINDSTR /RC:"%%Q" a')DO (IF %%A GEQ 20 (SET /Ad=%%A+76&CMD /CEXIT !d:96=48!&<NUL SET /P=b!=exitcodeAscii!) else IF %%A GEQ 10 (SET /Ad=%%A+86&CMD /CEXIT !d:96=48!&<NUL SET /P=a!=exitcodeAscii!) else <NUL SET /P=%%B))  Assuming @ECHO OFF and passing it as CALL golf.bat swagless  produces aibcagabeaiai  This can probably not the best way, but I thought that this was a pretty cool way to do it. Ungolfed: (CMD /U /C^"<NUL SET /P=abcdefghijklmnopqrstuvwxyz^"|FIND /V ""|FINDSTR /N "^")>a (CMD /U /C^"<NUL SET /P=%1^"|FIND /V "")>t FOR /F %%Q in (t) DO ( FOR /F "tokens=1-2 delims=:" %%A in ('FINDSTR /RC:"%%Q" a') DO ( IF %%A GEQ 20 ( SET /Ad=%%A+76 CMD /CEXIT !d:96=48! <NUL SET /P=b!=exitcodeAscii! ) else IF %%A GEQ 10 ( SET /Ad=%%A+86 CMD /CEXIT !d:96=48! <NUL SET /P=a!=exitcodeAscii! ) else <NUL SET /P=%%B ) )  # Bash, 74 47 bytes sed "s/[j-s]/a&/g;s/[t-z]/b&/g"|tr j-z 0a-i0a-i  Try it online! -27 thanks to Neil's idea # first approach, 74 bytes sed "s/./\"'&\"/g"|xargs printf '%d-96\n'|bc|sed '/../s/./&\n/'|tr 1-9 a-j  Try it online! # lin, 41 bytes $a0,.+10t2/\"rev _"' , ,*10d tro


Try it here!

Decided to go for a different non-regex approach, which came out quite nicely. Turns out that tro surprisingly accepts an iterator of iterators, which saved quite a few bytes.

For testing purposes:

"jobat" ; outln
$a0,.+10t2/\"rev _"' , ,*10d tro  ## Explanation Prettified code: $a 0, dup 10t 2/\ ( rev _ ) ' , ,* 10d tro

• $a 0, alphabet with 0 in front as a • $a 0,.+ 10t duplicate and create 0abcdefghi
• 2/\ ( rev _ ) ' 2-digit pairs (00 0a 0b ... ig ih ii)
• , ,* 10d zip with a and remove first 10 pairs ([j a0] [k aa] [l ab] ... [x bd] [y be] [z bf])
• tro transliterate

# Lexurgy, 92 bytes

a:


Naive 1-1 substitution.

# C (GCC), 74 bytes

c;f(char*s){for(;c=*s++%96;putchar((c%10?:-48)+96))c>9&&putchar(c/10+96);}


Attempt This Online!

# Dyalog APL, 32 bytes

{(⎕A,'0')[27@(0∘=)⍎¨∊⍕¨⎕A⍳⍥⎕C⍵]}


Attempt This Online!

                       ⎕A⍳   ⍵  find each character's index in the alphabet
⍥⎕C   case insensitively (casefold both arguments first)
⍕¨         turn each number into string
∊           flatten nested array to get the individual digits
⍎¨            turn each digit back into a number
27@(0∘=)              turn 0s into 27s
[                    ] index into
⎕A                            the alphabet
,'0'                        with a 0 at the end at the 27th position