Counting and spelling up

Write a program that takes as its input a string that outputs a string with the following properties.

• If a character in the string is an uppercase letter (ASCII 41-5A), then the character is replaced by a string containing every letter up to and including the original letter in upper case. For example, if the input string is I, then the output would be ABCDEFGHI.
• Similarly, if a character is a lowercase letter (ASCII 61-7A), then the character is replaced in the same way. i would be replaced by abcdefghi.
• If a character is a number (ASCII 30-39), then the character is replaced by every number starting from 0 and counting up to the number.
• If the input contains concatenated individual characters, then the replacement sequences are concatenated together.
• All other characters are printed without modification.

Sample inputs (separated by blank lines)

AbC123

pi=3.14159

Hello, World!


Sample outputs

AabABC010120123

abcdefghijklmnopabcdefghi=0123.0101234010123450123456789

ABCDEFGHabcdeabcdefghijklabcdefghijklabcdefghijklmno, ABCDEFGHIJKLMNOPQRSTUVWabcdefghijklmnoabcdefghijklmnopqrabcdefghijklabcd!


This is code golf, fellas. Standard rules apply. Shortest code in bytes wins.

To see the leaderboard, click "Show code snippet", scroll to the bottom and click "► Run code snippet". Snippet made by Optimizer.

/* Configuration */

var QUESTION_ID = 61940; // Obtain this from the url
// It will be like http://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 43444; // This should be the user ID of the challenge author.

/* App */

return "http://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

}

jQuery.ajax({
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
data.items.forEach(function(a) {
});
comment_page = 1;
}
});
}

jQuery.ajax({
method: "get",
dataType: "jsonp",
crossDomain: true,
success: function (data) {
data.items.forEach(function(c) {
if (c.owner.user_id === OVERRIDE_USER)
});
else process();
}
});
}

var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

function getAuthorName(a) {
return a.owner.display_name;
}

function process() {
var valid = [];

var body = a.body;
if(OVERRIDE_REG.test(c.body))
body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
});

var match = body.match(SCORE_REG);
if (match)
valid.push({
user: getAuthorName(a),
size: +match[2],
language: match[1],
});
else console.log(body);
});

valid.sort(function (a, b) {
var aB = a.size,
bB = b.size;
return aB - bB
});

var languages = {};
var place = 1;
var lastSize = null;
var lastPlace = 1;
valid.forEach(function (a) {
if (a.size != lastSize)
lastPlace = place;
lastSize = a.size;
++place;

.replace("{{NAME}}", a.user)
.replace("{{LANGUAGE}}", a.language)
.replace("{{SIZE}}", a.size)

var lang = a.language;
lang = jQuery('<a>'+lang+'</a>').text();

languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang, user: a.user, size: a.size, link: a.link};
});

var langs = [];
for (var lang in languages)
if (languages.hasOwnProperty(lang))
langs.push(languages[lang]);

langs.sort(function (a, b) {
if (a.lang_raw.toLowerCase() > b.lang_raw.toLowerCase()) return 1;
if (a.lang_raw.toLowerCase() < b.lang_raw.toLowerCase()) return -1;
return 0;
});

for (var i = 0; i < langs.length; ++i)
{
var language = jQuery("#language-template").html();
var lang = langs[i];
language = language.replace("{{LANGUAGE}}", lang.lang)
.replace("{{NAME}}", lang.user)
.replace("{{SIZE}}", lang.size)
language = jQuery(language);
jQuery("#languages").append(language);
}

}
body { text-align: left !important}

width: 290px;
float: left;
}

#language-list {
width: 290px;
float: left;
}

font-weight: bold;
}

