Public
Edited
Sep 23, 2023
Insert cell
Insert cell
Insert cell
Insert cell
function generateOperations(text, updateText) {
const addOps = [];
const removeOps = [];
let i = 0, j = 0;
let offsetAdjustment = 0;

while (i < text.length || j < updateText.length) {
if (i < text.length && j < updateText.length && text[i] === updateText[j]) {
// Characters match, move to the next character in both strings
i++;
j++;
} else if (i < text.length && (j >= updateText.length || text[i] !== updateText[j])) {
// Character in text doesn't match character in updateText or updateText is shorter, remove character from text
removeOps.push({
type: "remove_text",
offset: i,
text: text[i],
path: []
});
i++;
} else if (j < updateText.length && (i >= text.length || text[i] !== updateText[j])) {
// Character in updateText doesn't match character in text or text is shorter, insert character into text
addOps.push({
type: "insert_text",
offset: i + offsetAdjustment,
text: updateText[j],
path: []
});
j++;
offsetAdjustment += 1;
}
}

// Reverse the removeOps array to process deletions from right to left
removeOps.reverse();
return addOps.concat(removeOps);
}
Insert cell
function applyOperations(a, ops) {
let resultArray = a.split('');

for (const op of ops) {
if (op.type === 'insert_text'){
resultArray.splice(op.offset, 0, ...op.text.split(''));
} else{
resultArray.splice(op.offset, op.text.length);
}
}

return resultArray.join('');
}
Insert cell
tests.map(testCase => {
let ops = generateOperations(testCase.s1, testCase.s2)
let result = applyOperations(testCase.s1, ops)
const isCorrect = result === testCase.s2;

return `${isCorrect} | >> | ${testCase.s1}, ${testCase.s2}: |${result}#${testCase.s2}| (${ops.length}) | ${testCase.lcs} `;
})
Insert cell
function generateOperations2(
text,
updateText
) {
const m = text.length;
const n = updateText.length;
const lcs = lcsFunctions.findLCS(text, updateText);

const ops = [];
const removeOps = [];
let i = 0,
j = 0;
let curPos = 0;

for (const char of lcs) {
while (text[i] !== char) {
removeOps.push({
type: "remove_text",
offset: curPos,
text: text[i],
path: [],
});
i++;
curPos ++;
}
while (updateText[j] !== char) {
ops.push({
type: "insert_text",
offset: curPos,
text: updateText[j],
path: [],
});
j++;
curPos++;
}
i++;
j++;
curPos++;
}

while (i < m) {
removeOps.push({ type: "remove_text", offset: curPos, text: text[i], path: [] });
i++;
curPos++;
}
while (j < n) {
ops.push({ type: "insert_text", offset: curPos, text: updateText[j], path: [] });
j++;
curPos++;
}

// Reverse the remove operations and merge with other ops.
return ops.concat(removeOps.reverse());
}



Insert cell
tests.map(testCase => {
let ops = generateOperations2(testCase.s1, testCase.s2)
let result = applyOperations(testCase.s1, ops)
const isCorrect = result === testCase.s2;
const repr = `${isCorrect} | >> | ${testCase.s1}, ${testCase.s2}: |${result}#${testCase.s2}| (${ops.length}) | ${testCase.lcs} `
// return {result: repr,
// ops: ops,
// test: testCase,
// output: result
// };
return repr
})
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more