diff --git a/DIRECTORY.md b/DIRECTORY.md index 0f4aeefe3b8204084c5b5636b409be5ca045eded..d9196e130196692e8940629bd7e73cc3e8314aae 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -761,6 +761,7 @@ * [Odd Even Transposition Parallel](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_parallel.py) * [Odd Even Transposition Single Threaded](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_single_threaded.py) * [Pancake Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pancake_sort.py) + * [Patience Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/patience_sort.py) * [Pigeon Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pigeon_sort.py) * [Pigeonhole Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pigeonhole_sort.py) * [Quick Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/quick_sort.py) diff --git a/sorts/patience_sort.py b/sorts/patience_sort.py new file mode 100644 index 0000000000000000000000000000000000000000..f4e35d9a0ac6d720ac29ee8fadf6ace9e3986bad --- /dev/null +++ b/sorts/patience_sort.py @@ -0,0 +1,64 @@ +from bisect import bisect_left +from functools import total_ordering +from heapq import merge + +""" +A pure Python implementation of the patience sort algorithm + +For more information: https://en.wikipedia.org/wiki/Patience_sorting + +This algorithm is based on the card game patience + +For doctests run following command: +python3 -m doctest -v patience_sort.py + +For manual testing run: +python3 patience_sort.py +""" + + +@total_ordering +class Stack(list): + def __lt__(self, other): + return self[-1] < other[-1] + + def __eq__(self, other): + return self[-1] == other[-1] + + +def patience_sort(collection: list) -> list: + """A pure implementation of quick sort algorithm in Python + + :param collection: some mutable ordered collection with heterogeneous + comparable items inside + :return: the same collection ordered by ascending + + Examples: + >>> patience_sort([1, 9, 5, 21, 17, 6]) + [1, 5, 6, 9, 17, 21] + + >>> patience_sort([]) + [] + + >>> patience_sort([-3, -17, -48]) + [-48, -17, -3] + """ + stacks = [] + # sort into stacks + for element in collection: + new_stacks = Stack([element]) + i = bisect_left(stacks, new_stacks) + if i != len(stacks): + stacks[i].append(element) + else: + stacks.append(new_stacks) + + # use a heap-based merge to merge stack efficiently + collection[:] = merge(*[reversed(stack) for stack in stacks]) + return collection + + +if __name__ == "__main__": + user_input = input("Enter numbers separated by a comma:\n").strip() + unsorted = [int(item) for item in user_input.split(",")] + print(patience_sort(unsorted))