Create a function or program that takes a number as input, and outputs a string where ASCII-code points for the lower and upper case alphabet are substituted by their character equivalents.

  • The upper case alphabet use the code points: 65-90
  • The lower case alphabet use the code points: 97-122

If any adjacent digits in the input equals the code point of a letter, then that letter shall replace the digits in the output string.


  • The input will be a positive integer with between 1 and 99 digits
  • You can assume only valid input is given
  • You start substituting at the beginning of the integer (976 -> a6, not 9L)
  • The input can be on any suitable format (string representation is OK)
  • The output can be on any suitable format
  • Standard rules apply







Shortest code in bytes win!


The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

var QUESTION_ID=71735,OVERRIDE_USER=31516;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

  • 2
    \$\begingroup\$ "The input will be a positive integer with between 1 and 99 digits" In just about any programming language I know, it'll be a string with between 1 and 99 digits, as even a 64-bit int only holds up to 19 decimal digits... \$\endgroup\$ Commented Feb 11, 2016 at 17:41
  • 3
    \$\begingroup\$ @T.J.Crowder I assume he meant integer in the mathematical sense, not the data type. \$\endgroup\$
    – Dennis
    Commented Feb 11, 2016 at 17:59
  • 1
    \$\begingroup\$ @T.J.Crowder valid point :-) Although, if I'm not mistaken, 1e99 is technically still an integer. long int isn't enough, you need super long int. \$\endgroup\$ Commented Feb 11, 2016 at 18:04
  • 2
    \$\begingroup\$ @StewieGriffin: Hah! :-) I'm sure there's a language somewhere with such a thing. \$\endgroup\$ Commented Feb 11, 2016 at 18:05

14 Answers 14


Perl, 39 38 bytes

(1 byte added for the -p flag.)

s/                           /          replace...
  @{[                      ]}           this string, treated as a regex:
     join"|",65..90,97..122             65|66|67|68|...|121|122
                                   /ge  ...with this string, eval()'d:
                                 $&     the entirety of the last match
                              chr       convert to char from ASCII code

Right Tool for the Job™.

The explanation is outdated after one small optimization (thanks dev-null!) that makes it a single byte shorter (but a bit less elegant): the $" variable represents what to join on when interpolating an arrray into a string, so setting $"="|" removes the need for join.


llama@llama:~$ perl -pe '$"="|";s/@{[65..90,97..122]}/chr$&/ge' 
  • \$\begingroup\$ I guess you can save a single byte by setting $"="|" instead of join? \$\endgroup\$ Commented Feb 11, 2016 at 23:09
  • \$\begingroup\$ eg. $"="|";s/@{[65..90,97..122]}/chr$&/ge \$\endgroup\$ Commented Feb 11, 2016 at 23:17
  • \$\begingroup\$ @dev-null That does work, thanks! \$\endgroup\$
    – Doorknob
    Commented Feb 12, 2016 at 14:24

Javascript, 80 bytes


See regex in action here: https://regex101.com/r/iX8bJ2/1


document.body.innerHTML = '<pre>' +
    "f('1234567')\n" + f('1234567') + '\n\n' +
    "f('3456789')\n" + f('3456789') + '\n\n' +
    "f('9865432')\n" + f('9865432') + '\n\n' +
    "f('6566676869707172737475767778798081828384858687888990')\n" + f('6566676869707172737475767778798081828384858687888990') + '\n\n' +
    "f('6711110010100071111108102')\n" + f('6711110010100071111108102') +

Just for curiosity, one thing I learned here:

I can't change x=>String.fromCharCode(x) to String.fromCharCode because ...


CJam, 22 bytes


Try it online!


Simply replacing all occurrences of digit groups with the corresponding letters (in whatever order we may choose) will fail to comply with the left-to-right rule.

Instead, we can generate all prefixes of the input string, and attempt to make all possible substitutions while we're generating them. Since no code point is contained in another code point, the order of these attempts is not important.

For example:


6     -> 6
67    -> C
 C4   -> C4
 C46  -> C46
 C467 -> C4B


How it works

