Alphabetize Integers

For a given set of numbers, put them in alphabetical order when they are spelled out (i.e. 1: one, 2: two, 90: ninety, 19: nineteen). Your code should work for the range [-999999, 999999]. Output must have a delimiter between numbers. A space will work, as will a space and a comma as shown in the examples below. Input can be an array of integers, a string of delimited numbers, or however you see fit. All integers are assumed to be unique.

Numbers are not hyphenated for the purposes of this challenge and spaces are alphabetized before any other characters. Negative numbers are assumed to be expressed by using the word minus. For example, four would precede four thousand and the number -40 would be sorted using the string minus forty. Assume all numbers will be solely comprised of number words and no conjunctions (e.g. use two thousand forty two instead of two thousand and forty two).

Test Cases

Single Digit Integers:


1, 2, 3, 4, 5


5, 4, 1, 3, 2

Multiple Digit Integers:


-1002, 5, 435012, 4, 23, 81, 82


81, 82, 5, 4, 435012, -1002, 23

Spaces between words, no hyphens, commas or "and":


6, 16, 60, 64, 600, 6000, 60000, 60004, 60008, 60204, 60804


6, 600, 6000, 16, 60, 64, 60000, 60008, 60804, 60004, 60204

Remember, this is , so the code with the fewest bytes wins. No loopholes allowed!

  • \$\begingroup\$ Here is the link to the relevant sandbox post. \$\endgroup\$
    – wubs
    Commented Dec 1, 2016 at 20:23
  • \$\begingroup\$ Will the input ever contain more than one of a single integer? \$\endgroup\$ Commented Dec 1, 2016 at 20:42
  • \$\begingroup\$ @ETHproductions No, it will not. I'll specify that in the question. \$\endgroup\$
    – wubs
    Commented Dec 1, 2016 at 20:43
  • 8
    \$\begingroup\$ Welcome to PPCG. Nice avatar. :D Nice first question. \$\endgroup\$ Commented Dec 1, 2016 at 20:50
  • \$\begingroup\$ @TimmyD Thanks! I'm looking forward to PowerShell-ing everything I can around here. \$\endgroup\$
    – wubs
    Commented Dec 1, 2016 at 21:05

7 Answers 7


Inform 7, 214 201 118 bytes

Inform 7 is an absolutely terrible language for golfing, so I wanted to give it a chance here.

Indentation should use tab (\t) characters, but HTML doesn't like those. Conversely, Inform doesn't like spaces for indentation, so you'll have to replace the spaces with tabs if you copy-paste the code from here to test it. Or just copy-paste from the Markdown source instead.


To X:
    repeat through Table 1:
        now Q entry is "[R entry in words]";
    sort Table 1 in Q order;
    say "[R in Table 1]".

Input should be an Inform table, like so (with \t between the columns):

Table 1
R (number)  Q (text)


81, 82, 5, 4, 435012, -1002, 23

This function runs through the table once, adding a textual representation of each number in a new column. Then it sorts the table rows according to the text column; in Inform, strings are sorted lexicographically. Finally, it prints out the original column in the new order. Conveniently, Inform 7's "crude but sometimes useful" format for printing out table columns turns out to be comma separated, exactly as requested.

Ungolfed, with boilerplate showing how to call the function:

To print the numbers in alphabetical order:
    repeat through the Table of Sortable Numbers:
        now the name entry is "[the index entry in words]";
    sort the Table of Sortable Numbers in name order;
    say "[the index column in the Table of Sortable Numbers]".

Table of Sortable Numbers
index (number)  name (text)

There is a room.
When play begins: print the numbers in alphabetical order.
  • 1
    \$\begingroup\$ I'm slightly confused by this. Is words a reference of the spelled out versions of numbers, built into Inform 7? \$\endgroup\$
    – Pavel
    Commented Dec 1, 2016 at 20:52
  • 1
    \$\begingroup\$ @Pavel Indeed! "(number) in words" returns a string with a textual representation of the number. It conveniently uses "minus" for negative numbers, and while it puts hyphens between words, it does so consistently and alphabetizes hyphens before all letters (so the end result is the same). \$\endgroup\$
    – Draconis
    Commented Dec 1, 2016 at 20:57
  • 2
    \$\begingroup\$ +1 for the language choice. I'd have to check, but I suspect there are some golfing opportunities left, though; for example, does the parser really require all those "the" articles? And you'd have to ask the OP, but I don't see any obvious reason why " and " would not be a valid delimiter. Even if not, a single space is explicitly allowed, so just say "[R entry] " should suffice. \$\endgroup\$ Commented Dec 1, 2016 at 23:01
  • \$\begingroup\$ I'd say the "and" at the end is fine. I didn't say that the delimiters had to be uniform, so this is a perfectly acceptable answer. If I could give points for most interesting answer, I would give it to you. I really enjoy the readability of this language, even golfed. Nice job! \$\endgroup\$
    – wubs
    Commented Dec 2, 2016 at 18:56
  • \$\begingroup\$ I finally got a chance to play with Inform7 a bit, and managed to re-golf your entry down to just 118 bytes. Since posting Inform code in comments doesn't work very well, I went ahead and edited it into your answer directly. I hope you don't mind, feel free to revert and/or tweak my edits any way you like if you do. \$\endgroup\$ Commented Dec 10, 2016 at 19:25

