greedydev

Untitled

Mar 12th, 2023
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 3.09 KB | None | 0 0
  1. import Foundation
  2.  
  3. // Extension to split an array into chunks
  4. extension Array {
  5.     func chunks(_ size: Int) -> [[Element]] {
  6.         return stride(from: 0, to: count, by: size).map {
  7.             Array(self[$0..<Swift.min($0 + size, count)])
  8.         }
  9.     }
  10. }
  11.  
  12. func generateRandomWords(size: Int) -> [String] {
  13.     let words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange", "peach", "quince", "raspberry", "strawberry", "tangerine", "watermelon"]
  14.    
  15.     var wordCounts: [String: Int] = [:]
  16.     var randomWords: [String] = []
  17.    
  18.     // Generate a random word count for each word
  19.     for word in words {
  20.         let count = Int.random(in: 1...50)
  21.         wordCounts[word] = count
  22.     }
  23.    
  24.     // Create an array of random words
  25.     for (word, count) in wordCounts {
  26.         for _ in 0..<count {
  27.             randomWords.append(word)
  28.         }
  29.     }
  30.    
  31.     // Return shuffled array of words
  32.     return Array(repeating: randomWords, count: size/randomWords.count + 1).flatMap { $0 }.prefix(size).shuffled()
  33. }
  34.  
  35. func getWordCountConcurrently(words: [String]) -> [String: Int] {
  36.     let queue = DispatchQueue(label: "io.greedydev.wordcount", attributes: .concurrent)
  37.     let group = DispatchGroup()
  38.  
  39.     // Use GCD to divide the work betweek multiple threads
  40.     let chunkSize = words.count / ProcessInfo.processInfo.activeProcessorCount
  41.     let chunks = words.chunks(chunkSize)
  42.  
  43.     var wordCounts: [String: Int] = [:]
  44.  
  45.     // Use map-reduce to count the occurrences of each word in each chunk and add them up
  46.     for chunk in chunks {
  47.         group.enter()
  48.         queue.async {
  49.             let count = chunk.reduce(into: [:]) { counts, word in
  50.                 counts[word, default: 0] += 1
  51.             }
  52.             queue.async(flags: .barrier) {
  53.                 for (word, occurrences) in count {
  54.                     wordCounts[word, default: 0] += occurrences
  55.                 }
  56.                 group.leave()
  57.             }
  58.         }
  59.     }
  60.  
  61.     // Wait for all the work to complete
  62.     group.wait()
  63.  
  64.     return wordCounts
  65. }
  66.  
  67.  
  68. func getWordCountSync(words: [String]) -> [String: Int] {
  69.     let wordCounts = words
  70.         .map {
  71.             ($0, 1)
  72.         }
  73.         .reduce(into: [String: Int]()) { wordCounts, tuple in
  74.             let (word, count) = tuple
  75.             wordCounts[word, default: 0] += count
  76.         }
  77.    
  78.     return wordCounts
  79. }
  80.  
  81. // Function to measure execution time
  82. func measureTime(_ block: () -> Void) -> TimeInterval {
  83.     let startTime = Date()
  84.     block()
  85.     let endTime = Date()
  86.     return endTime.timeIntervalSince(startTime)
  87. }
  88.  
  89. // Input array of words
  90. let randomWords = generateRandomWords(size: 10_000_000)
  91. print(randomWords.count)
  92.  
  93. var concurrentWordCount = [String: Int]()
  94. let concurrentExecTime = measureTime {
  95.     concurrentWordCount = getWordCountConcurrently(words: randomWords)
  96. }
  97.  
  98. print("\(concurrentWordCount)")
  99. print("Concurrent: \(concurrentExecTime)\n")
  100.  
  101. var syncWordCount = [String: Int]()
  102. let syncExecTime = measureTime {
  103.     syncWordCount = getWordCountSync(words: randomWords)
  104. }
  105. print("\(syncWordCount)")
  106. print("Sync: \(syncExecTime)")
  107.  
Add Comment
Please, Sign In to add comment