Hone logo
Hone
Problems

Implementing a Simple Diff Algorithm with Jest

This challenge asks you to implement a basic diff algorithm in TypeScript and test it thoroughly using Jest. A diff algorithm is crucial for comparing text files or strings and identifying the differences between them, a common task in version control systems, code review tools, and text editors. Your implementation should focus on identifying insertions and deletions to transform one string into another.

Problem Description

You need to implement a function diff(oldString: string, newString: string): string[] that takes two strings, oldString and newString, as input and returns an array of strings representing the diff. Each string in the array represents an operation:

  • '+ line': Indicates a line that was added to the newString.
  • '- line': Indicates a line that was removed from the oldString.
  • ' line': Indicates a line that is common to both strings.

The diff should be line-oriented. That is, the input strings are treated as sequences of lines, and the diff identifies changes at the line level. The output array should contain the operations in the order they would be applied to transform oldString into newString.

Key Requirements:

  • The function must handle empty strings correctly.
  • The function must handle cases where newString is a subset of oldString (only deletions).
  • The function must handle cases where oldString is a subset of newString (only insertions).
  • The function should be reasonably efficient for strings of moderate length (up to a few hundred lines). Optimization for extremely large strings is not required.
  • The output array should not contain empty strings.

Expected Behavior:

The function should return an array of strings, where each string represents a line with a prefix indicating the operation. The prefixes are '+', '-', and ' ' as described above.

Edge Cases to Consider:

  • Empty input strings.
  • Identical input strings.
  • newString is a prefix of oldString.
  • oldString is a prefix of newString.
  • Strings with many insertions and deletions.
  • Strings with long lines.

Examples

Example 1:

Input: oldString = "line1\nline2\nline3", newString = "line1\nline4\nline3"
Output: ["- line2", "+ line4"]
Explanation: "line2" was removed, and "line4" was added.

Example 2:

Input: oldString = "line1\nline2", newString = "line1\nline2\nline3"
Output: ["+ line3"]
Explanation: "line3" was added.

Example 3:

Input: oldString = "line1\nline2\nline3", newString = "line1"
Output: ["- line2", "- line3"]
Explanation: "line2" and "line3" were removed.

Example 4:

Input: oldString = "line1\nline2", newString = "line1\nline2"
Output: ["  line1", "  line2"]
Explanation: The strings are identical.

Example 5:

Input: oldString = "", newString = "line1"
Output: ["+ line1"]
Explanation: An empty string is transformed into a string with one line.

Constraints

  • The maximum length of oldString and newString is 500 lines.
  • Each line in oldString and newString can have a maximum length of 200 characters.
  • The function must return the diff in the specified format.
  • The time complexity should be reasonable for the given constraints (avoiding excessively inefficient algorithms).

Notes

Consider using a dynamic programming approach or a simpler iterative method to compare the lines. Focus on correctly identifying insertions, deletions, and common lines. Remember to split the input strings into lines using \n as the delimiter. Testing with a variety of inputs, including edge cases, is crucial for ensuring the correctness of your implementation. The goal is to produce a clear and concise diff representation. Don't worry about sophisticated diff formats like unified diffs; a simple line-oriented diff is sufficient.

Loading editor...
typescript