Created
March 2, 2022 18:59
-
-
Save gregomni/327f2c49de1e86888e4989e0b0997f4e to your computer and use it in GitHub Desktop.
This file contains 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
// Returns a set of instructions in the form of an array of closed ranges, | |
// where you should swap the element at the lowerBound of the range continually forward until next to the upperBound, | |
// and then cancel. | |
func shortenList<T>(inputList: [T], cancellable: (T, T) -> Bool, swappable: (T, T) -> Bool) -> [ClosedRange<Int>] { | |
var list = inputList | |
var result: [ClosedRange<Int>] = [] | |
while list.count > 1 { | |
var cancelRange: ClosedRange<Int>? | |
var currentLength = list.count | |
// For each value, find closest inverse after it that is reachable via swaps | |
outerloop: for startIndex in list.indices { | |
let startValue = list[startIndex] | |
// only consider ranges between values that are smaller than the shortest we've found so far | |
for endIndex in startIndex+1 ..< min(list.endIndex, startIndex+currentLength) { | |
let endValue = list[endIndex] | |
if cancellable(startValue, endValue) { | |
cancelRange = startIndex ... endIndex | |
currentLength = cancelRange!.count | |
// if we find adjacent cancellation, can't do any better | |
guard currentLength > 1 else { break outerloop } | |
break | |
} else if !swappable(startValue, endValue) { | |
break | |
} | |
} | |
} | |
if let cancelRange = cancelRange { | |
result.append(cancelRange) | |
list.remove(at: cancelRange.upperBound) | |
list.remove(at: cancelRange.lowerBound) | |
} else { | |
// no additional cancellable pairs found | |
break | |
} | |
} | |
return result | |
} | |
let list = [1, 2, 3, 4, -2, 5, 6, -1] | |
let result = shortenList(inputList: list, cancellable: {$0 == -$1}, swappable: {$0 < $1}) | |
result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Rereading this, I didn't actually need the label for the outer loop, just move the guard down to outside the bottom of the inner loop, oops.