table td {
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="language-list">
<h2>Shortest Solution by Language</h2>
<table class="language-list">
<tr><td>Language</td><td>User</td><td>Score</td></tr>
<tbody id="languages">

</tbody>
</table>
</div>
<tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>

</tbody>
</table>
</div>
<table style="display: none">
</tbody>
</table>
<table style="display: none">
<tbody id="language-template">
</tbody>
</table>

• Idea for a sequel: undo this transformation. – ETHproductions Oct 27 '15 at 18:56
• @ETHproductions Perhaps, though the way here seems better to me because it can take any input; what if in the reverse the input were Hello, World!? – Arcturus Oct 27 '15 at 18:58
• Do we have to support NUL (ascii 0x00) characters in the input string? – nimi Oct 27 '15 at 20:33
• @Eridan in such a case, the code should either print an error or, for a fun twist, perform the above transformation. I.e., f(f(input)) == input. I don't believe it is possible for any alphanumerical input to disobey this relation. – JArkinstall Oct 28 '15 at 1:46
• That is entirely true - I make the assumption that "if a string CAN BE the result of the transformation, reverse it. Otherwise, apply the transformation." - it's your challenge, you can specify any rules you choose so long as (a) they're consistent and (b) they are verifiable and don't require an entire new branch of mathematics to solve. Side note: Irradicating (b) would be interesting; you never know when someone will accidently revolutionise computer science by coming up with a polynomial time algorithm for an NP problem - which is actually reasonable on here, so long as it saves 4 bytes. – JArkinstall Oct 28 '15 at 2:18

Pyth, 19 bytes

sXzsJ+rBG1jkUTs._MJ


Try it online: Demonstration or Test Suite

Explanation

sXzsJ+rBG1jkUTs._MJ
rBG1            the list ["abc...xyz", "ABC...XYZ"]
+    jkUT        appends the string "0123456789"
J                 save this list of 3 strings in J
sJ                 join the strings in J
._MJ   create all prefixes of the strings in J
s       and combine them to one list
XzsJ         s._MJ   translate the input string, chars from sJ
get translated to the correct prefix,
chars that don't appear in sJ don't get translated
s                     join all resulting translation strings


Python 2.7, 10098 96 bytes

a=[]
for c in raw_input():d=ord(c);a+=range(max(d&96|1,48),d)*c.isalnum()+[d]
print bytearray(a)


TeaScript, 24 bytes 2628

TeaScript is JavaScript for golfing

xl(#(i=lN()1)h(ii(l)+1))


Pretty short

Try it online

Explanation

x.l(#            // Loops through each character of the string

(i=l.N()1)  // Determines whether a character is alphanumeric
// Will return A-Z, a-z or 0-9 depending on result
// Assigns to variable i

.h(         // Get characters up to...
i.i      // where the character is in "i"
) + 1       // Increased by one
)


Ruby, 13787827667 55 bytes

Ungolfed, but you can see the pattern.

$><<gets.gsub(/[a-z0-9]/i){[*" 0Aa"[$&.ord/32]..$&]*""}  Edit: golfed down to only one regex. Edit 2: had a lot of extra spaces. Edit 3: Thanks to manatwork for golfing 12 bytes! • $><<gets.gsub(/[a-z0-9]/i){[*" 0Aa"[$&.ord/32]..$&]*""} – manatwork Oct 28 '15 at 9:21
• @manatwork Damn that's clever! – Peter Lenkefi Oct 28 '15 at 10:33

Python 2, 145140133103 102 Bytes

A not-so-sleek anonymous function using list comprehension. I feel like the logic should be much shorter, I'll try and figure something out.

lambda k:''.join([c,map(chr,range(48+17*(c>'@')+32*(c>''),ord(c)+1))[2::5]][c.isalnum()]for c in k)


Should be given a name to be used, i.e. f=...

• @Mego Oh, haha! No worries :) – Kade Oct 27 '15 at 19:50

c#(a:o:r)|c<a||c>o=c#r|1<2=[a..c]
c#_=[c]
f=((#"AZaz09")=<<)


Usage example: f "pi=3.14159" -> "abcdefghijklmnopabcdefghi=0123.0101234010123450123456789"

How it works: copy every char c in the input string unless c is in-between any of A/Z, a/z or 0/9 and if so take the list of [<first char in pair> ... <c>].

Edit: @Zgarb saved many many bytes. Thanks!

• I think you can define c#_=[c] and skip t entirely. – Zgarb Oct 27 '15 at 20:54
• @Zgarb: Yes indeed and then s is also superfluous. Thanks a lot! – nimi Oct 27 '15 at 21:01

JavaScript (ES6), 143 138 bytes

Uses string comparisons to test which characters to use.

s=>s.replace(/[A-Z0-9]/gi,c=>(a=btoaÓ]·ã»óÖq×£Y§¢«²Û¯Ã³,(c>'Z'?a:a.toUpperCase()).split.filter(x=>x<=c&(x>'9'|c<'A')).join))


Online demo. Tested in Firefox and Chrome.

Edit: Saved 5 bytes by replacing a='0123456789abcdefghijklmnopqrstuvwxyz' with

a=btoaÓ]·ã»óÖq×£Y§¢«²Û¯Ã³


PHP, 146 bytes

Golfed

function f($n,&$l){for(;$c=$n[$r],$b=0,$d=ord($c);$r++,$b?:$l.=$c)foreach([58=>48,91=>65,123=>97] as $m=>$i)while($d<$m&&$d>=$i)$b=$l.=chr($i++);}  Revision 1: put ord ranges directly into foreach. incremented ord range maxes and changed $d<=$m to $d<$m. using for to iterate chars instead of foreach and str_split. Removed all {} by moving code into for function f($input,&$output){ foreach (str_split($input) as $char){$ord = ord($char);$ords = [57=>48,90=>65,122=>97];
$b = 0; foreach ($ords as $max=>$min){
while ($ord<=$max&&$ord>=$min){
$b =$max;
$output .= chr($min);
$min++; } }$b ?: $output.=$char;
}
};

$output = NULL;$input = "pi=3.141592";
f($input,$output);
echo $output;  Explanation: split string into array. If ascii value falls into a range (for a-z,A-Z,0-9), then increment a counter from the min of the range to the char's ascii value, appending each value until you reach the char's ascii value. I passed in &$var so output is done by reference rather than a return

• There is no need for variable $z to hold the array of ranges, you can put the array literal directly in foreach. – manatwork Oct 28 '15 at 17:29 • Tried to use range()? pastebin.com/k2tqFEgD – manatwork Oct 28 '15 at 17:48 • @manatwork, I changed from declaring $z and made some other changes. range() would probably be better. I might try something with range later. – Reed Oct 28 '15 at 18:16
• Using range, I got function f($n,&$l){$o=['a'=>'z','A'=>'Z','0'=>'9'];foreach(str_split($n) as $c){$b=0;foreach($o as$m=>$x)!($c>$m&&$c<=$x)?:$b=$l.=implode(range($m,$c));$b?:$l.=$c;}}, which was 166. – Reed Oct 29 '15 at 1:11
• Yes, after your rewrite to 146 characters using range() is less beneficial. But that 166 is too long even so: the $o for the array literal is back, there are extra spaces around as keywords, join() is alias for implode(). (Checked the pastebin code I linked earlier? Shows another possibility to store the range endpoints.) Regarding your 146 characters solution, you can move the assignment to$c inside the ord() call: $d=ord($c=$n[$r]). – manatwork Oct 29 '15 at 9:00

Python, 143 bytes

lambda s:''.join(map(chr,sum(map(lambda a,r=range:r(65,a+1)if 64<a<97else r(97,a+1)if 96<a<123else r(48,a+1)if 47<a<58else[a],map(ord,s)),[])))


Try it online

• You could use z=range to save 4 bytes. – Arcturus Oct 27 '15 at 19:19
• Pretty sure that you can replace the double space indents with a single tab, which would save you a few bytes – Nic Hartley Oct 27 '15 at 19:25

Perl 6, 101 bytes

Here is a first pass at it:

sub MAIN($_ is copy){ s:g/<[0..9]>/{(0..$/).join}/;
s:g/<[a..z]>/{('a'..~$/).join}/; s:g/<[A..Z]>/{('A'..~$/).join}/;
.say
}

sub MAIN($_ is copy){s:g/<[0..9]>/{(0..$/).join}/;s:g/<[a..z]>/{('a'..~$/).join}/;s:g/<[A..Z]>/{('A'..~$/).join}/;.say}


119

Using .trans on $_to remove is copy. sub MAIN($_){
.trans(
/\d/       => {(0..$/).join}, /<[a..z]>/ => {('a'..~$/).join},
/<[A..Z]>/ => {('A'..~$/).join} ).say }  sub MAIN($_){.trans(/\d/=>{(0..$/).join},/<[a..z]>/=>{('a'..~$/).join},/<[A..Z]>/=>{('A'..~$/).join}).say}  106 Act on @*ARGS directly instead of defining a MAIN sub. (otherwise identical to previous example) @*ARGS[0].trans(/\d/=>{(0..$/).join},/<[a..z]>/=>{('a'..~$/).join},/<[A..Z]>/=>{('A'..~$/).join}).say


101

Scala, 111 91 bytes

val f=(_:String).flatMap(x=>if(x.isDigit)('0'to x)else if(x.isUpper)('A'to x)else('a'to x))

• This fails for pi=3.14159. Could the solution be val f=(_:String).flatMap(x:String=>if(x.isDigit)('0'to x)else if(x.isUpper)('A'to x)else if(x.isLower)('a'to x)else x.toString) for a whopping 128 characters? – Leonardo Oct 28 '15 at 11:28

Julia, 1029890 84 bytes

s->join([(i=Int(c);join(map(Char,(64<c<91?65:96<c<123?97:47<c<58?48:i):i)))for c=s])


This creates an unnamed function that accepts a string and returns a string.

Ungolfed:

function f(s::AbstractString)
# For each character in the input, get the codepoint and construct
# a range of codepoints from the appropriate starting character to
# the current character, convert these to characters, and join them
# into a string
x = [(i = Int(c);
join(map(Char, (isupper(c) ? 65 :
islower(c) ? 97 :
isdigit(c) ? 48 : i):i))
) for c in s]

# Join the array of strings into a single string
return join(x)
end


PowerShell, 155 Bytes

($args-split''|%{$b=$_;switch([int][char]$_){{$_-in(65..90)}{[char[]](65..$_)}{$_-in(97..122)}{[char[]](97..$_)}{$_-in(48..57)}{0..$b}default{$b}}})-join''  Technically a one-liner, and PowerShell is all about those ;-) Splits the input, pipes that into a ForEach-Object loop, switches on the integer value of the cast character, then generates new char[] of the appropriate ranges. Note that we have to spend bytes to set a temp variable $b because the act of casting the input $_ in the switch statement means that we can't just keep using $_ or we'll get funky output.