JavaScript (ES6), 189 179 186 bytes

let f =

a=>a.sort((x,y)=>!x-!y||(X=q(x),Y=q(y),X>Y)-(X<Y),q=n=>n<0?"L"+q(-n):n>999?q(n/1e3)+"Z"+q(n%1e3):n>99?q(n/100)+"K"+q(n%100):n>19?"  cYHFVSCO"[n/10|0]+q(n%10):"0PdaIGTQAMWDbXJEURBN"[n|0])

let g = a => console.log(`[${f(a)}]`)

<input id=I value="1 2 3 4 5"><button onclick="g(I.value.match(/\d+/g)||[])">Run</button>

The basic idea is to convert each input number into a short string that's in the correct lexographical position compared to all other number-string pairs. Here's the dictionary used: (Don't run the snippet; it's just used to hide the long list.)

A eight
B eighteen
C eighty
D eleven
E fifteen
F fifty
G five
H forty
I four
J fourteen
K hundred
L minus
M nine
N nineteen
O ninety
P one
Q seven
R seventeen
S seventy
T six
U sixteen
V sixty
W ten
X thirteen
Y thirty
Z thousand
a three
b twelve
c twenty
d two

This creates a very concise way of mapping each number to its lexographically correct position. That's what the recursive q function does:

q(-X)        => "L" + q(X)
q(XYYY)      => q(X) + "Z" + q(YYY)
q(XYY)       => q(X) + "K" + q(YY)
q(XY >= 20)` => "  cYHFVSCO"[X] + q(Y)
q(X)         => "0PdaIGTQAMWDbXJEURBN"[X]

The 0 at the beginning of the string is to ensure that e.g. 100 (one hundred, converted to PK0) is sorted before 101 (one hundred one, converted to PKP). This creates an odd scenario where 0 (zero) is sorted to the front of the array, so to get around this, in the sorting function we first sort any zeroes to the right with !x-!y||(....

  • \$\begingroup\$ Looks like it doesn't work for [1100, 1000]. I would expect the output to be 1000 (one thousand), 1100 (one thousand one hundred), but the output is the same order as input. \$\endgroup\$
    – milk
    Commented Dec 1, 2016 at 21:38
  • \$\begingroup\$ @milk Hmm... I'm not sure why this happens, but I'll look into it. \$\endgroup\$ Commented Dec 1, 2016 at 22:18
  • \$\begingroup\$ @milk Ah, 1000 is being parsed as one thousand zero; I'll fix this momentarily. Must we support 0 on its own though? It's a unique case that will add 15 bytes or so to my code. \$\endgroup\$ Commented Dec 1, 2016 at 22:22

Mathematica, 67 bytes


Unnamed function taking a list of integers as its argument and returning a list of integers as its value. #~IntegerName~"Words" is a built-in that changes an integer to its name in English. IntegerName sometimes has commas and hyphens in its output, so the StringReplace call gets rid of those. (Sadly the hyphen is actually the 3-byte character, 8208, in UTF-8.) Then SortBy sorts the original list alphabetically according to the value of the modified integer name.

A nice coincidence: IntegerName uses negative instead of minus in its output—but no word appearing in the names of any of the allowed numbers is alphabetically between those two words, so no replacement is needed!

(Hat tip to ngenisis for reminding me of Sortby.)

  • \$\begingroup\$ Kudos! I came very close to getting this solution, but that dash was giving me headaches! \$\endgroup\$
    – user61980
    Commented Dec 1, 2016 at 22:12
  • \$\begingroup\$ Does your answer here actually use the correct hyphen? If I copy what you have here into Mathematica it doesn't replace the hyphens from IntegerName. The Wolfram documentation says that it is unicode character 2010. \$\endgroup\$
    – user61980
    Commented Dec 1, 2016 at 22:38
  • \$\begingroup\$ Probably not, then—I tried to get the correct hyphen in this answer, but looks like I didn't succeed. \$\endgroup\$ Commented Dec 2, 2016 at 2:11
  • \$\begingroup\$ I cut your answer in half ;) \$\endgroup\$ Commented Dec 2, 2016 at 15:27
  • \$\begingroup\$ And then some... you make unnecessary modifications to the string. \$\endgroup\$ Commented Dec 2, 2016 at 15:28

Bash + GNU utils + bsdgames, 52

  • 4 bytes saved thanks to @izabera.
sed 's/.*/echo `echo &|number`:&/e'|sort|sed s/.*://

I/O is newline-delimited lines.

  • The first sed expression replaces each numerical number with a shell command that outputs the word form of the number (as given by the bsdgames number utility), followed by a : then the numerical form of the number.
  • This is then sorted.
  • Then the second sed strips leading characters up to and including the :, leaving the numerical form sorted as required.

number correctly handles "minus", and its output is close enough to the specificed format that the sort works as required. It does output "fourty-four" instead of "fourty four", but this shouldn't matter from the sorting perspective.

The bsdgames package may need installation:

sudo apt-get install bsdgames

The sed and sort utilities are almost certainly already in your distro.

  • \$\begingroup\$ -t: is useless and you can use number<<<& \$\endgroup\$
    – izabera
    Commented Dec 2, 2016 at 2:06
  • \$\begingroup\$ @izabera Yes - thanks - I removed the -t:. However, sed's eval feature runs commands using sh, so bash features like <<< won't work. \$\endgroup\$ Commented Dec 2, 2016 at 17:38
  • \$\begingroup\$ it works fine as long as your sh is bash :P \$\endgroup\$
    – izabera
    Commented Dec 2, 2016 at 22:49
  • \$\begingroup\$ @izabera Nope - if bash as started as sh it tries to emulate Posix sh as much as possible, which means that bashisms such as <<< are turned off. GNU sed's eval feature starts commands with /bin/sh -c ... and not /bin/bash -c .... Have you tried this? \$\endgroup\$ Commented Dec 2, 2016 at 23:32
  • \$\begingroup\$ bash never turns off <<<, not even in posix mode \$\endgroup\$
    – izabera
    Commented Dec 3, 2016 at 0:13

Python + inflect, 97 91 89 bytes

from inflect import*
a={x:engine().number_to_words(x)for x in words}

Used the inflect library to transform the words array of integers into their phonetic/string representation. Stored into a dictionary of k/v pairs where the keys were the numeric representation and values were the string representation. Returned the list of keys as sorted by values.

EDIT: Saved 5 and 3 bytes, thanks to ETHproductions and Alex.S!

  • \$\begingroup\$ Welcome to PPCG! You can golf this by removing spaces; for example, the second line can be a={x:inflect.engine().number_to_words(x)for x in words}. \$\endgroup\$ Commented Dec 2, 2016 at 4:06
  • \$\begingroup\$ You can save two bytes using from inflect import* and throwing out inflect. in the second line. \$\endgroup\$
    – Alex.S
    Commented Dec 2, 2016 at 11:15
  • \$\begingroup\$ Alas, looks like this also fails to correctly sort the list 40, 44, 40000, 40804, 40004, 40204 (which should stay in that order). \$\endgroup\$ Commented Dec 10, 2016 at 20:13

Mathematica, 30 bytes

The answer below outputs a pure function which will take a list of integers as an input and sort them by their alphabetic name. Just what the doctor ordered ;)


Here is the ungolfed version:

SortBy[IntegerName[#, "Words"]&]

And here is an example usage:


Which could also be written as


They produce identical outputs - in mathematica, f[x] is equivilant to f@x.

Outputs: {8, 5, 4, 9, 1, 7, 6, 10, 3, 2}

There is a much longer answer that another user posted in Mathematica. That answer tries to correct for some small differences between the way mathematica alphebatizes numbers to better conform to the way the OP stated numbers should be alphebatized, however the things they correct for don't affect sorting order, and my answer outputs identically to theirs:

MyF = SortBy[#~IntegerName~"Words"&];
TheirF = SortBy[#, #~IntegerName~"Words"~ StringReplace~{"," -> "", "-" -> ""} &] &;
MyF[Range[-999999, 999999]] == TheirF[Range[-999999, 999999]]
(*Outputs True*)
  • \$\begingroup\$ A great investigation!—unfortunately, they don't actually give the same order. TheirF correctly sorts 888 before 880,000, while MyF doesn't. Probably the issue is with the copy-pasting of the strange hyphen: your version of TheirF is probably replacing normal hyphens (of which there are none), while the actual version replaces the strange 3-byte Unicode hyphen. (It would still be interesting to see whether removing commas is necessary.) \$\endgroup\$ Commented Dec 2, 2016 at 17:59
  • \$\begingroup\$ I tested it on Range[999999]. Looks like eliminating the commas is unnecessary, but replacing "[Hyphen]" with "" is definitely necessary. \$\endgroup\$
    – user61980
    Commented Dec 2, 2016 at 19:28

Common Lisp, 113 bytes

No external libraries necessary.

(print(mapcar #'cdr(sort(loop for i in x collect(cons(format()"~r"i)i))(lambda(y z)(string-lessp(car y)(car z))))))

Output if x is '(1 2 3 4 5):

(5 4 1 3 2)

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.