From 4efe882bff7c036c0a24beca7c214d7ceb80c28a Mon Sep 17 00:00:00 2001 From: Guillaume Date: Thu, 24 Sep 2020 19:26:07 +0200 Subject: [PATCH 1/8] heaps_algorithm: new algo --- divide_and_conquer/heaps_algorithm.py | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 divide_and_conquer/heaps_algorithm.py diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py new file mode 100644 index 000000000000..f1290ad0b880 --- /dev/null +++ b/divide_and_conquer/heaps_algorithm.py @@ -0,0 +1,50 @@ +""" +Heap's algorithm returns the list of all permutations possible from a list. +It minimizes movement by generating each permutation from the previous +by swapping only two elements. +More information: +https://en.wikipedia.org/wiki/Heap%27s_algorithm. +""" + + +def heaps(arr: list) -> list: + """ + Pure python implementation of the Heap's algorithm, + returning all permutations of a list. + >>> heaps([]) + [[]] + >>> heaps([0]) + [[0]] + >>> heaps([-1, 1]) + [[-1, 1], [1, -1]] + >>> heaps([1, 2, 3]) + [[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3], [2, 1, 3]] + """ + + if len(arr) <= 1: + return [arr] + + res = [] + + def generate(k: int, arr: list): + if k == 1: + res.append(arr[:]) + return + + generate(k - 1, arr) + + for i in range(k - 1): + if k % 2 == 0: # k is even + arr[i], arr[k - 1] = arr[k - 1], arr[i] + else: # k is odd + arr[0], arr[k - 1] = arr[k - 1], arr[0] + generate(k - 1, arr) + + generate(len(arr), arr) + return res + + +if __name__ == "__main__": + user_input = input("Enter numbers separated by a comma:\n").strip() + arr = [int(item) for item in user_input.split(",")] + print(heaps(arr)) From d8f8fb31e64a241529b009fe19384c92860b9b04 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Thu, 24 Sep 2020 20:40:20 +0200 Subject: [PATCH 2/8] typo --- divide_and_conquer/heaps_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index f1290ad0b880..6dd7d97141d8 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -1,6 +1,6 @@ """ Heap's algorithm returns the list of all permutations possible from a list. -It minimizes movement by generating each permutation from the previous +It minimizes movement by generating each permutation from the previous one by swapping only two elements. More information: https://en.wikipedia.org/wiki/Heap%27s_algorithm. From 662aa3dd79101084bb582917807f89bc352383fa Mon Sep 17 00:00:00 2001 From: Guillaume Date: Thu, 24 Sep 2020 21:13:30 +0200 Subject: [PATCH 3/8] correction doctest --- divide_and_conquer/heaps_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index 6dd7d97141d8..30c0fb1bc448 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -18,7 +18,7 @@ def heaps(arr: list) -> list: >>> heaps([-1, 1]) [[-1, 1], [1, -1]] >>> heaps([1, 2, 3]) - [[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3], [2, 1, 3]] + [[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [2, 3, 1], [3, 2, 1]] """ if len(arr) <= 1: From a6adcb105b9612d9e96ca78fb207903a38031757 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Thu, 24 Sep 2020 22:25:38 +0200 Subject: [PATCH 4/8] doctests: compare with itertools.permutations --- divide_and_conquer/heaps_algorithm.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index 30c0fb1bc448..59a863bef559 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -12,23 +12,26 @@ def heaps(arr: list) -> list: Pure python implementation of the Heap's algorithm, returning all permutations of a list. >>> heaps([]) - [[]] + [()] >>> heaps([0]) - [[0]] + [(0,)] >>> heaps([-1, 1]) - [[-1, 1], [1, -1]] + [(-1, 1), (1, -1)] >>> heaps([1, 2, 3]) - [[1, 2, 3], [2, 1, 3], [3, 1, 2], [1, 3, 2], [2, 3, 1], [3, 2, 1]] + [(1, 2, 3), (2, 1, 3), (3, 1, 2), (1, 3, 2), (2, 3, 1), (3, 2, 1)] + >>> import itertools + >>> set(heaps([1,2,3])) == set(itertools.permutations([1,2,3])) + True """ if len(arr) <= 1: - return [arr] + return [tuple(arr)] res = [] def generate(k: int, arr: list): if k == 1: - res.append(arr[:]) + res.append(tuple(arr[:])) return generate(k - 1, arr) From d613539dde4808c4f8bc9fa56d6c8972d13967e4 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 25 Sep 2020 10:57:31 +0200 Subject: [PATCH 5/8] doctest: sorted instead of set --- divide_and_conquer/heaps_algorithm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index 59a863bef559..39ed5cd6e7b5 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -19,8 +19,8 @@ def heaps(arr: list) -> list: [(-1, 1), (1, -1)] >>> heaps([1, 2, 3]) [(1, 2, 3), (2, 1, 3), (3, 1, 2), (1, 3, 2), (2, 3, 1), (3, 2, 1)] - >>> import itertools - >>> set(heaps([1,2,3])) == set(itertools.permutations([1,2,3])) + >>> from itertools import permutations + >>> sorted(heaps([1,2,3])) == sorted(permutations([1,2,3])) True """ From 32add91dded75e1227d44e41bccbcf4bbc0fd30d Mon Sep 17 00:00:00 2001 From: Guillaume Date: Mon, 28 Sep 2020 20:09:51 +0200 Subject: [PATCH 6/8] doctest --- divide_and_conquer/heaps_algorithm.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index 39ed5cd6e7b5..5b58a7c35c57 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -22,6 +22,8 @@ def heaps(arr: list) -> list: >>> from itertools import permutations >>> sorted(heaps([1,2,3])) == sorted(permutations([1,2,3])) True + >>> all(sorted(heaps(x)) == sorted(permutations(x)) for x in ([], [0], [-1, 1], [1, 2, 3])) + True """ if len(arr) <= 1: From 4785a1d3f3cdfa94eb6e7e9fd548a6a12329ebab Mon Sep 17 00:00:00 2001 From: Guillaume Date: Mon, 28 Sep 2020 20:24:40 +0200 Subject: [PATCH 7/8] doctest --- divide_and_conquer/heaps_algorithm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index 5b58a7c35c57..75b636ec0526 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -22,7 +22,8 @@ def heaps(arr: list) -> list: >>> from itertools import permutations >>> sorted(heaps([1,2,3])) == sorted(permutations([1,2,3])) True - >>> all(sorted(heaps(x)) == sorted(permutations(x)) for x in ([], [0], [-1, 1], [1, 2, 3])) + >>> all(sorted(heaps(x)) == sorted(permutations(x)) + ... for x in ([], [0], [-1, 1], [1, 2, 3])) True """ From f751cd325afda0ed21a4419e74045b0360461a29 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Tue, 29 Sep 2020 10:21:38 +0200 Subject: [PATCH 8/8] rebuild --- divide_and_conquer/heaps_algorithm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/divide_and_conquer/heaps_algorithm.py b/divide_and_conquer/heaps_algorithm.py index 75b636ec0526..af30ad664101 100644 --- a/divide_and_conquer/heaps_algorithm.py +++ b/divide_and_conquer/heaps_algorithm.py @@ -9,7 +9,7 @@ def heaps(arr: list) -> list: """ - Pure python implementation of the Heap's algorithm, + Pure python implementation of the Heap's algorithm (recursive version), returning all permutations of a list. >>> heaps([]) [()]