Skip to content

Instantly share code, notes, and snippets.

@gregomni
Created March 2, 2022 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregomni/327f2c49de1e86888e4989e0b0997f4e to your computer and use it in GitHub Desktop.
Save gregomni/327f2c49de1e86888e4989e0b0997f4e to your computer and use it in GitHub Desktop.
// 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
@gregomni
Copy link
Author

gregomni commented Mar 2, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment