Created
June 11, 2015 01:51
-
-
Save WeZZard/87a6c3f234f97533b5c2 to your computer and use it in GitHub Desktop.
A binary search implementation in Swift 2.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Search an integer number in an ordered-cycling integer number array | |
var anArray = [22, 33, 44, 55, 66, 88, 99, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
func find(number: Int, inArray anArray: [Int]) -> Int? { | |
return binary_search_considering_cycling(number, | |
inArray: anArray, baseIndex: 0) | |
} | |
func binary_search_considering_cycling(number: Int, | |
inArray anArray: [Int], baseIndex: Int) | |
-> Int? | |
{ | |
if anArray.count != 0 { | |
// Is there a break point in array? | |
let middleDistance = anArray.count / 2 | |
let middleIndex = advance(anArray.startIndex, middleDistance) | |
let inspectedElement = anArray[middleIndex] | |
if inspectedElement == number { | |
return advance(baseIndex, middleDistance) | |
} | |
let shouldConsiderBreakPoint: Bool = { | |
if anArray.count > 2 { | |
if let first = anArray.first, | |
last = anArray.last | |
{ | |
let predecessor = anArray[middleIndex.predecessor()] | |
let successor = anArray[middleIndex.successor()] | |
let (doesBreakPointExist, isInspectingBreakPoint) = | |
getBreakPointInfo(first: first, | |
predecessor: predecessor, | |
inspected: inspectedElement, | |
successor: successor, | |
last: last) | |
return doesBreakPointExist && !isInspectingBreakPoint | |
} | |
} | |
return false | |
}() | |
let mightBeLocatedInThePreceding = (anArray.first < number && | |
number < inspectedElement) | |
let shouldInspectPreceding = (mightBeLocatedInThePreceding || | |
shouldConsiderBreakPoint) | |
if shouldInspectPreceding { | |
let precedingRange = anArray.startIndex..<middleIndex | |
let ascendants = anArray[precedingRange].map {$0} | |
if let result = binary_search_considering_cycling(number, | |
inArray: ascendants, | |
baseIndex: baseIndex) | |
{ | |
return result | |
} | |
} | |
let mightBeLocatedInTheSucceding = (inspectedElement < number && | |
number < anArray.last) | |
let shouldInspectSuccedding = (mightBeLocatedInTheSucceding || | |
shouldConsiderBreakPoint) | |
if shouldInspectSuccedding { | |
let succeddingRange = middleIndex.successor()..<anArray.endIndex | |
let descedants = anArray[succeddingRange].map {$0} | |
if let result = binary_search_considering_cycling(number, | |
inArray: descedants, | |
baseIndex: advance(baseIndex, | |
distance(anArray.startIndex, middleIndex.successor()))) | |
{ | |
return result | |
} | |
} | |
} | |
return nil | |
} | |
func getBreakPointInfo<C: Comparable>(first first: C, | |
predecessor: C, inspected: C, successor: C, last: C) -> | |
(doesBreakPointExist: Bool, isInspectingBreakPoint: Bool) | |
{ | |
if first < inspected && inspected < last || | |
first > inspected && inspected > last | |
{ | |
return (false, false) | |
} else { | |
if predecessor < inspected && inspected < successor || | |
predecessor > inspected && inspected > successor | |
{ | |
return (true, !(predecessor < inspected && inspected < successor || | |
predecessor > inspected && inspected > successor)) | |
} else { | |
return (true, true) | |
} | |
} | |
} | |
let result = find(6, inArray: anArray) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment