Skip to content

Instantly share code, notes, and snippets.

@proxpero
Last active September 18, 2023 13:17
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save proxpero/9fd3c4726d19242365d6 to your computer and use it in GitHub Desktop.
Save proxpero/9fd3c4726d19242365d6 to your computer and use it in GitHub Desktop.
Generate the permutations of a Swift array.
//: Permutations
// based on https://www.objc.io/blog/2014/12/08/functional-snippet-10-permutations/
// but updated for Swift 2.0 (Xcode 7.0)
extension Array {
func decompose() -> (Generator.Element, [Generator.Element])? {
guard let x = first else { return nil }
return (x, Array(self[1..<count]))
}
}
func between<T>(x: T, _ ys: [T]) -> [[T]] {
guard let (head, tail) = ys.decompose() else { return [[x]] }
return [[x] + ys] + between(x, tail).map { [head] + $0 }
}
let example = between(0, [1, 2, 3])
// example = [[0, 1, 2, 3], [1, 0, 2, 3], [1, 2, 0, 3], [1, 2, 3, 0]]
func permutations<T>(xs: [T]) -> [[T]] {
guard let (head, tail) = xs.decompose() else { return [[]] }
return permutations(tail).flatMap { between(head, $0) }
}
let p = permutations([1, 2, 3])
// p = [[1, 2, 3], [2, 1, 3], [2, 3, 1], [1, 3, 2], [3, 1, 2], [3, 2, 1]]
@sabiland
Copy link

sabiland commented Aug 29, 2017

Thx for this, works great!

Swift 3 needs little bit of tweaking to work.

@ryansobol
Copy link

Thanks so much for this! FWIW, I've updated the code to Swift 5, and made a few stylistic changes for personal preference.

@scottiesan
Copy link

What's the Big O of this? LogN?

@abey
Copy link

abey commented Mar 29, 2020

Updated this to Swift 5.2 🙌

extension Array {
    func decompose() -> (Iterator.Element, [Iterator.Element])? {
        guard let x = first else { return nil }
        return (x, Array(self[1..<count]))
    }
}

func between<T>(x: T, _ ys: [T]) -> [[T]] {
    guard let (head, tail) = ys.decompose() else { return [[x]] }
    return [[x] + ys] + between(x: x, tail).map { [head] + $0 }
}

func permutations<T>(xs: [T]) -> [[T]] {
    guard let (head, tail) = xs.decompose() else { return [[]] }
    return permutations(xs: tail).flatMap { between(x: head, $0) }
}

@marcoboerner
Copy link

Updated this to Swift 5.2 🙌

Great, thank you!

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