Number reader function

I wrote a function that takes a number input and reads it out in words. It works for all nonnegative integers up to 10^3006 - 1

function read(n)
	n = tostring(n or ""):match("^0*(.*)$")
	if #n == 0 then return "zero" end
	if #n > 3 then
		local x = {"thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion"}
		local y = {"", "un", "duo", "tre", "quattuor", "quin", "sex", "septen", "octo", "novem"}
		local z = {"t", "dec", "vigint", "trigint", "quadragint", "quinquagint", "sexagint", "septuagint", "octogint", "nonagint"}
		for i = 2, #z do
			for j = 1, #y do
				x[#x+1] = y[j]..z[i].."illion"
			end
		end
		y[3], y[10] = "do", "ovem"
		local v = {"cen", "ducen", "trecen", "quadringen", "quingen", "sescen", "septingen", "optingen", "nongen"}
		for h = 1, #v do
			for i = 1, #z do
				for j = 1, #y do
					x[#x+1] = v[h]..y[j]..z[i].."illion"
				end
			end
		end
		x[#x+1] = "millillion"
		local c = (#n - 1)%3 + 1
		local remain = n:sub(c+1)
		return read(n:sub(1, c)).." "..x[math.ceil(#n/3)-1]..(remain:find("[^0]") and " "..read(remain) or "")
	end
	local a = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
	local b = {"", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}
	local c = {[0] = "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}
	if #n == 1 then
		return a[tonumber(n)]
	elseif #n == 2 then
		local ones = tonumber(n:sub(2, 2))
		local tens = tonumber(n:sub(1, 1))
		if tens == 1 then
			return c[ones]
		elseif ones == 0 then
			return b[tens]
		else
			return b[tens].." "..a[ones]
		end
	elseif #n == 3 then
		local rest = read(n:sub(2))
		return a[tonumber(n:sub(1, 1))].." hundred"..(rest == "zero" and "" or " "..rest)
	end
end

e.g. print(read("133790018675309123456789042"))

one hundred thirty three septillion seven hundred ninety sextillion eighteen quintillion six hundred seventy five quadrillion three hundred nine trillion one hundred twenty three billion four hundred fifty six million seven hundred eighty nine thousand forty two

19 Likes

Y4YFthE

1 Like
if (n < 0) then
    return 'negative ' .. Result;
end;

The lazy way into negative integers.

This lets me generate some self-describing strings fairly quickly, for example:

"four"
"five plus six"
"positive fifteen"
"five multiplied by four"
"the sum of twelve and nine"
"twenty five multiplied by one"
"the product of twelve and two"
"the fifth root of thirteen billion three hundred eighty two million two hundred fifty five thousand seven hundred seventy six"
https://pastebin.com/raw/aCxXjzPp

where each string here describes how many letters it has.

Oh wow, this is pretty neat!