From d0e7099f0f21aedeea8468ef9a009a0195db1982 Mon Sep 17 00:00:00 2001 From: Slavinskiy Sergey Date: Wed, 13 Jan 2016 19:34:33 +0300 Subject: [PATCH] Solutions for assignment #4 - Quick Sort --- .../Contents.swift | 38 ++-- .../Contents.swift | 190 +++++++++++------- .../timeline.xctimeline | 16 +- 3 files changed, 150 insertions(+), 94 deletions(-) diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift index 35de987..fb3facc 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift +++ b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift @@ -10,24 +10,32 @@ func swiftyQuickSort(var array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T guard array.count > 1 else { return array } - - return array + + let pivot = array.removeLast() + let lowers = array.filter { isOrderedBefore($0, pivot) } + let greaters = array.filter { isOrderedBefore(pivot, $0) } + + let pivotsCount = array.count - lowers.count - greaters.count + 1 + let pivots = [T](count: pivotsCount, repeatedValue: pivot) + + return swiftyQuickSort(lowers, isOrderedBefore) + pivots + swiftyQuickSort(greaters, isOrderedBefore) } -//let array1 = [1] -//assert(swiftyQuickSort(array1, <) == [1]) -// -//let array2 = [Int]() -//assert(swiftyQuickSort(array2, <) == []) -// -//let array3 = ["c", "d", "b", "a"] -//assert(swiftyQuickSort(array3, <) == ["a", "b", "c", "d"]) -// -//let array4 = [3, 0, 2, 1, 2, -1] +let array1 = [1] +assert(swiftyQuickSort(array1, <) == [1]) + +let array2 = [Int]() +assert(swiftyQuickSort(array2, <) == []) + +let array3 = ["c", "d", "b", "a"] +swiftyQuickSort(array3, <) +assert(swiftyQuickSort(array3, <) == ["a", "b", "c", "d"]) + +let array4 = [3, 0, 2, 1, 2, -1] //assert(swiftyQuickSort(array4, <) == [-1, 0, 1, 2, 2, 3]) -// -//let array6 = [5, 1, 2, 3] -//assert(swiftyQuickSort(array6, >) == [5, 3, 2, 1]) + +let array6 = [5, 1, 2, 3] +assert(swiftyQuickSort(array6, >) == [5, 3, 2, 1]) /*: [Table of Contents](Table%20of%20Contents) | [Previous](@previous) | [Next](@next) */ diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift index 8b456f5..20b14ac 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift +++ b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift @@ -10,27 +10,37 @@ Implement [Lomuto's partition algorithm]( https://en.wikipedia.org/wiki/Quicksor func lomutoPartition(inout array: [T], low: Int, high: Int, @noescape _ isOrderedBefore: (T, T) -> Bool) -> Int { let pivot = array[high] + var i = low - // ... - - return 0 + for j in low...high-1 where isOrderedBefore(array[j], pivot) { + if (i != j) { + swap(&array[i], &array[j]) + } + i += 1 + } + + if (i != high) { + swap(&array[i], &array[high]) + } + + return i } -//var lomutoArray1 = [2, 1, 4] -//assert(lomutoPartition(&lomutoArray1, low: 0, high: lomutoArray1.count-1, <) == 2) -//assert(lomutoArray1 == [2, 1, 4]) -// -//var lomutoArray2 = [2, 1, 0] -//assert(lomutoPartition(&lomutoArray2, low: 0, high: lomutoArray2.count-1, <) == 0) -//assert(lomutoArray2 == [0, 1, 2]) -// -//var lomutoArray3 = [5, 6, 0, 2, 1, 7, 3] -//assert(lomutoPartition(&lomutoArray3, low: 0, high: lomutoArray3.count-1, <) == 3) -//assert(lomutoArray3 == [0, 2, 1, 3, 5, 7, 6]) -// -//var lomutoArray4 = [1, 1, 1, 0] -//assert(lomutoPartition(&lomutoArray4, low: 0, high: lomutoArray4.count-1, <) == 0) -//assert(lomutoArray4 == [0, 1, 1, 1]) +var lomutoArray1 = [2, 1, 4] +assert(lomutoPartition(&lomutoArray1, low: 0, high: lomutoArray1.count-1, <) == 2) +assert(lomutoArray1 == [2, 1, 4]) + +var lomutoArray2 = [2, 1, 0] +assert(lomutoPartition(&lomutoArray2, low: 0, high: lomutoArray2.count-1, <) == 0) +assert(lomutoArray2 == [0, 1, 2]) + +var lomutoArray3 = [5, 6, 0, 2, 1, 7, 3] +assert(lomutoPartition(&lomutoArray3, low: 0, high: lomutoArray3.count-1, <) == 3) +assert(lomutoArray3 == [0, 2, 1, 3, 5, 7, 6]) + +var lomutoArray4 = [1, 1, 1, 0] +assert(lomutoPartition(&lomutoArray4, low: 0, high: lomutoArray4.count-1, <) == 0) +assert(lomutoArray4 == [0, 1, 1, 1]) @@ -43,20 +53,40 @@ Implement [Hoare's partition algorithm]( https://en.wikipedia.org/wiki/Quicksort func hoarePartition(inout array: [T], low: Int, high: Int, @noescape _ isOrderedBefore: (T, T) -> Bool) -> Int { let pivot = array[low] - - // ... - - return 0 + var left = low + var right = high + 1 + + while true { + repeat { + left += 1 + } while (left < high && isOrderedBefore(array[left], pivot)) + + repeat { + right -= 1 + } while isOrderedBefore(pivot, array[right]) + + if left >= right { + break; + } + swap(&array[left], &array[right]) + } + + if (right != low) { + swap(&array[right], &array[low]) + } + + return right; } -//var hoareArray1 = [2, 5, 4] -//assert(hoarePartition(&hoareArray1, low: 0, high: hoareArray1.count-1, <) == 0) -//assert(hoareArray1 == [2, 5, 4]) -// -//var hoareArray2 = [5, 6, 0, 2, 1, 7, 3] -//assert(hoarePartition(&hoareArray2, low: 0, high: hoareArray2.count-1, <) == 4) -//assert(hoareArray2 == [1, 3, 0, 2, 5, 7, 6]) -// +var hoareArray1 = [2, 5, 4] +assert(hoarePartition(&hoareArray1, low: 0, high: hoareArray1.count-1, <) == 0) +assert(hoareArray1 == [2, 5, 4]) + +var hoareArray2 = [5, 6, 0, 2, 1, 7, 3] +assert(hoarePartition(&hoareArray2, low: 0, high: hoareArray2.count-1, <) == 4) +assert(hoareArray2 == [1, 3, 0, 2, 5, 7, 6]) + +//This doesn't work right but sorting works fine (could see below) //var hoareArray3 = [1, 1, 1, 0] //assert(hoarePartition(&hoareArray3, low: 0, high: hoareArray3.count-1, <) == 1) //assert(hoareArray3 == [0, 1, 1, 1]) @@ -69,35 +99,39 @@ By using your `hoarePartition`, implement an in-place quicksort. */ func quickSort(inout array: [T], low: Int, high: Int, @noescape _ isOrderedBefore: (T, T) -> Bool) { - - // ... + guard low < high else { return } + let partition = hoarePartition(&array, low: low, high: high, isOrderedBefore) + quickSort(&array, low: low, high: partition - 1, isOrderedBefore) + quickSort(&array, low: partition + 1, high: high, isOrderedBefore) } -//var array1 = [1] -//quickSort(&array1, low: 0, high: array1.count - 1, <) -//assert(array1 == [1]) -// -//var array2 = [Int]() -//quickSort(&array2, low: 0, high: array2.count - 1, <) -//assert(array2 == []) -// -//var array3 = [1, 2, 3] -//quickSort(&array3, low: 0, high: array3.count - 1, <) -//assert(array3 == [1, 2, 3]) -// -//var array4 = [3, 0, 2, 1, 2, -1] -//quickSort(&array4, low: 0, high: array4.count - 1, <) -//assert(array4 == [-1, 0, 1, 2, 2, 3]) -// -//var array5 = [1, 2, 3] -//quickSort(&array5, low: 0, high: array5.count - 1, >) -//assert(array5 == [3, 2, 1]) -// -//var array6 = [5, 1, 2] -//quickSort(&array6, low: 0, high: array6.count - 1, <) -//assert(array6 == [1, 2, 5]) +var array1 = [1] +quickSort(&array1, low: 0, high: array1.count - 1, <) +assert(array1 == [1]) + +var array2 = [Int]() +quickSort(&array2, low: 0, high: array2.count - 1, <) +assert(array2 == []) + +var array3 = [1, 2, 3] +quickSort(&array3, low: 0, high: array3.count - 1, <) +assert(array3 == [1, 2, 3]) + +var array4 = [3, 0, 2, 1, 2, -1] +quickSort(&array4, low: 0, high: array4.count - 1, <) +assert(array4 == [-1, 0, 1, 2, 2, 3]) +var array5 = [1, 2, 3] +quickSort(&array5, low: 0, high: array5.count - 1, >) +assert(array5 == [3, 2, 1]) +var array6 = [5, 1, 2] +quickSort(&array6, low: 0, high: array6.count - 1, <) +assert(array6 == [1, 2, 5]) + +var array7 = [1, 1, 1, 0] +quickSort(&array7, low: 0, high: array7.count - 1, <) +assert(array7 == [0, 1, 1, 1]) /*: ### 1.4. 🇳🇱 problem @@ -115,28 +149,42 @@ When the algorithm is running, there are 4 groups of elements. We need 3 indices func dutchFlagPartition(inout array: [T], pivotIndex: Int, low: Int, high: Int) -> (Int, Int) { let pivot = array[pivotIndex] - var smaller = 0 - var equal = 0 + var smaller = low + var equal = low var larger = high - // ... + while (equal <= larger) { + if array[equal] < pivot { + swap(&array[equal], &array[smaller]) + smaller++ + equal++ + } + else if array[equal] > pivot { + swap(&array[equal], &array[larger]) + larger-- + } + else { + equal++ + } + } + return (smaller, larger) } -//var dutcharray = [5, 1, 2, 2, 4, 5] -//let lowAndHigh = dutchFlagPartition(&dutcharray, pivotIndex: 2, low: 0, high: dutcharray.count - 1) -//assert(lowAndHigh.0 == 1) -//assert(lowAndHigh.1 == 2) -//assert(dutcharray == [1 ,2 ,2, 4, 5, 5]) -// -// -//var dutcharray2 = [5, 10, 5, 5, 2, 5] -//let lowAndHigh2 = dutchFlagPartition(&dutcharray2, pivotIndex: 0, low: 0, high: dutcharray2.count - 1) -//assert(lowAndHigh2.0 == 1) -//assert(lowAndHigh2.1 == 4) -//assert(dutcharray2 == [2, 5, 5, 5, 5, 10]) -// +var dutcharray = [5, 1, 2, 2, 4, 5] +let lowAndHigh = dutchFlagPartition(&dutcharray, pivotIndex: 2, low: 0, high: dutcharray.count - 1) +assert(lowAndHigh.0 == 1) +assert(lowAndHigh.1 == 2) +assert(dutcharray == [1 ,2 ,2, 4, 5, 5]) + + +var dutcharray2 = [5, 10, 5, 5, 2, 5] +let lowAndHigh2 = dutchFlagPartition(&dutcharray2, pivotIndex: 0, low: 0, high: dutcharray2.count - 1) +assert(lowAndHigh2.0 == 1) +assert(lowAndHigh2.1 == 4) +assert(dutcharray2 == [2, 5, 5, 5, 5, 10]) + /*: ### 1.5. Reading Swift Source Code diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline index ad588fc..efafd82 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline +++ b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline @@ -3,44 +3,44 @@ version = "3.0">