From b4b38614f0e39efbe3eb46c8bb1856e5cb790260 Mon Sep 17 00:00:00 2001 From: diegopetrucci Date: Wed, 6 Jan 2016 20:44:13 +0100 Subject: [PATCH] Solutions for assignment #4 - Quick Sort --- .../Contents.swift | 237 +++++++++++++----- .../timeline.xctimeline | 16 +- 2 files changed, 177 insertions(+), 76 deletions(-) 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..20a5400 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 @@ -11,26 +11,50 @@ 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] - // ... - - return 0 + var j = low + var i = j - 1 + + while j < array.count - 1 { + if isOrderedBefore(array[j], pivot) { + i += 1 + + guard i != j else { + j += 1 + continue + } + + swap(&array[j], &array[i]) + j += 1 + } else { + j += 1 + } + } + + i += 1 + + if i == high { + return i + } + + swap(&array[j], &array[i]) + 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]) @@ -41,26 +65,74 @@ 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 { + + + guard array.count != 1 else { + return 0 + } + + guard array.count != 2 else { + switch isOrderedBefore(array[0], array[1]) { + case true: + return 0 + case false: + swap(&array[0], &array[1]) + return 1 + } + } + + if low == high { return low } + + // Following Wikipedia's example implementation let pivot = array[low] - - // ... + + var i = low - 1 + var j = high + 1 + + + while true { + repeat { + j -= 1 + } while isOrderedBefore(pivot, array[j]) + + repeat { + i += 1 + } while isOrderedBefore(array[i], pivot) + + if i < j { + swap(&array[i], &array[j]) + } else { return j } + } + + - return 0 } -//var hoareArray1 = [2, 5, 4] -//assert(hoarePartition(&hoareArray1, low: 0, high: hoareArray1.count-1, <) == 0) -//assert(hoareArray1 == [2, 5, 4]) -// + +var hoareArray1 = [2, 5, 4] +assert(hoarePartition(&hoareArray1, low: 0, high: hoareArray1.count-1, <) == 0) +assert(hoareArray1 == [2, 5, 4]) + +// This one doesn't work with Wikipedia's example implementation //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 hoareArray3 = [1, 1, 1, 0] -//assert(hoarePartition(&hoareArray3, low: 0, high: hoareArray3.count-1, <) == 1) -//assert(hoareArray3 == [0, 1, 1, 1]) +var hoareArray3 = [1, 1, 1, 0] +assert(hoarePartition(&hoareArray3, low: 0, high: hoareArray3.count-1, <) == 1) +assert(hoareArray3 == [0, 1, 1, 1]) + +var hoareArray4 = [5] +assert(hoarePartition(&hoareArray4, low: 0, high: hoareArray4.count-1, <) == 0) +assert(hoareArray4 == [5]) + +var hoareArray5 = [5, 3] +assert(hoarePartition(&hoareArray5, low: 0, high: hoareArray5.count-1, <) == 1) +assert(hoareArray5 == [3, 5]) /*: ### 1.3. Sort @@ -70,32 +142,41 @@ 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 + } + + var divider = hoarePartition(&array, low: low, high: high, isOrderedBefore) + + quickSort(&array, low: low, high: divider, isOrderedBefore) + quickSort(&array, low: divider + 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]) /*: @@ -119,24 +200,44 @@ func dutchFlagPartition(inout array: [T], pivotIndex: Int, low: I var equal = 0 var larger = high - // ... - + // Implementing Wikipedia's pseudocode https://en.wikipedia.org/wiki/Dutch_national_flag_problem#Pseudocode + while equal <= larger { + if array[equal] < pivot { + // Making sure I'm not swapping the same index + if smaller != equal { + swap(&array[smaller], &array[equal]) + } + smaller += 1 + equal += 1 + } else if array[equal] > pivot { + // Making sure I'm not swapping the same index + if larger != equal { + swap(&array[equal], &array[larger]) + } + larger -= 1 + } else { + equal += 1 } + } 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..c696929 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">