merge5 = (annT2, newT2) => {
if (newT2.length > 500) return ['aborting to avoid performance issue']
const tagRE = /<\/?\d+>/g
const tags = [...annT2.matchAll(tagRE)]
const reindexed = tags.reduce(([acc, idx], t) => [[...acc, {...t, index: t.index - idx}], idx + t[0].length], [[], 0])[0]
let newTags = []
let N = 20
const M = 3
let nSpaces = n => new Array(n).map(v => '').join(' ')
const context = (s, i, k) => (s + nSpaces(k)).slice(i, i + k)
const pad2sides = (s, k) => (nSpaces(k) + s + nSpaces(k))
const oldT2 = annT2.replaceAll(tagRE, '')
const oldT2rev = oldT2.split('').reverse().join('')
for (const tag of reindexed) {
let idx = tag.index
newTags.push({contextR: context(oldT2, idx, N), contextL: context(oldT2rev, oldT2.length - idx, N), tag})
}
newTags = newTags.map((t, i) => ({...t, idx: i}))
const newT2rev = newT2.split('').reverse().join('')
const isOpen = t => t.tag[0][1] !== '/';
const pairMapping = newTags.filter(isOpen).map(t1 => ({open: t1, close: newTags.find((t2, j) => t2.tag[0].slice(2,-1) === t1.tag[0].slice(1,-1))}) ).map(({open, close}) => [...new Array(newT2.length)].map((_,i) => [...new Array(newT2.length)].map((_,j) => [[i,j], j < i ? -1 : distance(pad2sides(oldT2, M).slice(open.tag.index, close.tag.index), pad2sides(newT2, M).slice(i, j))])))
const fullmapping1 = newTags.map((t) => {
return [t.tag[0],
[...new Array(newT2.length)].map((_,i) => {
const pairIdx = newTags.filter(isOpen).findIndex(t1 => t1.tag[0].slice(1,-1) === t.tag[0].slice(-2,-1))
return (distance(t.contextR, context(newT2, i, N)) * .3 +
distance(t.contextL, context(newT2rev, newT2.length - i, N)) * .3 +
distance(t.contextR.slice(0, 3), context(newT2, i, 3)) * .2 +
distance(t.contextL.slice(0, 3), context(newT2rev, newT2.length - i, 3)) * .2 +
/*(isOpen(t) ? pairMapping[pairIdx][i].reduce((sum, v, k) => sum + v[1], 0) :
pairMapping[pairIdx].reduce((sum, v, k) => sum + v[i][1], 0)) *(1/25) * .4 + */
(isOpen(t) ? pairMapping[pairIdx][i].reduce(([j, max], v, k) => [v[1] > max ? k : j, v[1] > max ? v[1]: max], [-1, -1])[1] :
pairMapping[pairIdx].reduce(([j, max], v, k) => [v[i][1] > max ? k : j, v[i][1] > max ? v[i][1]: max], [-1, -1])[1]) * .4)
})]
})
//return fullmapping1
const fullmapping = fullmapping1.map(([t, out]) => [t, out.reduce(([i, max], v, j) => [v > max ? j : i, v > max ? v : max], [-1, null])])
//return fullmapping
const mapping = fullmapping.map(m => [m[0], m[1][0]])
//return mapping
const out = mapping.sort((a, b) => b[1] - a[1] !== 0 ? b[1] - a[1] : a[0][-2] < b[0][-2] ? -1 : 1).reduce((acc, [t, i]) => acc.slice(0, i) + t + acc.slice(i), newT2)
return [out, fullmapping]
}