currently i have a numbers to words converter, but i feel like there’s a pattern in these functions which would allow me to compress them down into one, but how?
function thousandDigitsToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local NLength:number = string.len(tostring(n))
local FirstDigits:number?
local TheRest:number?
if NLength == 4 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 1))
TheRest = tonumber(string.sub(tostring(n), 2, 4))
elseif NLength == 5 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 2))
TheRest = tonumber(string.sub(tostring(n), 3, 5))
else
FirstDigits = tonumber(string.sub(tostring(n), 1, 3))
TheRest = tonumber(string.sub(tostring(n), 4, 6))
end
local finalResult:string = belowThreeDigitsToWord(FirstDigits).." thousand "..belowThreeDigitsToWord(TheRest)
if isNegative then
finalResult = "negative "..finalResult
end
return finalResult
end
function millionDigitsToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local NLength:number = string.len(tostring(n))
local FirstDigits:number?
local TheRest:number?
if NLength == 7 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 1))
TheRest = tonumber(string.sub(tostring(n), 2, 7))
elseif NLength == 8 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 2))
TheRest = tonumber(string.sub(tostring(n), 3, 8))
else
FirstDigits = tonumber(string.sub(tostring(n), 1, 3))
TheRest = tonumber(string.sub(tostring(n), 4, 9))
end
local finalResult:string = belowThreeDigitsToWord(FirstDigits).." million "..daft:numberToWord(TheRest)
if isNegative then
finalResult = "negative "..finalResult
end
return finalResult
end
function billionDigitsToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local NLength:number = string.len(tostring(n))
local FirstDigits:number?
local TheRest:number?
if NLength == 10 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 1))
TheRest = tonumber(string.sub(tostring(n), 2, 10))
elseif NLength == 11 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 2))
TheRest = tonumber(string.sub(tostring(n), 3, 11))
else
FirstDigits = tonumber(string.sub(tostring(n), 1, 3))
TheRest = tonumber(string.sub(tostring(n), 4, 12))
end
local finalResult:string = belowThreeDigitsToWord(FirstDigits).." billion "..daft:numberToWord(TheRest)
if isNegative then
finalResult = "negative "..finalResult
end
return finalResult
end
function trillionDigitsToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local NLength:number = string.len(tostring(n))
local FirstDigits:number?
local TheRest:number?
if NLength == 13 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 1))
TheRest = tonumber(string.sub(tostring(n), 2, 13))
elseif NLength == 14 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 2))
TheRest = tonumber(string.sub(tostring(n), 3, 14))
else
FirstDigits = tonumber(string.sub(tostring(n), 1, 3))
TheRest = tonumber(string.sub(tostring(n), 4, 15))
end
local finalResult:string = belowThreeDigitsToWord(FirstDigits).." trillion "..daft:numberToWord(TheRest)
if isNegative then
finalResult = "negative "..finalResult
end
return finalResult
end
function quadrillionDigitsToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local NLength:number = string.len(tostring(n))
local FirstDigits:number?
local TheRest:number?
if NLength == 14 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 1))
TheRest = tonumber(string.sub(tostring(n), 2, 16))
elseif NLength == 15 then
FirstDigits = tonumber(string.sub(tostring(n), 1, 2))
TheRest = tonumber(string.sub(tostring(n), 3, 17))
else
FirstDigits = tonumber(string.sub(tostring(n), 1, 3))
TheRest = tonumber(string.sub(tostring(n), 4, 18))
end
local finalResult:string = belowThreeDigitsToWord(FirstDigits).." quadrillion "..daft:numberToWord(TheRest)
if isNegative then
finalResult = "negative "..finalResult
end
return finalResult
end
– not the focus of the post, just here if someone asks for it
function numberInRange(n:number, mn:number, mx:number):boolean
n, mn, mx = tonumber(n), tonumber(mn), tonumber(mx)
return (n>=mn) and (n<=mx)
end
function singleDigitToWord(n:number):string
local numbers:{string} = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
if n == 0 then
return "zero"
elseif n < 0 then
n = math.abs(n)
return "negative "..numbers[n]
else
return numbers[n]
end
end
function doubleDigitToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local tenCases:{string} = {"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"}
local otherNumbers:{string} = {"", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"}
local FirstDigit:number = tonumber(string.sub(tostring(n), 1, 1))
local SecondDigit:number = tonumber(string.sub(tostring(n), 2, 2))
if isNegative then
for i, v in ipairs(tenCases) do
tenCases[i] = "negative "..v
end
for i, v in ipairs(otherNumbers) do
otherNumbers[i] = "negative "..v
end
end
-- we got a ten here
if FirstDigit == 1 then
-- special case for ten to make the rest of the code cleaner
if SecondDigit == 0 then
if isNegative then
return "negative ten"
else
return "ten"
end
else
return tenCases[SecondDigit]
end
else
if SecondDigit == 0 then
return otherNumbers[FirstDigit]
else
return otherNumbers[FirstDigit].."-"..singleDigitToWord(SecondDigit)
end
end
end
function tripleDigitToWord(n:number):string
local isNegative:boolean = (n<0)
n = math.abs(n)
local FirstDigit:number = tonumber(string.sub(tostring(n), 1, 1))
local TheRest:number = tonumber(string.sub(tostring(n), 2, 3))
local finalResult:string = singleDigitToWord(FirstDigit).." hundred "..daft:numberToWord(TheRest)
if isNegative then
finalResult = "negative "..finalResult
end
return finalResult
end
function belowThreeDigitsToWord(n:number):string
-- don't count the negative sign
local NLength:number = string.len(tostring(math.abs(n)))
if NLength == 1 then
return singleDigitToWord(n)
elseif NLength == 2 then
return doubleDigitToWord(n)
else
return tripleDigitToWord(n)
end
end