vendredi 28 avril 2017

MergeSort loop where comparison is done in real-time with user input. Don't know design pattern to make this work

So I want to implement a merge sort on an array of items that will be compared in pairs in real-time by the end user. There is a MergeSortMgr object with a delegate to the viewControl who will present the comparisons. All works fine if I simply return from the view control's delegate method. However, I am having crazy trouble figuring out the pattern to only return from the delegate method after I have presented the user with the two items and a selection has been made. I have tried while loops (causes my UI to blank out), callbacks (couldn't figure out a pattern than would let me delay the sync delegateMethod return. Anyway...I got a really cool feature that needs this. Help please.

Here is the MergeSortMgr object:

protocol MergeSortMgrDelegate {
  func presentMatch(item1: Int, item2: Int) -> Bool
}

class MergeSortMgr: NSObject {

  var delegate: MergeSortMgrDelegate?

  override init() {

  }

  func merge(leftArray leftArray: [Int], rightArray: [Int]) -> [Int] {
    // Index of items to compare
    var leftIndex = 0
    var rightIndex = 0

    print("Merging \(leftArray) and \(rightArray)")

    // Array containing the sorted items
    var sortedArray = [Int]()

    // Compare the elements and add them to the sorted array *in order*
    while leftIndex < leftArray.count && rightIndex < rightArray.count {
     var comparison = delegate?.presentMatch(item1: leftArray[leftIndex], item2: rightArray[rightIndex])
     print(comparison)
     if comparison! { //leftArray[leftIndex] < rightArray[rightIndex]
       sortedArray.append(leftArray[leftIndex])
       print("Moving left item into array: \(leftArray[leftIndex])")
       leftIndex += 1
     } else if !comparison!  { //leftArray[leftIndex] > rightArray[rightIndex]
       sortedArray.append(rightArray[rightIndex])
       print("Moving right item into array: \(rightArray[rightIndex])")
       rightIndex += 1
     } else {
       print("Numbers were identical: \(leftArray[leftIndex]) == \(rightArray[rightIndex])")
    sortedArray.append(leftArray[leftIndex])
    leftIndex += 1
    sortedArray.append(rightArray[rightIndex])
    rightIndex += 1

    }
  }

  // At this point, the elements were compared and sorted properly,
  // so we just need to append the rest of the items to the array
  while leftIndex < leftArray.count {
    sortedArray.append(leftArray[leftIndex])
    print("Moving left item into array: \(leftArray[leftIndex])")
    leftIndex += 1
  }
  while rightIndex < rightArray.count {
    sortedArray.append(rightArray[rightIndex])
    print("Moving right item into array: \(rightArray[rightIndex])")
    rightIndex += 1
  }

  return sortedArray
}


func mergeSort(array: [Int]) -> [Int] {
  // If our array only has one item, we're done
  guard array.count > 1 else { return array }

  // Find the middle of the array
  let middleIndex = array.count / 2

  // Recursively sort the left and right parts of the array
  let leftArray = mergeSort(array: Array(array[0..<middleIndex]))
  let rightArray = mergeSort(array: Array(array[middleIndex..<array.count]))

  return merge(leftArray: leftArray, rightArray: rightArray)
  }
}

Here is the ViewController which implements the MergeSortMgr delegate method, should display to the user the comparison, then return the selection back via the delegate. (This last part is my problem.)


class ViewController: UIViewController, MergeSortMgrDelegate {


var mergeSortMgr = MergeSortMgr() var array: [Int] = []


var selection: Int?


@IBOutlet weak var button_item1: UIButton! @IBOutlet weak var button_item2: UIButton!


override func viewDidLoad() { super.viewDidLoad()

mergeSortMgr.delegate = self //test array actual array will be not comparable objects array = [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10] array = mergeSortMgr.mergeSort(array: array) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func presentMatch(item1: Int, item2: Int) -> Bool { selection = nil button_item1.setTitle(String(item1), for: .normal) button_item1.tag = item1 button_item2.setTitle(String(item2), for: .normal) button_item2.tag = item2 //async callback pattern doesn't seem to work getResult() { if selection == item1 { return false } else { return true } return false } //While loop blanks out my screen var result = false while selection == nil { if selection == item1 { result = false } else { result = true } } return result } func getResult(completion: (Void) -> Bool) { completion() } @IBAction func onItem1(_ sender: UIButton) { self.selection = sender.tag } @IBAction func onItem2(_ sender: UIButton) { self.selection = sender.tag } }

Aucun commentaire:

Enregistrer un commentaire