Skip to content

Commit

Permalink
update: reverse sequence
Browse files Browse the repository at this point in the history
  • Loading branch information
wzxha committed May 25, 2018
1 parent 829f3a9 commit e8a7d5c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 21 deletions.
44 changes: 30 additions & 14 deletions Sources/Sdifft/Diff.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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..<row {
for j in 1..<column {
if from[i-1] == to[j-1] {
result[i][j] = result[i-1][j-1] + 1
if from[i - 1] == to[j - 1] {
result[i][j] = result[i - 1][j - 1] + 1
} else {
result[i][j] = max(result[i][j-1], result[i-1][j])
result[i][j] = max(result[i][j - 1], result[i - 1][j])
}
}
}
Expand All @@ -72,11 +72,11 @@ typealias Position = (row: Int, column: Int)
/// - Returns: same character's indexes
func lcs(from: String, to: String, position: Position, matrix: Matrix, same: (from: [Int], to: [Int])) -> (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)
Expand Down Expand Up @@ -144,9 +144,25 @@ public struct Modification {
public let same: [CountableClosedRange<Int>]
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 {
Expand All @@ -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)
}
}
28 changes: 21 additions & 7 deletions Tests/SdifftTests/SdifftTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand All @@ -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],
Expand All @@ -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],
Expand All @@ -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],
]
)
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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
Expand All @@ -187,6 +200,7 @@ class DiffTests: XCTestCase {
("testRange", testRange),
("testString1", testString1),
("testString2", testString2),
("testString3", testString3),
("testTime", testTime)
]
}

0 comments on commit e8a7d5c

Please sign in to comment.