q                       Read all input from STDIN.
 {                  }*  Fold; push the first character, and for each subsequent
                        character, push it and do the following:
  +                       Append the character to the string on the stack.
   '[,_el^                Push the string of all ASCII letters.
                          See: http://codegolf.stackexchange.com/a/54348
          {       }/      For each ASCII letter:
           _                Push a copy of the letter.
            i               Convert to integer, i.e., compute its code point.
             s              Cast to string.
              @\            Rotate and swap.
                /           Split the modified input characters at occurrences (at
                            most one) of the string repr. of the code point.
                 *          Join, separating by the corresponding letter.

PHP, 110 102 101 68 67 bytes

Pretty hard challenge. This is the best I could come up with. This is a completely new version.


Run like this:

php -r 'for($i=64;123>$i+=$i-90?1:7;)$t[$i]=chr($i)?><?=strtr($argv[1],$t);' 6711110010100071111108102;echo
> Code000Golf
  • Saved 8 bytes by using ctype_alpha instead of preg_match, thx to manatwork
  • Saved 1 byte by prepending 0 to the string instead of checking non-empty string: when the last character of the input is a 0, the substring I'm taking would be "0", which is falsy, whereas "00" is truthy, so it won't skip printing the last 0.
  • Saved a massive 33 bytes by using strtr after building an array with conversion pairs
  • Saved a byte by using short print tag
  • 1
    \$\begingroup\$ Yo will have to change the regular expression to #[A-Z]#i as the current one will happily allow “92” to be transformed in “\”. Or try ctype_alpha() instead of preg_match(). So far seems to work. \$\endgroup\$
    – manatwork
    Commented Feb 11, 2016 at 14:22
  • \$\begingroup\$ "0", which is falsy, whereas "00" is truthy Good going, PHP. \$\endgroup\$
    – cat
    Commented Mar 30, 2016 at 22:20

Jolf, 18 16 bytes

Try it here! I knew that upperLower function would be useful someday! Replace ó with ΢, or just use the interpreter link. This is encoded in ISO 8859-7.

      pw           upper and lower
        pu         of the uppercase alphabet
     G    E        split by nothing (E = "")
    Μ      dóH     map each char to its numeric counterpart
  La               regex alternate array (e.g. La[1,2,3] => "1|2|3")
ρi            ΅A   replace input with the character code of the match (΅ is string lambda)

Python 3, 211 189 188 bytes

def f(c,i=0,n=""):
 while i<len(c):a=1;x=int(c[i:i+2]);a=2 if 64<x<91 or 96<x<100 else a;x=int(c[i:i+3]) if a<2 else x;a=3 if 99<x<123 else a;x=chr(x) if a>1 else c[i];n+=x;i+=a
 return n
  • Saved 23 bytes by replacing \n with ; thanks to Dennis


enter image description here

  • 1
    \$\begingroup\$ If you use ; instead of line breaks, you can put the entire while loop on a single line. Also, the first line can become def f(c,i=0,n=""):. \$\endgroup\$
    – Dennis
    Commented Feb 11, 2016 at 18:03
  • 1
    \$\begingroup\$ a=1;a=2 if 64<x<91 or 96<x<100 else a -> a=1+(64<x<91or 96<x<100) etc \$\endgroup\$
    – seequ
    Commented Feb 11, 2016 at 20:26

Vyxal, 10 9 bytes


Try it Online! Link includes test cases.

Port of @KevinCruijssen's 05AB1E answer.
-1 thanks to @KevinCruijssen


JkBC:CV)R  # Implicit input
       )R  # Reduce by:
J          #  Append to the string
 kB        #  Push constant [A-Za-z]
   C       #  Convert to codepoints
    :C     #  Duplicate and convert back
      V    #  Replace codepoints with characters
           # Implicit output
  • \$\begingroup\$ rt can be R. 05AB1E lacks a reduce-by with body builtin, which is why I've used a cumulative reduce with last combination, but Vyxal doesn't have that limitation. \$\endgroup\$ Commented Apr 5, 2023 at 17:08
  • \$\begingroup\$ @KevinCruijssen thanks, updated \$\endgroup\$
    – The Thonnu
    Commented Apr 5, 2023 at 17:11

Pyth, 20 18 bytes


Same algorithm as @Dennis. It's a lot easier to code in Pyth on my phone than in Jelly.

                implicit: z=input