EDIT - I should point out that this will toss off errors since the first object being fed into %{...} is a null object. Since STDERR is ignored by default, this shouldn't be an issue. If it's a problem, change the first bit to be ($args-split''-ne''|... to eliminate the null object. JavaScript (ES6), 340258273 271 bytes a=s=>{s=s.split;Q=x=>x.toUpperCase();A="ABCDEFGHIJKLMNOPQRSTUVWXYZ";D="0123456789";f="";for(i=0;i<s.length;i++){j=s[i];c="to"+(Q(j)==j?"Upper":"Lower")+"Case";j=Q(j);if(q=A.search(j)+1)f+=g=A.slice(0,q)[c]();else if(q=D.search(j)+1)f+=g=D.slice(0,q);else f+=j}return f}  • You can use a template string  for split instead of ("") and f=i="" in the for loop. You might be able to save a few more bytes. – intrepidcoder Oct 27 '15 at 21:07 • @intrepidcoder The first would work. I'm checking on the second. – Conor O'Brien Oct 27 '15 at 21:35 C (269 bytes) (line break added for clarity) #include<stdio.h> #define F(x,y,z)if(c>=T[0][x]&&c<=T[1][y]){z} #define L(x,y)for(i=0;i<x;++i){y} main(){int c,i,n;char o,*T[]={"0Aa","9Zz"};while((c=getchar())!=EOF) {F(0,2,L(3,F(i,i,o=T[0][i],n=++c-o;L(n,putchar(o++));break;))else putchar(c);)}}  Ungolfed #include<stdio.h> int main(void) { int c, i, n; char output; char *char_table[] = {"0Aa", "9Zz"}; while ((c = getchar()) != EOF) { if (c < '0' || c > 'z') { putchar(c); } else { for (i = 0; i < 3; ++i) { if (c >= char_table[0][i] && c <= char_table[1][i]) { output = char_table[0][1]; n = c - output; break; } } for (i = 0; i <= n; ++i) { putchar(output); ++output; } } } return(0); }  Perl 5, 6661 (51 Bytes + 1) 52 Combining regexes with conditional operators worked out nice in this case. With a join Using map to combine the ranges into an array. say map{(/\d/?0:/[A-Z]/?A:/[a-z]/?a:$_)..$_}split//  Test $ echo "A0C1.a3c_2!" |perl -M5.010 -n count_and_spell_up.pl
A0ABC01.a0123abc_012!


Explanation

say                # print output
map{             # loop through the array that's at the end of the other mustache.
# outputs an array.
(
/\d/?0            # if $_ is a digit then 0 :/[A-Z]/?A # else, if it's an uppercase character then A :/[a-z]/?a # else, if it's a lowercase character then a :$_        # else the current character
)..$_ # generate a sequenced string of characters # that ends with the magic variable$_
# ($_ is currently a character from the array) }split// # split the magic variable$_ (currently the input string)
# to an array of characters


JavaScript (ES7), 125 bytes

There were already two JS answers focusing on encoding the strings, so I decided to go for a more algorithmic approach using String.fromCharCode():

x=>x.replace(/[^\W_]/g,z=>(c=z.charCodeAt(),f=c<65?48:c<97?65:97,String.fromCharCode(...[for(i of Array(c-f).keys())i+f])+z))


A bonus of using this method is that it takes any amount of char codes, so joining the list is not necessary. This turned out shorter than any other technique, so I'm happy with the result.

MUMPS, 131 bytes

u(l,h) i l'>a,a'>h f j=l:1:a s o=o_$C(j),f=0 q t(s) f i=1:1:$L(s) s a=$A(s,i),f=1 d u(48,57),u(65,90),u(97,122) s:f o=o_$C(a)
q o


I did manage to save a good few bytes here thanks to MUMPS's dynamic scoping. Here's a roughly-equivalent ungolfed version, which I sure would love to syntax highlight, if only support for the MUMPS Prettify module were available.

convert(str) ;
new asciiCode,flag,i,output
for i=1:1:$LENGTH(str) do . set asciiCode=$ASCII(str,i)
. set flag=1
. do helper(48,57)
. do helper(65,90)
. do helper(97,122)
. if 'flag do
. . set output=output_$CHAR(asciiCode) quit helper(low,high) ; if low'>asciiCode,asciiCode'>high do . for code=low:1:asciiCode do . . set output=output_$CHAR(code)
. . set flag=0
quit


Perl 6, 78 77 bytes

@*ARGS[0].trans(/\d/=>{[~] 0..$/},/<:L>/=>{[~] samecase("a",~$/)..~$/}).say  • I knew it could be shortened by combining the 'a'..'z' and 'A'..'Z' cases, I should have tried harder. – Brad Gilbert b2gills Nov 1 '15 at 18:00 • I recommend adding <!-- language-all: lang-perl6 --> just after ## Perl 6 so that it will highlight correctly. ( Change is already pending on this answer ) – Brad Gilbert b2gills Nov 1 '15 at 18:03 • You can switch {[~](0..$/)} to {[~] 0..$/} which will save one byte. – Brad Gilbert b2gills Nov 3 '15 at 18:36 Mathematica, 102 bytes FromCharacterCode@Flatten[Which[64<#<91,65,96<#<123,97,47<#<58,48,1>0,#]~Range~#&/@ToCharacterCode@#]&  Oh well... CJam, 32 31 bytes q_'[,_el^A,s+26/ff{_@#)<}:s\.e|  Try it online in the CJam interpreter. How it works q_ e# Push two copies of the user input. '[, e# Push the string of all ASCII characters up to Z. _el e# Push a copy and convert it to lowercase. ^ e# Perform symmetric difference this keeps only letters. A,s+ e# Append the string "0123456789". 26/ e# Split the result into chunks of length 26. ff{ e# For each character from input: For each chunk: _@ e# Copy the chunk and rotate the character on top of it. # e# Push the index of the character in the string (-1 for not found). )< e# Increment and keep that many characters from the left of the chunk. e# This pushes "" for index -1. } :s e# Flatten the resulting arrays of strings. e# The results will be empty strings iff the character wan't alphanumeric. \ e# Swap the result with the input string. .e| e# Perform vectorized logical OR.  Python 2, 135 117 bytes s='' for c in raw_input(): b=ord(c);e=b+1 if c.isalnum(): b=max(b&96,47)+1 for i in range(b,e):s+=chr(i) print s  PHP - 291 bytes Pass the string to GET["s"]. <?php$s=$_GET["s"];$m="array_map";echo implode($m(function($v){$i="in_array";$l="implode";$r="range";global$m;$a=ord($v);if($i($a,$r(48,57)))$v=$l($m("chr",$r(48,$a)));if($i($a,$r(65,90)))$v=$l($m("chr",$r(65,$a)));if($i($a,$r(97,122)))$v=$l($m("chr",$r(97,$a)));return$v;},str_split($s)));


C#, 251201184157 154 Bytes

using System;class c{static void Main(string[] i){foreach(var c in i[0])for(var x=c>64&c<91?'A':c>96&c<123?'a':c>47&c<58?'0':c;x<=c;)Console.Write(x++);}}


edit: Strike! Shorter than PowerShell ;)

• can you do string[]i`? – Erik the Outgolfer Jun 15 '16 at 14:29