# 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:

Input:

1, 2, 3, 4, 5


Output:

5, 4, 1, 3, 2


Multiple Digit Integers:

Input:

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


Output:

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


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

Input:

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


Output:

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!

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

## Inform 7, 214201 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.

Golfed:

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)
-1002
5
435012
4
23
81
82


Output:

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)
-1002
5
435012
4
23
81
82

There is a room.
When play begins: print the numbers in alphabetical order.

• I'm slightly confused by this. Is words a reference of the spelled out versions of numbers, built into Inform 7? Dec 1, 2016 at 20:52
• @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). Dec 1, 2016 at 20:57
• +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. Dec 1, 2016 at 23:01
• 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!
– wubs
Dec 2, 2016 at 18:56
• 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. Dec 10, 2016 at 19:25

# JavaScript (ES6), 189179 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)}])

g([1,2,3,4,5])
g([-1002,5,435012,4,23,81,82])
g([0,1000,1100])
<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||(....

• 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.
– milk
Dec 1, 2016 at 21:38
• @milk Hmm... I'm not sure why this happens, but I'll look into it. Dec 1, 2016 at 22:18
• @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. Dec 1, 2016 at 22:22

# Mathematica, 67 bytes

SortBy[#,#~IntegerName~"Words"~StringReplace~{","->"","-"->""}&]&


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.)

• Kudos! I came very close to getting this solution, but that dash was giving me headaches! Dec 1, 2016 at 22:12
• 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. Dec 1, 2016 at 22:38
• Probably not, then—I tried to get the correct hyphen in this answer, but looks like I didn't succeed. Dec 2, 2016 at 2:11
• I cut your answer in half ;) Dec 2, 2016 at 15:27
• And then some... you make unnecessary modifications to the string. 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.

• -t: is useless and you can use number<<<& Dec 2, 2016 at 2:06
• @izabera Yes - thanks - I removed the -t:. However, sed's eval feature runs commands using sh, so bash features like <<< won't work. Dec 2, 2016 at 17:38
• it works fine as long as your sh is bash :P Dec 2, 2016 at 22:49
• @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? Dec 2, 2016 at 23:32
• bash never turns off <<<, not even in posix mode Dec 3, 2016 at 0:13

# Python + inflect, 9791 89 bytes

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


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!

• 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}. Dec 2, 2016 at 4:06
• You can save two bytes using from inflect import* and throwing out inflect. in the second line. Dec 2, 2016 at 11:15
• Alas, looks like this also fails to correctly sort the list 40, 44, 40000, 40804, 40004, 40204 (which should stay in that order). 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 ;)

SortBy[#~IntegerName~"Words"&]


Here is the ungolfed version:

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


And here is an example usage:

SortBy[#~IntegerName~"Words"&][{0,1,2,3,4,5,6,7,8,9,10}]


Which could also be written as

SortBy[#~IntegerName~"Words"&]@{0,1,2,3,4,5,6,7,8,9,10}


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*)

• 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.) Dec 2, 2016 at 17:59
• I tested it on Range. Looks like eliminating the commas is unnecessary, but replacing "[Hyphen]" with "" is definitely necessary. 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)
`