From e8a7d5c82c045fb6bb34cc05aa3256aed9f6d4c6 Mon Sep 17 00:00:00 2001 From: wzxjiang Date: Fri, 25 May 2018 11:33:53 +0800 Subject: [PATCH] update: reverse sequence --- Sources/Sdifft/Diff.swift | 44 ++++++++++++++++++++--------- Tests/SdifftTests/SdifftTests.swift | 28 +++++++++++++----- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/Sources/Sdifft/Diff.swift b/Sources/Sdifft/Diff.swift index 4dfa06c..2f2bfd8 100644 --- a/Sources/Sdifft/Diff.swift +++ b/Sources/Sdifft/Diff.swift @@ -49,10 +49,10 @@ func drawMatrix(from: String, to: String) -> Matrix { var result: [[Int]] = Array(repeating: Array(repeating: 0, count: column), count: row) for i in 1.. (from: [Int], to: [Int]) { if position.row == 0 || position.column == 0 { - return (same.from.reversed(), same.to.reversed()) + return same } - if from[position.row-1] == to[position.column-1] { + if from[position.row - 1] == to[position.column - 1] { return lcs(from: from, to: to, position: (position.row - 1, position.column - 1), matrix: matrix, same: (same.from + [position.row - 1], same.to + [position.column - 1])) - } else if matrix[position.row-1][position.column] >= matrix[position.row][position.column-1] { + } else if matrix[position.row - 1][position.column] >= matrix[position.row][position.column - 1] { return lcs(from: from, to: to, position: (position.row - 1, position.column), matrix: matrix, same: same) } else { return lcs(from: from, to: to, position: (position.row, position.column - 1), matrix: matrix, same: same) @@ -144,9 +144,25 @@ public struct Modification { public let same: [CountableClosedRange] public let base: Base - init(from: String, to: String, matrix: Matrix) { - let same = + + /// Return modification with strings + /// + /// - Parameters: + /// - from: string + /// - to: string that be compared + /// - matrix: matrix + /// - isReversed: from and to is reversed + init(from: String, to: String, matrix: Matrix, isReversed: Bool) { + var same = lcs(from: from, to: to, position: (from.count, to.count), matrix: matrix, same: ([], [])) + + if isReversed { + same = ( + same.from.map({ from.count - 1 - $0 }), + same.to.map({ to.count - 1 - $0 }) + ) + } + add = same.to.getChangeRanges(max: to.count - 1) delete = same.from.getChangeRanges(max: from.count - 1) if add.isEmpty { @@ -160,15 +176,15 @@ public struct Modification { } public struct Diff { - public let from: String - public let to: String public let modification: Modification let matrix: Matrix public init(from: String, to: String) { - self.from = from - self.to = to - matrix = drawMatrix(from: from, to: to) - modification = Modification(from: from, to: to, matrix: matrix) + // because LCS is 'bottom-up' + // so them need be reversed to get the normal sequence + let reversedFrom = String(from.reversed()) + let reversedTo = String(to.reversed()) + matrix = drawMatrix(from: reversedFrom, to: reversedTo) + modification = Modification(from: reversedFrom, to: reversedTo, matrix: matrix, isReversed: true) } } diff --git a/Tests/SdifftTests/SdifftTests.swift b/Tests/SdifftTests/SdifftTests.swift index b8c48b5..aa0688c 100644 --- a/Tests/SdifftTests/SdifftTests.swift +++ b/Tests/SdifftTests/SdifftTests.swift @@ -12,7 +12,7 @@ extension String { class DiffTests: XCTestCase { func testMatrix() { assert( - Diff(from: "abcd", to: "acd").matrix == [ + drawMatrix(from: "abcd", to: "acd") == [ [0, 0, 0, 0], [0, 1, 1, 1], [0, 1, 1, 1], @@ -22,7 +22,7 @@ class DiffTests: XCTestCase { ) assert( - Diff(from: "abcdegh", to: "ae").matrix == [ + drawMatrix(from: "abcdegh", to: "ae") == [ [0, 0, 0], [0, 1, 1], [0, 1, 1], @@ -35,7 +35,7 @@ class DiffTests: XCTestCase { ) assert( - Diff(from: "adf", to: "d").matrix == [ + drawMatrix(from: "adf", to: "d") == [ [0, 0], [0, 0], [0, 1], @@ -44,14 +44,14 @@ class DiffTests: XCTestCase { ) assert( - Diff(from: "d", to: "adf").matrix == [ + drawMatrix(from: "d", to: "adf") == [ [0, 0, 0, 0], [0, 0, 1, 1] ] ) assert( - Diff(from: "", to: "").matrix == [ + drawMatrix(from: "", to: "") == [ [0], ] ) @@ -140,8 +140,8 @@ class DiffTests: XCTestCase { let from3 = "A\r\n\r\nB\r\n\r\nC" let diff3 = Diff(from: from3, to: to3) assert(diff3.modification.add == []) - assert(diff3.modification.delete == [1...1, 4...4]) - assert(diff3.modification.same == [0...0, 2...3, 5...6]) + assert(diff3.modification.delete == [2...2, 5...5]) + assert(diff3.modification.same == [0...1, 3...4, 6...6]) } func testString1() { @@ -170,6 +170,19 @@ class DiffTests: XCTestCase { to[diff.modification.same[1]] == "j" ) } + + func testString3() { + let to = "A\r\nB\r\nC" + let from = "A\r\n\r\nB\r\n\r\nC" + let diff = Diff(from: from, to: to) + assert( + diff.modification.add.count == 0 && + from[diff.modification.delete[0]] == "\r\n" && + (diff.modification.base == .to ? to[diff.modification.same[0]]: from[diff.modification.same[0]]) == "A\r\n" && + (diff.modification.base == .to ? to[diff.modification.same[1]]: from[diff.modification.same[1]]) == "B\r\n" && + (diff.modification.base == .to ? to[diff.modification.same[2]]: from[diff.modification.same[2]]) == "C" + ) + } func testTime() { // 1000 character * 1000 character: 3.681s @@ -187,6 +200,7 @@ class DiffTests: XCTestCase { ("testRange", testRange), ("testString1", testString1), ("testString2", testString2), + ("testString3", testString3), ("testTime", testTime) ] }