Skip to content
This repository has been archived by the owner on Mar 29, 2018. It is now read-only.

Commit

Permalink
Merge branch 'michaeleisel-repeated_permutations'
Browse files Browse the repository at this point in the history
  • Loading branch information
pNre committed Jan 29, 2015
2 parents 5b710fb + 0254b90 commit 48f084a
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 18 deletions.
81 changes: 78 additions & 3 deletions ExSwift/Array.swift
Original file line number Diff line number Diff line change
Expand Up @@ -792,11 +792,48 @@ internal extension Array {
return result
}

/**
Returns all of the combinations in the array of the given length, allowing repeats

:param: length
:returns: Combinations
*/
func repeatedCombination (length: Int) -> [[Element]] {
if length < 0 {
return []
}
var indexes: [Int] = []
length.times {
indexes.append(0)
}
var combinations: [[Element]] = []
var offset = self.count - indexes.count
while true {
var combination: [Element] = []
for index in indexes {
combination.append(self[index])
}
combinations.append(combination)
var i = indexes.count - 1
while i >= 0 && indexes[i] == self.count - 1 {
i--
}
if i < 0 {
break
}
indexes[i]++
(i+1).upTo(indexes.count - 1) { j in
indexes[j] = indexes[i]
}
}
return combinations
}

/**
Returns all of the combinations in the array of the given length
:param: length
:returns: Combinations
:param: length
:returns: Combinations
*/
func combination (length: Int) -> [[Element]] {
if length < 0 || length > self.count {
Expand Down Expand Up @@ -827,6 +864,33 @@ internal extension Array {
return combinations
}

/**
Returns all of the permutations of this array of a given length, allowing repeats

:param: length The length of each permutations
:returns All of the permutations of this array of a given length, allowing repeats
*/
func repeatedPermutation(length: Int) -> [[T]] {
if length < 1 {
return []
}
var permutationIndexes: [[Int]] = []
permutationIndexes.repeatedPermutationHelper([], length: length, arrayLength: self.count, permutationIndexes: &permutationIndexes)
return permutationIndexes.map({ $0.map({ i in self[i] }) })
}

func repeatedPermutationHelper(seed: [Int], length: Int, arrayLength: Int, inout permutationIndexes: [[Int]]) {
if seed.count == length {
permutationIndexes.append(seed)
return
}
for i in (0..<arrayLength) {
var newSeed: [Int] = seed
newSeed.append(i)
self.repeatedPermutationHelper(newSeed, length: length, arrayLength: arrayLength, permutationIndexes: &permutationIndexes)
}
}

/**
Returns the number of elements which meet the condition

Expand Down Expand Up @@ -871,6 +935,17 @@ internal extension Array {
return transposition
}

/**
Replaces each element in the array with object. I.e., it keeps the length the same but makes the element at every index be object

:param: object The object to replace each element with
*/
mutating func fill (object: T) -> () {
(0..<self.count).each { i in
self[i] = object
}
}

/**
Joins the array elements with a separator.

Expand Down
56 changes: 41 additions & 15 deletions ExSwiftTests/ExSwiftArrayTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,16 @@ class ExtensionsArrayTests: XCTestCase {
XCTAssertEqual(array.uniqueBy({$0 % 3}), [1, 2, 3])
XCTAssertEqual(array.uniqueBy({$0 < 3}), [1, 3])
}

func testRepeatedCombination() {
var shortArray = [1, 2, 3]
XCTAssertEqual(shortArray.repeatedCombination(-1), [])
XCTAssertEqual(shortArray.repeatedCombination(0), [[]])
XCTAssertEqual(shortArray.repeatedCombination(1), [[1], [2], [3]])
XCTAssertEqual(shortArray.repeatedCombination(2), [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]])
XCTAssertEqual(shortArray.repeatedCombination(3), [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3], [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]])
XCTAssertEqual(shortArray.repeatedCombination(4), [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3], [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3], [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]])
}

func testCombinations() {
XCTAssertEqual(array.combination(-1), [])
Expand All @@ -450,22 +460,22 @@ class ExtensionsArrayTests: XCTestCase {
XCTAssertEqual(array.combination(6), [])
}

func testTransposition() {
var arrays: [[Int]] = []
array.count.times {
arrays.append(self.array)
}
var arraysTransposition: [[Int]] = [].transposition(arrays)
arrays.eachIndex { i in
arrays[0].eachIndex { j in
XCTAssertEqual(arrays[i][j], arraysTransposition[j][i])
}
}
func testTransposition() {
var arrays: [[Int]] = []
array.count.times {
arrays.append(self.array)
}
var arraysTransposition: [[Int]] = [].transposition(arrays)
arrays.eachIndex { i in
arrays[0].eachIndex { j in
XCTAssertEqual(arrays[i][j], arraysTransposition[j][i])
}
}

var jagged: [[String]] = [["a", "b", "c"], ["d", "e"], ["f", "g", "h"]]
var jaggedTransposition = [].transposition(jagged)
XCTAssertEqual(jaggedTransposition, [["a", "d", "f"], ["b", "e", "g"], ["c", "h"]])
}
var jagged: [[String]] = [["a", "b", "c"], ["d", "e"], ["f", "g", "h"]]
var jaggedTransposition = [].transposition(jagged)
XCTAssertEqual(jaggedTransposition, [["a", "d", "f"], ["b", "e", "g"], ["c", "h"]])
}

func testPermutations() {
1.upTo(array.count) { i in
Expand All @@ -485,5 +495,21 @@ class ExtensionsArrayTests: XCTestCase {
XCTAssertEqual(array.permutation(0), [[]])
XCTAssertEqual(array.permutation(array.count + 1), [])
}

func testRepeatedPermutations() {
var shortArray = [1, 2]
XCTAssertEqual(shortArray.repeatedPermutation(0), [])
XCTAssertEqual(shortArray.repeatedPermutation(1), [[1], [2]])
XCTAssertEqual(shortArray.repeatedPermutation(2), [[1, 1], [1, 2], [2, 1], [2, 2]])
XCTAssertEqual(shortArray.repeatedPermutation(3), [[1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 2, 2], [2, 1, 1], [2, 1, 2], [2, 2, 1], [2, 2, 2]])
}

func testFill() {
array.fill(0)
XCTAssertEqual(array, [0, 0, 0, 0, 0])
var emptyArray: [String] = []
emptyArray.fill("foo")
XCTAssertEqual(emptyArray, [])
}
}

0 comments on commit 48f084a

Please sign in to comment.