.U              Reduce the following lambda b, Z over z
                b is the string being built; z is the next char
   u                Reduce the following lambda G,H over +bZ
                    G is the string, H is the next letter to match
     :                  Replace
       G                in G
       ` C H            the char code of H
       H                with H
     s rB            where H takes on values:
          G              the lowercase alphabet (that's the global value of G)
          1              concatenated to its uppercased self.

Thanks @isaacg

Try it here.

  • \$\begingroup\$ You just can't stay off this site on your phone, can you...? \$\endgroup\$ Commented Feb 11, 2016 at 22:41
  • 1
    \$\begingroup\$ Especially when I have the luxury of coding in all printable ASCII :D \$\endgroup\$
    – lirtosiast
    Commented Feb 11, 2016 at 22:42
  • 1
    \$\begingroup\$ That is true, probably nice to take a break from all that jelly... You know, a balanced diet ;) \$\endgroup\$ Commented Feb 11, 2016 at 22:43

05AB1E, 12 11 bytes


Try it online or verify all test cases or see a step-by-step reduction with just the first 9 bytes.


Å»         # Cumulative left reduce the (implicit) input-string by:
  «        #  Append the current character to the string
   žn      #  Push the builtin "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
     Ç     #  Convert it to a list of integer codepoints
      D    #  Duplicate this list
       ç   #  Convert each integer to its character again
           #  (so it's a list of the characters, instead of a string)
        :  #  Replace all integers with these characters (at the same indices)
           #  (would only replace 0 or 1 time)
}          # After the cumulative reduce-by is done:
 θ         # Pop the list, and only leave the last string
           # (after which it is output implicitly as result)

Ruby -p, 50 45 bytes

-5 bytes thanks to manatwork


Attempt This Online!

  • \$\begingroup\$ You can use * instead of .join: “array * string_separator → new_string (…) When String argument string_separator is given, equivalent to array.join(string_separator)”. \$\endgroup\$
    – manatwork
    Commented Oct 18, 2022 at 21:41
  • \$\begingroup\$ @manatwork Ah, of course. Not sure how I missed that. Thanks! \$\endgroup\$
    – Jordan
    Commented Oct 18, 2022 at 21:42

Java (JDK), 164 169 bytes

-5 bytes thanks to @KevinCruijssen !

I tried without regexp, and it was surprisingly tricky to handle all the possibilities :')

I'm seven years late to the party, but nice challenge anyway!

s->{var r="";for(int i=0,j,a,m=s.length();i<m;r+=a>64&a<91|a>96&a<123?(char)(a+0*(i=j)):s.charAt(i++))for(j=i,a=0;j<m&&(a=a*10+s.charAt(j++)-48)>0&a<13;);return r;}

Try it online!

  • 1
    \$\begingroup\$ j=i+(a=0) can be j=i,a=0 for -2 bytes, and String r=""; can be var r=""; in JDK 10+ for another -3 bytes: try it online. \$\endgroup\$ Commented Apr 5, 2023 at 17:01
  • 1
    \$\begingroup\$ @KevinCruijssen Nice! I didn't know the trick about the "," :o And i wasn't fond of using Java>8 because of the computer i use, but i can't ignore your optimization ;) My answer has been updated \$\endgroup\$
    – Fhuvi
    Commented Apr 6, 2023 at 8:57

Python 3, 95 bytes

lambda x:re.sub("6[5-9]|[7-8]\d|90|9[7-9]|1[01]\d|12[0-2]",lambda r:chr(int(r[0])),x)
import re

Assuming we can take in strings, otherwise this would be 100 bytes.

Try it online!


Io, 228 bytes

As for these warnings... let's just ignore them.

s :=method(H,r(H slice(0,1),H slice(1)))
r :=method(H,T,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"foreach(i,H=H asMutable replaceSeq(i asString,i asCharacter))if(T=="",return H)r(list(H,T slice(0,1))join,T slice(1)))

Try it online!


PowerShell, 51 bytes


Try it online!


  • replace by RegExp 65|66|67|68|...|121|122
  • replace to result of {[char]+"$_"}:

        $_   object with matched string 
       "$_"  matched string 
      +"$_"  convert the string to int

    [char]+"$_" convert the int to char


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.