利用者:InmuTroll/ruby
表示
Lua使えないのか…(落胆)
-- using Wagner–Fischer algorithm
local function str_ucompare(s1, s2, limit)
s1, s2 = mw.text.split(s1, ''), mw.text.split(s2, '')
local len1, len2 = #s1, #s2
if limit and len1 * len2 * 20 > limit then return {{s1}, {s2}} end
local m_cost, m_step = {{0}}, {{}}
for i = 1, len1 do
m_cost[i + 1] = {i}
m_step[i + 1] = {3}
end
for j = 1, len2 do
m_cost[1][j + 1] = j
m_step[1][j + 1] = 4
end
for i = 1, len1 do
for j = 1, len2 do
local b_same = s1[i] == s2[j]
local c_sub = m_cost[i][j] + (b_same and 0 or 1)
local c_del = m_cost[i][j + 1] + 1
local c_ins = m_cost[i + 1][j] + 1
if c_sub <= c_del and c_sub <= c_ins then
m_cost[i + 1][j + 1] = c_sub
m_step[i + 1][j + 1] = b_same and 1 or 2
elseif c_del <= c_ins then
m_cost[i + 1][j + 1] = c_del
m_step[i + 1][j + 1] = 3
else
m_cost[i + 1][j + 1] = c_ins
m_step[i + 1][j + 1] = 4
end
end
end
local i1, i2 = len1 + 1, len2 + 1
local m_offset = {{-1, -1}, {-1, -1}, {-1, 0}, {0, -1}}
local r_step_rev = {}
local r_step_rev_pos1 = {}
local r_step_rev_pos2 = {}
local step = m_step[i1][i2]
while step do
table.insert(r_step_rev, step)
i1 = i1 + m_offset[step][1]
i2 = i2 + m_offset[step][2]
table.insert(r_step_rev_pos1, i1)
table.insert(r_step_rev_pos2, i2)
step = m_step[i1][i2]
end
local r1, r2 = {}, {}
local i = #r_step_rev
local step = r_step_rev[i]
while i > 0 do
local r1_f, r2_f = {}, {}
if step == 1 then
repeat
table.insert(r1_f, s1[r_step_rev_pos1[i]])
table.insert(r2_f, s2[r_step_rev_pos2[i]])
i = i - 1
step = r_step_rev[i]
until step ~= 1
else
while true do
if step == 2 then
table.insert(r1_f, s1[r_step_rev_pos1[i]])
table.insert(r2_f, s2[r_step_rev_pos2[i]])
elseif step == 3 then
table.insert(r1_f, s1[r_step_rev_pos1[i]])
elseif step == 4 then
table.insert(r2_f, s2[r_step_rev_pos2[i]])
else
break
end
i = i - 1
step = r_step_rev[i]
end
end
table.insert(r1, table.concat(r1_f))
table.insert(r2, table.concat(r2_f))
end
return {r1, r2}
end
return {
ruby = function(frame)
local text_blocks = str_ucompare(frame.args[1], frame.args[2])
local result = {}
for index, text_below in ipairs(text_blocks[1]) do
local text_above = text_blocks[2][index]
if text_above == text_below then
table.insert(result, text_below)
else
table.insert(result, '<ruby>' .. text_below .. '<rp>(</rp><rt>' .. text_above .. '</rt><rp>)</rp></ruby>')
end
end
return table.concat(result)
end,
}