Skip to content

Commit ca48856

Browse files
committed
refactoring more by using more helper structures
1 parent 715a59a commit ca48856

1 file changed

Lines changed: 98 additions & 120 deletions

File tree

Diff/DiffArray.swift

Lines changed: 98 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -232,145 +232,136 @@ private func diff_computeDiffsBetweenArrays<T: Equatable>(arrayA: [T], arrayB: [
232232
return diff_bisectOfArrays(arrayA: arrayA, arrayB: arrayB)
233233
}
234234

235-
private struct FrontPathParameters<T> {
236-
let currentD: Int
235+
private class Kay {
236+
var start: Int = 0
237+
var end: Int = 0
238+
var index: Int = 0
239+
}
240+
241+
private struct CommonPathParameters<T: Equatable> {
237242
let vOffset: Int
238243
let inArrayA: [T]
239244
let inArrayB: [T]
245+
let front: Bool
246+
let delta: Int
247+
let vLength: Int
240248
}
241249

242-
// swiftlint:disable function_parameter_count
243-
private func walkFrontPath<T>(parameters: FrontPathParameters<T>,
244-
kIndex1: inout Int,
245-
k1end: inout Int,
246-
vectors1: inout [Int],
247-
k1start: inout Int,
248-
front: Bool,
249-
delta: Int,
250-
vLength: Int,
251-
vectors2: inout [Int],
252-
diffs: inout [Diff<T>]) -> Bool {
253-
254-
var haveFoundDiffs = false // assume
255-
while kIndex1 <= parameters.currentD - k1end {
250+
private func walkFrontPath<T: Equatable>(
251+
commonParameters: CommonPathParameters<T>,
252+
currentD: Int,
253+
kay1: Kay,
254+
vectors1: inout [Int],
255+
vectors2: inout [Int]) -> [Diff<T>] {
256+
257+
while kay1.index <= currentD - kay1.end {
256258
defer {
257-
kIndex1 += 2
259+
kay1.index += 2
258260
}
259-
let k1Offset = parameters.vOffset + kIndex1
261+
let k1Offset = commonParameters.vOffset + kay1.index
260262
var x1 = 0
261263

262-
if kIndex1 == -parameters.currentD || (kIndex1 != parameters.currentD && vectors1[k1Offset - 1] < vectors1[k1Offset + 1]) {
264+
if kay1.index == -currentD || (kay1.index != currentD && vectors1[k1Offset - 1] < vectors1[k1Offset + 1]) {
263265
x1 = vectors1[k1Offset + 1]
264266
} else {
265267
x1 = vectors1[k1Offset - 1] + 1
266268
}
267269

268-
var y1 = x1 - kIndex1
270+
var y1 = x1 - kay1.index
269271

270272
// follow the snake!
271-
while x1 < parameters.inArrayA.count && y1 < parameters.inArrayB.count && parameters.inArrayA[x1] == parameters.inArrayB[y1] {
273+
while x1 < commonParameters.inArrayA.count && y1 < commonParameters.inArrayB.count && commonParameters.inArrayA[x1] == commonParameters.inArrayB[y1] {
272274
x1 += 1
273275
y1 += 1
274276
}
275277

276278
vectors1[k1Offset] = x1
277279

278-
if x1 > parameters.inArrayA.count {
280+
if x1 > commonParameters.inArrayA.count {
279281
// Ran off the right of the graph.
280-
k1end += 2
281-
} else if y1 > parameters.inArrayB.count {
282+
kay1.end += 2
283+
} else if y1 > commonParameters.inArrayB.count {
282284
// Ran off the bottom of the graph.
283-
k1start += 2
284-
} else if front {
285-
let k2Offset = parameters.vOffset + delta - kIndex1
285+
kay1.start += 2
286+
} else if commonParameters.front {
287+
let k2Offset = commonParameters.vOffset + commonParameters.delta - kay1.index
286288

287-
if k2Offset >= 0 && k2Offset < vLength && vectors2[k2Offset] != -1 {
289+
if k2Offset >= 0 && k2Offset < commonParameters.vLength && vectors2[k2Offset] != -1 {
288290
// Mirror x2 onto top-left coordinate system.
289-
let x2 = parameters.inArrayA.count - vectors2[k2Offset]
291+
let x2 = commonParameters.inArrayA.count - vectors2[k2Offset]
290292
if x1 >= x2 {
291293
// diffs = diff_bisectSplitOfStrings(text1, text2, x1, y1, properties);
292-
diffs = diff_bisectSplitOfArrays(arrayA: parameters.inArrayA, arrayB: parameters.inArrayB, x: x1, y: y1)
293-
haveFoundDiffs = true
294-
break
294+
return diff_bisectSplitOfArrays(arrayA: commonParameters.inArrayA, arrayB: commonParameters.inArrayB, x: x1, y: y1)
295295
}
296296
}
297297
}
298298
}
299-
300-
return haveFoundDiffs
299+
return []
301300
}
302301

303-
private func walkReversePath<T: Equatable>(kIndex2: inout Int,
304-
currentD: Int,
305-
k2end: inout Int,
306-
vOffset: Int,
307-
vectors2: inout [Int],
308-
inArrayA: [T],
309-
inArrayB: [T],
310-
k2start: inout Int,
311-
front: Bool,
312-
delta: Int,
313-
vLength: Int,
314-
vectors1: inout [Int],
315-
diffs: inout [Diff<T>],
316-
haveFoundDiffs: inout Bool) {
317-
while kIndex2 <= currentD - k2end {
302+
private func walkReversePath<T: Equatable>(
303+
commonParameters: CommonPathParameters<T>,
304+
currentD: Int,
305+
kay2: Kay,
306+
vectors1: inout [Int],
307+
vectors2: inout [Int]) -> [Diff<T>] {
308+
309+
while kay2.index <= currentD - kay2.end {
318310

319311
defer {
320-
kIndex2 += 2
312+
kay2.index += 2
321313
}
322-
let k2Offset = vOffset + kIndex2
314+
let k2Offset = commonParameters.vOffset + kay2.index
323315
var x2 = 0
324316

325-
if kIndex2 == -currentD || (kIndex2 != currentD && vectors2[k2Offset - 1] < vectors2[k2Offset + 1]) {
317+
if kay2.index == -currentD || (kay2.index != currentD && vectors2[k2Offset - 1] < vectors2[k2Offset + 1]) {
326318
x2 = vectors2[k2Offset + 1]
327319
} else {
328320
x2 = vectors2[k2Offset - 1] + 1
329321
}
330322

331-
var y2 = x2 - kIndex2
323+
var y2 = x2 - kay2.index
332324

333-
while x2 < inArrayA.count && y2 < inArrayB.count && (inArrayA[inArrayA.count - x2 - 1] == inArrayB[inArrayB.count - y2 - 1]) {
325+
while x2 < commonParameters.inArrayA.count && y2 < commonParameters.inArrayB.count && (commonParameters.inArrayA[commonParameters.inArrayA.count - x2 - 1] == commonParameters.inArrayB[commonParameters.inArrayB.count - y2 - 1]) {
334326
x2 += 1
335327
y2 += 1
336328
}
337329

338330
vectors2[k2Offset] = x2
339331

340-
if x2 > inArrayA.count {
332+
if x2 > commonParameters.inArrayA.count {
341333
// Ran off the left of the graph.
342-
k2end += 2
343-
} else if y2 > inArrayB.count {
334+
kay2.end += 2
335+
} else if y2 > commonParameters.inArrayB.count {
344336
// Ran off the top of the graph.
345-
k2start += 2
346-
} else if !front {
347-
let k1Offset = vOffset + delta - kIndex2
337+
kay2.start += 2
338+
} else if !commonParameters.front {
339+
let k1Offset = commonParameters.vOffset + commonParameters.delta - kay2.index
348340

349-
if k1Offset >= 0 && k1Offset < vLength && vectors1[k1Offset] != -1 {
341+
if k1Offset >= 0 && k1Offset < commonParameters.vLength && vectors1[k1Offset] != -1 {
350342
let x1 = vectors1[k1Offset]
351-
let y1 = vOffset + x1 - k1Offset
343+
let y1 = commonParameters.vOffset + x1 - k1Offset
352344
// Mirror x2 onto top-left coordinate system.
353-
x2 = inArrayA.count - x2
345+
x2 = commonParameters.inArrayA.count - x2
354346

355347
if x1 >= x2 {
356348
// Overlap detected.
357-
diffs = diff_bisectSplitOfArrays(arrayA: inArrayA, arrayB: inArrayB, x: x1, y: y1)
358-
haveFoundDiffs = true
359-
break
349+
return diff_bisectSplitOfArrays(arrayA: commonParameters.inArrayA, arrayB: commonParameters.inArrayB, x: x1, y: y1)
360350
}
361351
}
362352
}
363353
}
354+
return []
364355
}
365356

366357
// yes this method is way too long. Pull requests welcome!
367-
func diff_bisectOfArrays<T: Equatable>(arrayA inArrayA: [T], arrayB inArrayB: [T]) -> [Diff<T>] {
368-
let arrayALength = inArrayA.count
369-
let arrayBLength = inArrayB.count
370-
var haveFoundDiffs = false
371-
var diffs: [Diff<T>] = []
358+
private func debugPrint(kay: Kay, vectors1: [Int], vectors2: [Int]) {
359+
print("--- kIndex: \(kay.index), kstart: \(kay.start), kend: \(kay.end), ")
360+
print("--- vectors1: \(vectors1), vectors2: \(vectors2)")
361+
}
372362

373-
let maxD = (arrayALength + arrayBLength + 1) / 2
363+
func diff_bisectOfArrays<T: Equatable>(arrayA inArrayA: [T], arrayB inArrayB: [T]) -> [Diff<T>] {
364+
let maxD = (inArrayA.count + inArrayB.count + 1) / 2
374365
let vOffset = maxD
375366
var vLength = 2 * maxD
376367

@@ -385,72 +376,59 @@ func diff_bisectOfArrays<T: Equatable>(arrayA inArrayA: [T], arrayB inArrayB: [T
385376
vectors1.append(-1)
386377
vectors2.append(-1)
387378
}
388-
389379
vectors1[vOffset + 1] = 0
390380
vectors2[vOffset + 1] = 0
391381

392-
let delta = arrayALength - arrayBLength
382+
let delta = inArrayA.count - inArrayB.count
393383

394384
// If the total number of characters is odd, then the front path will collide with the reverse path.
395385
let front = delta % 2 != 0
396386

397387
// Offsets for start and end of k loop. Prevents mapping of space beyond the grid.
398-
var k1start = 0
399-
var k1end = 0
400-
var k2start = 0
401-
var k2end = 0
388+
let kay1 = Kay()
389+
let kay2 = Kay()
390+
391+
let commonParameters = CommonPathParameters(vOffset: vOffset, inArrayA: inArrayA, inArrayB: inArrayB, front: front, delta: delta, vLength: vLength)
402392

403-
//
404393
for currentD in 0..<maxD {
405394

406395
// Walk the front path one step.
407-
var kIndex1 = -currentD + k1start
408-
409-
let parameters = FrontPathParameters(currentD: currentD, vOffset: vOffset, inArrayA: inArrayA, inArrayB: inArrayB)
410-
if walkFrontPath(
411-
parameters: parameters,
412-
kIndex1: &kIndex1,
413-
k1end: &k1end,
414-
vectors1: &vectors1,
415-
k1start: &k1start,
416-
front: front,
417-
delta: delta,
418-
vLength: vLength,
419-
vectors2: &vectors2,
420-
diffs: &diffs) {
421-
haveFoundDiffs = true
422-
break
396+
kay1.index = -currentD + kay1.start
397+
debugPrint(kay: kay1, vectors1: vectors1, vectors2: vectors2)
398+
399+
let frontDiffs = walkFrontPath(
400+
commonParameters: commonParameters,
401+
currentD: currentD,
402+
kay1: kay1,
403+
vectors1: &vectors1,
404+
vectors2: &vectors2)
405+
406+
debugPrint(kay: kay1, vectors1: vectors1, vectors2: vectors2)
407+
408+
if !frontDiffs.isEmpty {
409+
return frontDiffs
423410
}
424411

425412
// Walk the reverse path one step.
426-
var kIndex2 = -currentD + k2start
427-
walkReversePath(kIndex2: &kIndex2,
428-
currentD: currentD,
429-
k2end: &k2end,
430-
vOffset: vOffset,
431-
vectors2: &vectors2,
432-
inArrayA: inArrayA,
433-
inArrayB: inArrayB,
434-
k2start: &k2start,
435-
front: front,
436-
delta: delta,
437-
vLength: vLength,
438-
vectors1: &vectors1,
439-
diffs: &diffs,
440-
haveFoundDiffs: &haveFoundDiffs)
441-
442-
if haveFoundDiffs {
443-
break
413+
kay2.index = -currentD + kay2.start
414+
debugPrint(kay: kay2, vectors1: vectors1, vectors2: vectors2)
415+
let reverseDiffs = walkReversePath(
416+
commonParameters: commonParameters,
417+
currentD: currentD,
418+
kay2: kay2,
419+
vectors1: &vectors1,
420+
vectors2: &vectors2)
421+
422+
debugPrint(kay: kay2, vectors1: vectors1, vectors2: vectors2)
423+
424+
if !reverseDiffs.isEmpty {
425+
return reverseDiffs
444426
}
445427
}
446428

447-
if !haveFoundDiffs {
448-
// we haven't found a snake at all so we couldn't cut the problem in half.
449-
// This means we have no common element. Just add the diffs straight away.
450-
diffs = [Diff(operation: .delete, array: inArrayA), Diff(operation: .insert, array: inArrayB)]
451-
}
452-
453-
return diffs
429+
// we haven't found a snake at all so we couldn't cut the problem in half.
430+
// This means we have no common element. Just add the diffs straight away.
431+
return [Diff(operation: .delete, array: inArrayA), Diff(operation: .insert, array: inArrayB)]
454432
}
455433
// swiftlint:enable function_body_length
456434

0 commit comments

Comments
 (0)