Alphabetize Integers

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.

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.

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)}]`)

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


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