Skip to content

Commit

Permalink
fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Kazuhiro Hayashi committed Feb 25, 2017
1 parent 2255791 commit 24ad67e
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 86 deletions.
16 changes: 8 additions & 8 deletions EditDistance.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
6E0301671E61689200E24C49 /* EditDistanceContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0301661E61689200E24C49 /* EditDistanceContainer.swift */; };
6EBF3E341E58543F0025443A /* EditDistance.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6EBF3E2A1E58543F0025443A /* EditDistance.framework */; };
6EBF3E391E58543F0025443A /* EditDistanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E381E58543F0025443A /* EditDistanceTests.swift */; };
6EBF3E3B1E58543F0025443A /* EditDistance.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EBF3E2D1E58543F0025443A /* EditDistance.h */; settings = {ATTRIBUTES = (Public, ); }; };
6EBF3E451E58549A0025443A /* EditScript.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E441E58549A0025443A /* EditScript.swift */; };
6EBF3E471E5854C70025443A /* EditScriptConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E461E5854C70025443A /* EditScriptConverter.swift */; };
6EBF3E491E5854FD0025443A /* EditDistanceAlgorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E481E5854FD0025443A /* EditDistanceAlgorithm.swift */; };
6EBF3E4D1E58553C0025443A /* Wu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E4C1E58553C0025443A /* Wu.swift */; };
Expand All @@ -19,7 +19,7 @@
6EBF3E951E59C3830025443A /* EditScriptConverterProxy+UICollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E941E59C3830025443A /* EditScriptConverterProxy+UICollectionView.swift */; };
6EBF3E971E59C3BE0025443A /* EditScriptConverterProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3E961E59C3BE0025443A /* EditScriptConverterProxy.swift */; };
6EBF3EDA1E5B2BBF0025443A /* DynamicProgramming.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3ED91E5B2BBF0025443A /* DynamicProgramming.swift */; };
6EBF3EF21E5C79330025443A /* EditDistanceContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3EF11E5C79330025443A /* EditDistanceContainer.swift */; };
6EBF3EF21E5C79330025443A /* EditDistanceAlgorithmContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EBF3EF11E5C79330025443A /* EditDistanceAlgorithmContainer.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -33,13 +33,13 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
6E0301661E61689200E24C49 /* EditDistanceContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditDistanceContainer.swift; sourceTree = "<group>"; };
6EBF3E2A1E58543F0025443A /* EditDistance.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = EditDistance.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6EBF3E2D1E58543F0025443A /* EditDistance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EditDistance.h; sourceTree = "<group>"; };
6EBF3E2E1E58543F0025443A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6EBF3E331E58543F0025443A /* EditDistanceTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EditDistanceTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
6EBF3E381E58543F0025443A /* EditDistanceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDistanceTests.swift; sourceTree = "<group>"; };
6EBF3E3A1E58543F0025443A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6EBF3E441E58549A0025443A /* EditScript.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditScript.swift; sourceTree = "<group>"; };
6EBF3E461E5854C70025443A /* EditScriptConverter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditScriptConverter.swift; sourceTree = "<group>"; };
6EBF3E481E5854FD0025443A /* EditDistanceAlgorithm.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditDistanceAlgorithm.swift; sourceTree = "<group>"; };
6EBF3E4C1E58553C0025443A /* Wu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wu.swift; sourceTree = "<group>"; };
Expand All @@ -48,7 +48,7 @@
6EBF3E941E59C3830025443A /* EditScriptConverterProxy+UICollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "EditScriptConverterProxy+UICollectionView.swift"; sourceTree = "<group>"; };
6EBF3E961E59C3BE0025443A /* EditScriptConverterProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditScriptConverterProxy.swift; sourceTree = "<group>"; };
6EBF3ED91E5B2BBF0025443A /* DynamicProgramming.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DynamicProgramming.swift; sourceTree = "<group>"; };
6EBF3EF11E5C79330025443A /* EditDistanceContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditDistanceContainer.swift; sourceTree = "<group>"; };
6EBF3EF11E5C79330025443A /* EditDistanceAlgorithmContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditDistanceAlgorithmContainer.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -105,7 +105,7 @@
6EBF3E2D1E58543F0025443A /* EditDistance.h */,
6EBF3E2E1E58543F0025443A /* Info.plist */,
6EBF3E901E59C2FB0025443A /* EditDistance.swift */,
6EBF3E441E58549A0025443A /* EditScript.swift */,
6E0301661E61689200E24C49 /* EditDistanceContainer.swift */,
6E0301631E5F2DA300E24C49 /* Converter */,
6EBF3E4E1E58565A0025443A /* Algorithm */,
);
Expand All @@ -125,7 +125,7 @@
isa = PBXGroup;
children = (
6EBF3E481E5854FD0025443A /* EditDistanceAlgorithm.swift */,
6EBF3EF11E5C79330025443A /* EditDistanceContainer.swift */,
6EBF3EF11E5C79330025443A /* EditDistanceAlgorithmContainer.swift */,
6EBF3E4C1E58553C0025443A /* Wu.swift */,
6EBF3ED91E5B2BBF0025443A /* DynamicProgramming.swift */,
);
Expand Down Expand Up @@ -247,12 +247,12 @@
files = (
6EBF3E951E59C3830025443A /* EditScriptConverterProxy+UICollectionView.swift in Sources */,
6EBF3E971E59C3BE0025443A /* EditScriptConverterProxy.swift in Sources */,
6EBF3E451E58549A0025443A /* EditScript.swift in Sources */,
6EBF3E911E59C2FB0025443A /* EditDistance.swift in Sources */,
6EBF3E931E59C3640025443A /* EditScriptConverterProxy+UITableView.swift in Sources */,
6EBF3E491E5854FD0025443A /* EditDistanceAlgorithm.swift in Sources */,
6EBF3EDA1E5B2BBF0025443A /* DynamicProgramming.swift in Sources */,
6EBF3EF21E5C79330025443A /* EditDistanceContainer.swift in Sources */,
6EBF3EF21E5C79330025443A /* EditDistanceAlgorithmContainer.swift in Sources */,
6E0301671E61689200E24C49 /* EditDistanceContainer.swift in Sources */,
6EBF3E4D1E58553C0025443A /* Wu.swift in Sources */,
6EBF3E471E5854C70025443A /* EditScriptConverter.swift in Sources */,
);
Expand Down
12 changes: 5 additions & 7 deletions EditDistance/DynamicProgramming.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@

import Foundation

public class DynamicProgramming<T: Comparable>: EditDistanceAlgorithm {
public struct DynamicProgramming<T: Comparable>: EditDistanceAlgorithm {
public typealias Element = T

public init() {}

public func calculate(from: [[T]], to: [[T]]) -> [EditScript<T>] {
public func calculate(from: [[T]], to: [[T]]) -> EditDistanceContainer<T> {
let flattendTo = to.enumerated().flatMap { (firstOffset, collection) in
return collection.enumerated().flatMap { (secondOffset, element) in
return EditDistanceContainer(indexPath: IndexPath(row: secondOffset, section: firstOffset), element: element)
return EditDistanceAlgorithmContainer(indexPath: IndexPath(row: secondOffset, section: firstOffset), element: element)
}
}

let flattendFrom = from.enumerated().flatMap { (firstOffset, collection) in
return collection.enumerated().flatMap { (secondOffset, element) in
return EditDistanceContainer(indexPath: IndexPath(row: secondOffset, section: firstOffset), element: element)
return EditDistanceAlgorithmContainer(indexPath: IndexPath(row: secondOffset, section: firstOffset), element: element)
}
}

Expand All @@ -38,8 +38,6 @@ public class DynamicProgramming<T: Comparable>: EditDistanceAlgorithm {
}
}

print(table)

var editScripts = [EditScript<T>]()

do {
Expand Down Expand Up @@ -80,6 +78,6 @@ public class DynamicProgramming<T: Comparable>: EditDistanceAlgorithm {
}
}

return editScripts
return EditDistanceContainer(editScripts: editScripts)
}
}
39 changes: 31 additions & 8 deletions EditDistance/EditDistance.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import Foundation
///
/// ## calculates edit distance
/// ```
/// editDistance.calculate() [.add("Francis", [0, 0]), .delete("Francis", [0, 0]), .common("Woodruff", [0, 1]), .add("Stanton", [0, 2])]
/// editDistance.calculate() // [.common("Francis", [0, 0]), .common("Woodruff", [0, 1]), .add("Stanton", [0, 2])]
/// ```
public class EditDistance<T: Comparable> {
public struct EditDistance<T: Comparable> {
private let _from: [[T]]
private let _to: [[T]]

Expand Down Expand Up @@ -57,8 +57,8 @@ public class EditDistance<T: Comparable> {
/// In order to that, you can customize algoritm as you like.
///
/// - Parameter algorithm: how to calculate Edit Distance
/// - Returns: array of commn, insertion, deletion to each the element.
public func calculate<Algorithm: EditDistanceAlgorithm>(with algorithm: Algorithm) -> [EditScript<T>] where Algorithm.Element == T {
/// - Returns: array of commn, insertion and deletion to each the element.
public func calculate<Algorithm: EditDistanceAlgorithm>(with algorithm: Algorithm) -> EditDistanceContainer<T> where Algorithm.Element == T {
return algorithm.calculate(from: _from, to: _to)
}

Expand All @@ -67,30 +67,53 @@ public class EditDistance<T: Comparable> {
/// The implementation is based on S.W.Maner, G.Myers, W.Miller, "An O(NP) Sequence Comparison Algorithm"

/// - Returns: array of commn, insertion, deletion to each the element.
public func calculate() -> [EditScript<T>] {
public func calculate() -> EditDistanceContainer<T> {
return Wu().calculate(from: _from, to: _to)
}
}

public class EditDistanceProxy<T: Comparable> {
/// proxy type to Array<T: Comparable>.
/// It receives a starting array, after that evaluate resutls with destination array and an algorithm.
public struct EditDistanceProxy<T: Comparable> {
private let _generator: ([T]) -> EditDistance<T>


/// Create object with a starting array
///
/// - Parameter from: starting array
public init(_ from: [T]) {
_generator = { (to: [T]) -> EditDistance<T> in
return EditDistance(from: from, to: to)
}
}

public func compare<Algorithm: EditDistanceAlgorithm>(to ary: [T], with algorithm: Algorithm) -> [EditScript<T>] where Algorithm.Element == T {

/// calculate Edit Distance with destination array and an algorithm.
///
/// - Parameters:
/// - ary: destination array
/// - algorithm: any algorithm following EditDistanceAlgorithm protocol
/// - Returns: array of commn, insertion and deletion to each the element.
public func compare<Algorithm: EditDistanceAlgorithm>(to ary: [T], with algorithm: Algorithm) -> EditDistanceContainer<T> where Algorithm.Element == T {
return _generator(ary).calculate(with: algorithm)
}

public func compare(to ary: [T]) -> [EditScript<T>] {
/// calculate Edit Distance with destination array and an algorithm.
///
/// - Parameters:
/// - ary: destination array
/// - algorithm: any algorithm following EditDistanceAlgorithm protocol
/// - Returns: array of commn, insertion and deletion to each the element.
public func compare(to ary: [T]) -> EditDistanceContainer<T> {
return _generator(ary).calculate(with: Wu())
}
}


// MARK: - Array Extension
public extension Array where Element: Comparable {

/// namespace for EditDistance. create EditDistanceProxy object with self.
public var diff: EditDistanceProxy<Element> {
return EditDistanceProxy(self)
}
Expand Down
10 changes: 5 additions & 5 deletions EditDistance/EditDistanceAlgorithm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ import Foundation
public protocol EditDistanceAlgorithm {
associatedtype Element: Comparable

func calculate(from: [[Element]], to: [[Element]]) -> [EditScript<Element>]
func calculate(from: [[Element]], to: [[Element]]) -> EditDistanceContainer<Element>
}

public class AnyEditDistanceAlgorithm<T>: EditDistanceAlgorithm where T: Comparable {
public struct AnyEditDistanceAlgorithm<T>: EditDistanceAlgorithm where T: Comparable {

public func calculate(from: [[T]], to: [[T]]) -> [EditScript<T>] {
public func calculate(from: [[T]], to: [[T]]) -> EditDistanceContainer<T> {
return _calc(from, to)
}

public typealias Element = T
public var _calc: ([[T]], [[T]]) -> [EditScript<T>]
public var _calc: ([[T]], [[T]]) -> EditDistanceContainer<T>

public init(_ calc: @escaping ([[T]], [[T]]) -> [EditScript<T>]) {
public init(_ calc: @escaping ([[T]], [[T]]) -> EditDistanceContainer<T>) {
_calc = calc
}
}
23 changes: 23 additions & 0 deletions EditDistance/EditDistanceAlgorithmContainer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// EditDistanceContainer.swift
// EditDistance
//
// Created by Kazuhiro Hayashi on 2/21/17.
// Copyright © 2017 Kazuhiro Hayashi. All rights reserved.
//

import Foundation

public struct EditDistanceAlgorithmContainer<T: Comparable>: Equatable {
public let indexPath: IndexPath
public let element: T

public init(indexPath: IndexPath, element: T) {
self.indexPath = indexPath
self.element = element
}
}

public func ==<T: Comparable>(lhs: EditDistanceAlgorithmContainer<T>, rhs: EditDistanceAlgorithmContainer<T>) -> Bool {
return lhs.element == rhs.element
}
46 changes: 37 additions & 9 deletions EditDistance/EditDistanceContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,50 @@
// EditDistanceContainer.swift
// EditDistance
//
// Created by Kazuhiro Hayashi on 2/21/17.
// Created by Kazuhiro Hayashi on 2/25/17.
// Copyright © 2017 Kazuhiro Hayashi. All rights reserved.
//

import Foundation

public struct EditDistanceContainer<T: Comparable>: Equatable {
public let indexPath: IndexPath
public let element: T
/// container object for edit distance calculation results
public struct EditDistanceContainer<Element: Comparable> {
public let editScripts: [EditScript<Element>]

public init(indexPath: IndexPath, element: T) {
self.indexPath = indexPath
self.element = element
public init(editScripts: [EditScript<Element>]) {
self.editScripts = editScripts
}
}

public func ==<T: Comparable>(lhs: EditDistanceContainer<T>, rhs: EditDistanceContainer<T>) -> Bool {
return lhs.element == rhs.element
/// Edit script definition. It composes the difference between two arrays as common, add or delete.
///
/// - add: an element on the desitination array is added
/// - common: element on two arrays is common
/// - delete: an element on the starting array is deleted
public enum EditScript<Element> {
case common(element: Element, indexPath: IndexPath)
case add(element: Element, indexPath: IndexPath)
case delete(element: Element, indexPath: IndexPath)

var indexPath: IndexPath {
switch self {
case .add(element: _, indexPath: let indexPath):
return indexPath
case .common(element: _, indexPath: let indexPath):
return indexPath
case .delete(element: _, indexPath: let indexPath):
return indexPath
}
}

var element: Element {
switch self {
case .add(element: let element, indexPath: _):
return element
case .common(element: let elelemtn, indexPath: _):
return elelemtn
case .delete(element: let element, indexPath: _):
return element
}
}
}
37 changes: 0 additions & 37 deletions EditDistance/EditScript.swift

This file was deleted.

12 changes: 10 additions & 2 deletions EditDistance/EditScriptConverterProxy+UICollectionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@
import UIKit

public extension EditScriptConverterProxy where Converter: UICollectionView {
public func performBatchUpdates<T>(with editScripts: [EditScript<T>], completion: ((Bool) -> Void)?) {

/// Updates this UICollectionView object with EditDistanceContainer object.
///
/// EditScript array in the object is converted to insertItems(at:) and deleteItems(at:) of UICollectionView
///
/// - Parameters:
/// - container: <#container description#>
/// - completion: <#completion description#>
public func performBatchUpdates<T>(with container: EditDistanceContainer<T>, completion: ((Bool) -> Void)?) {
_converter.performBatchUpdates({ [weak self] in
editScripts.forEach({ (script) in
container.editScripts.forEach({ (script) in
switch script {
case .add(_, let indexPath):
self?._converter.insertItems(at: [indexPath])
Expand Down
9 changes: 7 additions & 2 deletions EditDistance/EditScriptConverterProxy+UITableView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
import UIKit

public extension EditScriptConverterProxy where Converter: UITableView {
public func reload<T>(with editScripts: [EditScript<T>]) {

/// Updates this UICollectionView object with EditDistanceContainer object.
///
/// EditScript array in the object is converted to insertRows(at:,with:) and deleteRows(at:,with:) of UITableView
/// - Parameter container: EditDistanceContainer object generated by EditDistance
public func reload<T>(with container: EditDistanceContainer<T>) {
_converter.beginUpdates()
editScripts.forEach({ (script) in
container.editScripts.forEach({ (script) in
switch script {
case .add(_, let indexPath):
_converter.insertRows(at: [indexPath], with: .fade)
Expand Down
Loading

0 comments on commit 24ad67e

Please sign in to comment.