30
\$\begingroup\$

I'm pretty sure there's not a better way to do this but figured it couldn't hurt to ask.

I'm tired of typing out a='abcdefghijklmnopqrstuvwxyz'.

Cool languages have Range('a'..'z') or similar

What can we come up with with JS that's as short as possible??

for(i=97,a='';i<123;){a+=String.fromCharCode(i++)}

is longer than just the alphabet - but guarantees I don't screw up somewhere.

I'm hoping there's a nasty bit-shifty way to produce a-z in less than 50 characters.

I messed around with i=97;Array(26).map(x=>String.fromChar....i++

but it was always way longer by the time I joined then split the array(26) to be useable


Edit: I've gotten it down to

[...Array(26)].reduce(a=>a+String.fromCharCode(i++),'',i=97)

60 bytes

\$\endgroup\$
6
  • 11
    \$\begingroup\$ @muddyfish, LuisMendo: This is on-topic per meta. \$\endgroup\$
    – Doorknob
    Feb 9 '16 at 21:11
  • 1
    \$\begingroup\$ [...Array(26)].map((q,w)=>String.fromCharCode(w+97)) is 52 bytes and add another 7 for the .join`` \$\endgroup\$
    – andlrc
    Feb 9 '16 at 21:13
  • \$\begingroup\$ Related: stackoverflow.com/questions/3895478/… \$\endgroup\$ Feb 9 '16 at 21:19
  • \$\begingroup\$ @dev-null a='';i=97;[...Array(26)].map(b=>a+=String.fromCharCode(i++)) is 60 but takes care of the join how are you doing join in 7 without getting commas in the result? \$\endgroup\$ Feb 9 '16 at 21:19
  • 1
    \$\begingroup\$ @CharlieWynn [...Array(26)].map((q,w)=>String.fromCharCode(w+97)).join`` \$\endgroup\$
    – andlrc
    Feb 9 '16 at 21:23
16
\$\begingroup\$

Alternative to String.fromCharCode

... if you are happy with a lowercase only alphabet.

for(i=9,a='';++i<36;)a+=i.toString(36) // 38, cannot be used in an expression
[...Array(26)].map(_=>(++i).toString(36),i=9).join`` // 52 directly returnig the string desired
[...Array(26)].map(_=>a+=(++i).toString(36),a='',i=9) // 53 assign to a variable
(i=9,[for(_ of Array(26))(++i).toString(36)].join``) // 52 ES7 direct return
i=9,a='',[for(_ of Array(26))a+=(++i).toString(36)] // 51 ES7 assign to a variable
\$\endgroup\$
7
  • 1
    \$\begingroup\$ Oh dang, that is clever. So it's starting with 10, converting to base 36 and printing it? so a-z! \$\endgroup\$ Feb 10 '16 at 14:46
  • \$\begingroup\$ Are those a='' and i=9 arguments of map function call? Checked Array.prototype.map() on mdn and it doesn't look like map support such arguments.. \$\endgroup\$ Jan 22 '19 at 14:10
  • \$\begingroup\$ @JaySomedon those are argument for map function call, in a way, Javascript functions tipically don't care and discard parameters they do not expect. So I initialize a variable I need, while adding a parameter that is of no use for the called function \$\endgroup\$
    – edc65
    Jan 22 '19 at 15:35
  • \$\begingroup\$ @JaySomedon see also this answer and related comments codegolf.stackexchange.com/a/2684/21348 \$\endgroup\$
    – edc65
    Jan 22 '19 at 15:40
  • \$\begingroup\$ @edc65 aha I see! That's neat! So here, when javascript evaluates arguments like i=9 in map(), it actually creates a global variable i then assigns 9 to that? \$\endgroup\$ Jan 23 '19 at 7:42
15
\$\begingroup\$

Note: All of these techniques assign the alphabet string to variable a.


I am 99% certain that the shortest way to achieve this in JavaScript is indeed:

a="abcdefghijklmnopqrstuvwxyz" // 30 bytes

But there are several other interesting methods. You can use string compression:

a=btoa`i·?yø!?9%?z)ª»-ºü1`+'yz' // 31 bytes; each ? represents an unprintable

You can get the compressed string from atob`abcdefghijklmnopqrstuvwx`. The 'yz' must be added manually because if you compress the whole string, while the result is only 27 bytes, it will turn out as abcdefghijklmnopqrstuvwxyw==.

I believe the shortest way to do it programmatically is also the method you suggested:

for(i=97,a='';i<123;)a+=String.fromCharCode(i++) // 48 bytes

You can do it with ES6 features (template strings ``, spread operator ...) if you want:

a=[...Array(26)].map(_=>String.fromCharCode(i++),i=97).join`` // 61 bytes
a=[...Array(26)].map((_,i)=>String.fromCharCode(i+97)).join`` // also 61 bytes
a=[...Array(i=26)].map(_=>String.fromCharCode(++i+70)).join`` // again, 61 bytes

You can do one better with a variable instead of .join``:

[...Array(26)].map(_=>a+=String.fromCharCode(i++),i=97,a='') // all 60 bytes
[...Array(26)].map((_,i)=>a+=String.fromCharCode(i+97),a='')
[...Array(i=26)].map(_=>a+=String.fromCharCode(++i+70),a='')

Or ES7 with array comprehensions, which is another byte shorter:

a=[for(_ of Array(i=26))String.fromCharCode(++i+70)].join`` // 59 bytes

Creating the variable beforehand saves yet another byte:

a='',[for(_ of Array(i=26))a+=String.fromCharCode(++i+70)] // 58 bytes

Also, String.fromCharCode accepts multiple arguments and will automatically join them. So we can golf each ES6 version down to 57 bytes:

a=String.fromCharCode(...[...Array(26)].map(_=>i++,i=97)) // all 57 bytes
a=String.fromCharCode(...[...Array(26)].map((_,i)=>i+97))
a=String.fromCharCode(...[...Array(i=26)].map(_=>++i+70))

And the ES7 one down to 55:

a=String.fromCharCode(...[for(_ of Array(i=26))++i+70]) // 55 bytes

If you'd like to learn more about golfing ranges, check out this set of tips. There's also one about ES7's array comprehensions.

EDIT: As edc65 has pointed out, most of these become shorter using i.toString(36) instead of String.fromCharCode(i):

for(i=9,a='';++i<36;)a+=i.toString(36) // 38 bytes
a=[...Array(26)].map(_=>(++i).toString(36),i=9).join`` // 54 bytes
[...Array(26)].map(_=>a+=(++i).toString(36),i=9,a='') // 53 bytes
i=9,a=[for(_ of Array(26))(++i).toString(36)].join`` // 52 bytes
i=9,a='',[for(_ of Array(26))a+=(++i).toString(36)] // 51 bytes

I believe this one is the shortest possible that can be called as a function return value:

eval("for(i=9,a='';++i<36;)a+=i.toString(36)") // 46 bytes

It's three bytes shorter than manually returning it from a function:

x=>eval("for(i=9,a='';++i<36;)a+=i.toString(36)") // 49 bytes
x=>{for(i=9,a='';++i<36;)a+=i.toString(36);return a} // 52 bytes

Of course, x=>"abcdefghijklmnopqrstuvwxyz" still beats everything else.

\$\endgroup\$
8
  • \$\begingroup\$ I really like where this is going - just wish I could ES7 in chrome :( \$\endgroup\$ Feb 9 '16 at 21:42
  • 3
    \$\begingroup\$ @CharlieWynn Yes, it's a shame that not all browsers support all the latest features. But after all, Chrome wasn't built in a day... ;) \$\endgroup\$ Feb 9 '16 at 21:53
  • \$\begingroup\$ Most of these solution can be shortened using .toString instead of String,.fromCharCode. See my answer \$\endgroup\$
    – edc65
    Feb 9 '16 at 22:42
  • 1
    \$\begingroup\$ @CharlieWynn I think Chrome Beta now supports all of ES7 and all of ES6 except modules and tail call optimisation. \$\endgroup\$
    – gcampbell
    Jun 10 '16 at 10:28
  • \$\begingroup\$ Here's a 42-byter that can be called as a function return value: (f=(i=9)=>++i<36?i.toString(36)+f(i):'')() \$\endgroup\$ Jul 3 '17 at 23:45
7
\$\begingroup\$

Here's another approach, a 51 byte ES6 expression:

String.fromCharCode(...Array(123).keys()).slice(97)

50 bytes in upper case of course.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ For upper case: String.fromCharCode(...Array(91).keys()).slice(65) \$\endgroup\$
    – jpoppe
    Jan 31 '17 at 16:27
5
\$\begingroup\$
(36n**26n*351n/1225n-1n).toString(36)

37 bytes, as an expression. Uses the same base-36 method as many others, but further, obtaining all the letters from a single number. Requires BigInt support.

\$\endgroup\$
3
\$\begingroup\$

36 bytes, using a trick I just learned about (from this post: https://codegolf.stackexchange.com/a/176496/64538):

for(i=9;++i<36;)name+=i.toString(36)

window.name is an empty string by default.

Of course, this is even less practical than the 38-byte solution since it uses a longer variable name.

\$\endgroup\$
1
\$\begingroup\$

Using what may or may not be defined at global scope

39 bytes for object properties to array matching a-z

a=`${Object.keys(top)}`.match(/[a-z]/g)

48 bytes for an unsorted Set

a=new Set(`${Object.keys(top)}`.match(/[a-z]/g))

55 bytes for a sorted Set

a=new Set(`${Object.keys(top)}`.match(/[a-z]/g).sort())

67 bytes for a sorted string

a=[...new Set(`${Object.keys(top)}`.match(/[a-z]/g).sort())].join``
\$\endgroup\$
1
  • \$\begingroup\$ `${Object.keys(top)}`.match(/([a-z])(?!.*\1)/g).sort().join`` is still shorter. \$\endgroup\$
    – quicVO
    Mar 23 at 17:57

This site is temporarily in read only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .