Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
import Foundation
import Dispatch
public struct SleepSort {
/// Dispatches a block after `secs` seconds
static func dispatch(after secs: Double, block: @escaping () -> Void) {
#if os(Linux)
let delay = Double(CLOCKS_PER_SEC) * secs
#else
let delay = Double(NSEC_PER_SEC) * secs
#endif
let dT = DispatchTime(uptimeNanoseconds:DispatchTime.now().rawValue + UInt64(delay))
if #available(OSX 10.10, *) {
DispatchQueue
.global(qos: .default)
.asyncAfter(deadline: dT, execute: block)
}
}
// Return sleep-sorted integer array
public static func sort(_ nums: [Int]) -> [Int] {
var results:[Int] = []
let maxItem = nums.max() ?? 0
let semaphore = DispatchSemaphore(value: 0)
let dTime = 0.05
let accessQueue = DispatchQueue(label: "org.sadun.sortIsolation", qos: .default, attributes: [.concurrent], autoreleaseFrequency: .inherit)
self.dispatch(after: Double(maxItem + 1) * dTime) { semaphore.signal() }
nums.forEach { number in
self.dispatch(after: Double(number) * dTime) {
accessQueue.sync(flags: [.barrier]) {
results.append(contentsOf: [number])
}
}
}
let _ = semaphore.wait(timeout: DispatchTime.distantFuture)
return results
}
}
extension Array {
// Scramble array members
func scramble() -> [Iterator.Element] {
var collection = self
let elementCount = collection.count
for offset in 0 ..< (elementCount - 1) {
#if os(Linux)
let r = offset + Int(rand() % (numericCast(elementCount - offset)))
#else
let r = offset + Int(arc4random_uniform(numericCast(elementCount - offset)))
#endif
guard r != offset else { continue }
swap(&collection[offset], &collection[r])
}
return collection
}
}
let array = Array(1...20).scramble()
print(array)
print(SleepSort.sort(array))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment