Module:MathRoman.lua: Difference between revisions
From Guild of Archivists
(function r.roman2integer( frame )) |
m (1 revision imported) |
(No difference)
|
Latest revision as of 07:26, 30 October 2015
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