toroman

function toroman( num [, mode] ) --> roman

Description

Converts the number num to a roman string. The number value must be positive.

Parameters

num

A number that should be convert.

mode

A number that specifies the type roman number that should be returned.

  • 0 for a classic roman number, this is also the default variant.

  • 1/2/3 for a more concise variants, check the examples to see the difference.

  • 4 for a simplified roman number.

Return Values

roman

A roman number as string.

Code

--ZFUNC-toroman-v1
local function toroman( num, mode ) --> roman
   mode = mode or 0
   if num < 1 or num > 3999 then return "" end

   local chars = { "M", "D", "C", "L", "X", "V", "I" }
   local vals = { 1000, 500, 100,  50,  10,   5,   1 }
   local sidx =  {   3,   3,   5,   5,   7,   7 }
   local last = #vals

   local roman = {}
   while num > 0 do
      local i = 1
      while i <= last do
         local v = vals[ i ]
         if num >= v then
            num = num - v
            table.insert( roman, chars[ i ] )
            i = last + 1
         else
            local j = math.min( sidx[ i ] + mode, last )
            local n = sidx[ i ]
            while j >= n do
               local v2 = v - vals[ j ]
               if num >= v2 then
                  num = num - v2
                  table.insert( roman, chars[ j ] )
                  table.insert( roman, chars[ i ] )
                  i = last + 1
                  j = 1
               else
                  j = j - 1
               end
            end

            i = i + 1
         end
      end
   end

   return table.concat( roman )
end

return toroman

Examples

local t = require( "tapered" )
local toroman = require( "toroman" )

t.is( "III", toroman( 3 ) )
t.is( "VII", toroman( 7 ) )
t.is( "MCMXCIX", toroman( 1999 ) )

t.is( "CDXCIX", toroman( 499, 0 ) )
t.is( "LDVLIV", toroman( 499, 1 ) )
t.is( "XDIX", toroman( 499, 2 ) )
t.is( "VDIV", toroman( 499, 3 ) )
t.is( "ID", toroman( 499, 4 ) )

t.is( "", toroman( -1 ) )

-- should allow only 3999 as max value
t.is( "MMMCMXCIX", toroman( 3999 ) )
t.is( "", toroman( 4000 ) )

t.done()

Inspired by

See also