Skip to content

Instantly share code, notes, and snippets.

@futureperfect
Last active August 29, 2015 14:23
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 futureperfect/718fefe5fcee6fcf8445 to your computer and use it in GitHub Desktop.
Save futureperfect/718fefe5fcee6fcf8445 to your computer and use it in GitHub Desktop.
Ruby Implementation of Heap's algorithm for generating all permutations of a collection

Permutations

This is an implementation of Heap's algorithm for generating the permutations of a collection.

# coding: utf-8
module Permutations
def permutations
acc = []
generate_permutations(self.count, self.clone, acc)
acc
end
private
# Heap's algorithm
# https://en.wikipedia.org/wiki/Heap%27s_algorithm
#
def generate_permutations(n, array, acc)
if n == 1
acc << array.clone
else
for i in 0...n
generate_permutations(n-1, array, acc)
j = n.even? ? i : 0
array[j], array[n-1] = array[n-1], array[j]
end
end
end
end
# coding: utf-8
require "minitest/autorun"
require "./lib/permutations"
class Array
include Permutations
end
class TestPermutations < Minitest::Test
def test_responds_to_permutations
array = []
assert_respond_to array, :permutations
end
def test_permutes_empty_array
assert_equal [], [].permutations
end
def test_permutes_single_element_array
actual = [1].permutations
assert_equal [[1]], actual
end
def test_permutes_two_element_array
actual = [1,2].permutations
expected = [[1, 2], [2, 1]]
assert_equal expected, actual
end
def test_generates_correct_number_of_permutations_for_three_elements
actual = [1, 2, 3].permutations
expected = [[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [2, 3, 1], [3, 2, 1]]
assert_equal expected, actual
end
def test_generates_correct_number_of_permutations_for_four_elements
actual = [1, 2, 3, 4].permutations
expected =
[[1, 2, 3, 4],
[2, 1, 3, 4],
[3, 1, 2, 4],
[1, 3, 2, 4],
[2, 3, 1, 4],
[3, 2, 1, 4],
[4, 2, 3, 1],
[2, 4, 3, 1],
[3, 4, 2, 1],
[4, 3, 2, 1],
[2, 3, 4, 1],
[3, 2, 4, 1],
[4, 1, 3, 2],
[1, 4, 3, 2],
[3, 4, 1, 2],
[4, 3, 1, 2],
[1, 3, 4, 2],
[3, 1, 4, 2],
[4, 1, 2, 3],
[1, 4, 2, 3],
[2, 4, 1, 3],
[4, 2, 1, 3],
[1, 2, 4, 3],
[2, 1, 4, 3]]
assert_equal 24, actual.count
assert_equal expected, actual
end
def test_generates_n_factorial_permutations_for_six_elements
actual = [1, 2, 3, 4, 5, 6].permutations
assert_equal 720, actual.count
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment