Module:MathRoman.lua

From Guild of Archivists
Revision as of 07:26, 30 October 2015 by Alahmnat (talk | contribs) (1 revision imported)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:MathRoman.lua/doc

 --[[ 20120505 19:50 calcul de nombre romain pour http://fr.wikisource.org/
 script en langage LUA, exemples d'appels :
 valeurDeRomain('MCXI')
 testerDesRomains('vue') parametre obsolete
 http://phrogz.net/Lua/LearningLua_FromJS.html   Learning Lua/From JS
 http://www.lua.org/pil/   Programming in Lua reference
 http://www.lua.org/cgi-bin/demo   Demo Try Lua
 20120503 22:16 tests partiel OK
 20120504 22:57 tests complets. Your program ran successfully.
 20120505 00:10 adapter a Module:mathRoman.lua
 http://www.mediawiki.org/wiki/Module:mathRoman.lua
 http://www.mediawiki.org/wiki/Extension:Scribunto/Parser_interface_design
 Proposed interface summary
 20120505 19:50 function r.roman2integer( frame )
 ]]--

  function roman2int(rm, err)
    if ( rm == nil ) then rm = '' end 
    if ( err == nil ) then err = '' end 
    if ( rm == '' ) then return '' end 
    local v = 0 -- valeur totale
    local v1 = 0 -- valeur de derniere lettre
    local v2 = 0 -- valeur de lettre precedente
    local v3 = 0 -- valeur de lettre precedente
    local x = '-' -- caractere en cours d'evaluation
    local i = 0 -- numéro du caractere en cours d'evaluation
    local j = 0 -- numéro du caractere de reference courant (debut en Lua)
    local k = 0 -- numéro du caractere de reference courant (fin en Lua)
    local e0 = '' -- texte d'erreur
    local e1 = '' -- texte d'erreur
    local e2 = '' -- texte d'erreur
    local e3 = '' -- texte d'erreur
    local e4 = '' -- texte d'erreur
    local lst = '-MDCLXVIJ' -- caracteres autorises
    while (x ~= '') do
      v3 = v2
      v2 = v1
      v1 = 0
      x = string.sub(rm, i, i)
      if ( x == 'M' ) then v1 = 1000 end
      if ( x == 'D' ) then v1 = 500 end
      if ( x == 'C' ) then v1 = 100 end
      if ( x == 'L' ) then v1 = 50 end
      if ( x == 'X' ) then v1 = 10 end
      if ( x == 'V' ) then v1 = 5 end
      if ( x == 'I' ) then v1 = 1 end
      if ( x == 'J' ) then
        v1 = 1
        if ( i < ( string.len(rm) - 0 ) )
        then e4 = ' erreur caractere J avant la fin.' end
      end
      v = v + v1
      if ( (v1 == 5*v2) or (v1 == 10*v2) ) then v = v - (2*v2) end -- ajuster 4, 9, 40, 90 ...
      j, k = string.find(lst, x)
      if ( j == nil ) then j = -1 end 
      if ( k == nil ) then k = -1 end 
      if ( j < 1 ) then e3 = ' erreur caractere '..x..' en '..i..'.' end
      if ( (v1 > v2) and (v2 > v3) ) then e2 = ' caracteres croissants.' end
      i = i + 1
      x = string.sub(rm, i, i)
    end
    if ( v == 0 ) then e0 = ' valeur nulle.' end
    if ( v > 4999 ) then e1 = ' valeur > 4999.' end
    if ( ( e0..e1..e2..e3..e4 > '' ) and ( err > '' ) ) then 
      err = ''..err..e0..e1..e2..e3..e4 -- sortie avec les erreurs
    else
      err = '' -- sortie sans les erreurs
    end
    return v, err -- avec ou sans erreurs
  end -- function roman2int(rm, err)

  function romani2r(i, j)
    if ( j == nil ) then j = '' end
    local rm=''
    if ( i == 1000 ) then rm = 'M' end
    if ( i == 500 ) then rm = 'D' end
    if ( i == 100 ) then rm = 'C' end
    if ( i == 50 ) then rm = 'L' end
    if ( i == 10 ) then rm = 'X' end
    if ( i == 5 ) then rm = 'V' end
    if ( i == 1 ) then 
      rm = 'I'
      if ( j == 'J' ) then  rm = 'J' end
    end
    return rm
  end -- function romani2r(i, j)

  function int2roman(i, err)
    local n = 0
    if ( i == nil ) then n = 0 else n = i end -- anti null
    if ( type(n) ~= 'number' ) then n = tonumber(n) end
    if ( type(n) ~= 'number' ) then n = 0 end
    n = math.floor(n) -- input:89: bad argument #1 to 'floor' (number expected, got nil)
    -- if ( type (v) ~= 'number' ) then i = 0 end -- anti nil
    -- i = i.valueOf()
    if ( err == nil ) then err = ' ' end -- anti null, to text
    local v100 = 100 
    local v500 = v100*5 
    local v1000 = v100*10 -- cycle romain 1000, 100, 10, 1
    local v=0 
    local v1=0 
    local v2=0 
    local v3=0 -- valeurs totale, derniere, et precedentes
    local reste=0 
    local reduction=0 -- reste a convertir, derniere reduction
    --local x='-' local i=0 -- caractere courant et son numéro
    --local lst='-MDCLXVIJ' -- liste des chiffres romains
    local rm='' 
    local roman='' -- chiffre et nombre romain resultant
    local e0='' 
    local e1='' 
    local e2='' 
    local e3='' 
    local e4='' -- erreurs detectables
    if ( n > 4999 ) then
      e1 = ' valeur > 4999.'
      roman = 'ERREUR'
      n = 0
    end 
    if ( n < 1 ) then
      e2 = ' valeur < 1.'
      roman = 'ERREUR'
      n = 0
    end 
    reste = n
    -- return ' test ' -- temporaire
    while (reste > 0) do
      v3 = v2 
      v2 = v1 
      v1 = reste
      reduction = 0
      if ( reste >= v1000 ) then 
        reduction = v1000 
      elseif ( reste >= v100*9 ) then 
        reduction = v100 
        reste = reste + v100*2 
      elseif ( reste >= v500 ) then 
        reduction = v500 
      elseif ( reste >= v100*4 ) then 
        reduction = v100 
        reste = reste + v100*2 
      elseif ( reste >= v100 ) then 
        reduction = v100 
      elseif ( reste >= 1000 ) then 
        v100 = 100 
        v1000 = 1000 
        reduction = v1000 
      end
      rm = romani2r(reduction)
      roman = roman..rm
      reste = reste - reduction
      if ( reste < v100 ) then 
        if ( v100 >= 10 ) then 
          v100 = v100/10 
          v500 = v100*5 
          v1000 = v100*10
        end
      end
    end
    -- if ( v == 0 ) then e0 = ' valeur nulle.' end
    -- if ( v > 4999 ) then e1 = ' valeur > 4999.' end
    if ( ( e0..e1..e2..e3..e4 > '' ) and ( err > '' ) ) then 
      err = ''..err..e0..e1..e2..e3..e4 -- sortie avec les erreurs
    else
      err = '' -- sortie sans les erreurs
    end
    return roman, err -- avec ou sans erreurs
  end -- function int2roman(in, err)

  function testerUnRomain(r1, vue) 
    if ( r1 == nil ) then r1 = '' end
    local i, erri = roman2int(r1, ' Erreur r2i : ')
    local rm, errm = int2roman(i, ' Erreur i2r : ')
    print( r1..'='..i..'='..rm )
    if ( ( erri == nil ) or ( erri == '' ) ) then erri = '' end
    if ( ( errm == nil ) or ( errm == '' ) ) then errm = '' end
    if ( ( erri ~= '' ) or ( errm ~= '' ) ) then print( ' -> '..erri..errm ) end
  end -- function testerUnRomain(r1, vue)

  function erreurUnRomain(r1, vue)
    if ( r1 == nil ) then r1 = '' end
    local i, erri = roman2int(r1, ' Erreur r2i : ')
    print( ' - '..r1..'='..i )
    if ( ( erri == nil ) or ( erri == '' ) ) then erri = '' end
    if ( erri ~= '' ) then print( ' -> '..erri..erri ) end
  end -- function erreurUnRomain(r1, vue)

  function testerDesRomains(vue)
    testerUnRomain('XIJ', vue)
    testerUnRomain('MCXI', vue)
    testerUnRomain('MCDXLIV', vue)
    testerUnRomain('MDCLXVI', vue)
    testerUnRomain('MCMXCIX', vue)
    testerUnRomain('MMCCXXII', vue)
    testerUnRomain('MMMMCMXCIX', vue)
    -- Nombres avec erreurs
    testerUnRomain('i', vue)
    testerUnRomain('ERREURS', vue)
    testerUnRomain('XIA', vue)
    testerUnRomain('XJI', vue)
    testerUnRomain('IXC', vue)
    testerUnRomain('VLD', vue)
    testerUnRomain('MMMMM', vue)
    testerUnRomain('MMMMMYJXC', vue)
    testerUnRomain('', vue)
    testerUnRomain(nil)
    erreurUnRomain('ERREURS', vue)
    erreurUnRomain('XIA', vue)
    erreurUnRomain('XJI', vue)
    erreurUnRomain('IXC', vue)
    erreurUnRomain('VLD', vue)
    erreurUnRomain('MMMMM', vue)
    erreurUnRomain('MMMMMYJXC', vue)
  end -- function testerDesRomains(vue) 

  testerDesRomains('x') -- lance le test

 -- http://www.mediawiki.org/wiki/Extension:Scribunto/Parser_interface_design
 -- Proposed interface summary
 -- <!-- Invoke a Lua function from wikitext -->
 -- {{ #invoke: module_name | function_name | arg1 | arg2 | name1 = value1 }}
 -- 20120505 18:37
 function p.function_name( frame )
        -- Get arg1
        local arg1 = frame.args[1]
         -- Get name1
        local name1 = frame.args.name1
         -- Get name1 by preprocessing
        name1 = frame:preprocess( '{{{name1}}}' )
         -- Put all arguments into a real table
        local t = {}
        for name, value in frame:argumentPairs() do
                t[name] = value
        end
         -- Make a <ref> tag
        local s = frame:preprocess( '<ref>Note</ref>' )
         -- Call a template
        s = s .. frame:expandTemplate{ title = 'tpl', args = {foo = arg1} }
         -- Return expanded text
        return s
 end
 -- return p

 -- 20120505 19:50
 function r.roman2integer( frame )
        -- Get arg1 arg2
        local r1 = frame.args[1]
        local err = frame.args[2]
        -- internal process
        if ( r1 == nil ) then r1 = '' end
        local i, erri = roman2int(r1, ' Error : ')
        s = i
        if ( ( erri == nil ) or ( erri == '' ) ) then erri = '' end
        if ( erri ~= '' ) then s = s .. erri end
         -- Return expanded text
        return s
 end
 return r