From 100c7b12ee33fe4496b75d2210d8ef2b42b661f5 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Fri, 23 May 2025 15:55:24 -0300 Subject: [PATCH] Reimplemented the main logic using a tip by Gbowne --- goulag_sort/goulagsort.py | 154 +++++++++++++------------------------- 1 file changed, 53 insertions(+), 101 deletions(-) diff --git a/goulag_sort/goulagsort.py b/goulag_sort/goulagsort.py index ce4a191..5481147 100644 --- a/goulag_sort/goulagsort.py +++ b/goulag_sort/goulagsort.py @@ -1,119 +1,71 @@ -def send_to_goulag(input_list:list)-> list : - """Sorts a list of numbers using the unique "Goulag Sort" method. +def send_to_goulag(main_list: list) -> list: + if not main_list: + return [] # Se a lista de entrada está vazia, retorna vazio - This algorithm processes a list of numbers through a distinctive iterative and - recursive procedure, inspired by the "Stalin Sort" concept. Here's how it operates: + # Se a lista tem 1 ou 0 elementos, ela já está ordenada + if len(main_list) <= 1: + return main_list - 1. **Iterative Filtering:** It iterates through the main list. If an element - is found to be greater than its subsequent element, the subsequent element - is moved to a temporary holding list (`temp`). The main list then continues - with the remaining elements. + filtered_list = [] + gulag_list = [] - 2. **Recursive Processing of Held Items:** If the `temp` list contains more than - one item, the `send_to_goulag` algorithm recursively processes `temp`. This - filtering and holding process continues until the sub-list contains a single - item or becomes empty. + # O primeiro elemento sempre vai para a filtered_list como ponto de partida + filtered_list.append(main_list[0]) - 3. **Partial Re-insertion:** After the recursive calls (or if `temp` was empty/single-item), - the algorithm attempts to re-insert the elements from `temp` back into the main list. - This re-insertion is performed by finding a suitable position where the held item - is less than the current element in the main list, maintaining a partial order. + # Percorre o restante da lista original (a partir do segundo elemento) + # com um único ponteiro 'i' + for i in range(1, len(main_list)): + current_item = main_list[i] + last_in_filtered = filtered_list[-1] # Pega o último item já colocado na filtered_list - 4. **Final Appending:** Any remaining elements in `temp` that were not re-inserted - into the middle of the list are then appended to the end of the main list. + if current_item >= last_in_filtered: + # Se o item atual mantém a ordem com o que já foi filtrado, adicione-o + filtered_list.append(current_item) + else: + # Se o item atual quebra a ordem, ele é "rejeitado" para o gulag + gulag_list.append(current_item) - For a more detailed step-by-step explanation of the algorithm's flow, please refer to: - :ref:`goulag_sort_detailed_explanation`. + if len(gulag_list) > 1: + gulag_list = send_to_goulag(gulag_list) + + filtered_list = merge_sorted_lists_efficient(filtered_list,gulag_list) + + return filtered_list + + +def merge_sorted_lists_efficient(list1: list, list2: list) -> list: + """ + Mescla duas listas ordenadas de forma eficiente, criando uma nova lista resultado. + Evita as operações custosas de insert/pop no meio das listas. Args: - input_list (list): The list of numbers to be processed and sorted. - This list will be modified **in-place**. + list1: A primeira lista ordenada. + list2: A segunda lista ordenada. Returns: - list: The list after being processed by the Goulag Sort algorithm. The result - is an ordered list. - - Examples: - >>> from goulag_sort import send_to_goulag - >>> my_list = [5, 2, 8, 1, 9, 4] - >>> send_to_goulag(my_list) - [1, 2, 4, 5, 8, 9] - - >>> empty_list = [] - >>> send_to_goulag(empty_list) - [] + Uma NOVA lista contendo todos os elementos de list1 e list2 mesclados e ordenados. """ + merged_list = [] + ptr1 = 0 # Ponteiro para list1 + ptr2 = 0 # Ponteiro para list2 - - idx = 0 - temp = [] - is_sorted = True - while True: - - if not input_list: - return [] - - if len(input_list)<=1: - return input_list - - - - while idx < len(input_list) - 1: - if input_list[idx] > input_list[idx + 1]: - temp.append(input_list[idx + 1]) - # pop(idx+1) é uma operação O(N) no pior caso - input_list.pop(idx + 1) - else: - idx += 1 - - # Chamada recursiva (pode adicionar complexidade se for muito frequente) - if len(temp) > 1: - temp = send_to_goulag(temp) - - idx = 0 - # Loop para reinserir elementos de 'temp' na lista principal - merge_two_sorted_lists_in_place(input_list,temp) - - if temp: - input_list.extend(temp) # extend é O(k) onde k é o tamanho de temp - temp.clear() - - for i in range(len(input_list) - 1): - if input_list[i] > input_list[i + 1]: - is_sorted = False - break - if is_sorted: - return input_list - -def merge_two_sorted_lists_in_place(list1: list, list2: list) -> list: - - if not list2: - return list1 - if not list1: - list1.extend(list2) - list2.clear() - return list1 - - - ptr1 = 0 - ptr2 = 0 - - + # Enquanto houver elementos em ambas as listas para comparar while ptr1 < len(list1) and ptr2 < len(list2): - if list1[ptr1] > list2[ptr2]: - - list1.insert(ptr1, list2[ptr2]) - + if list1[ptr1] <= list2[ptr2]: # Note o <= para estabilidade (mantém ordem de iguais) + merged_list.append(list1[ptr1]) ptr1 += 1 - - list2.pop(ptr2) else: + merged_list.append(list2[ptr2]) + ptr2 += 1 - ptr1 += 1 + # Adicionar quaisquer elementos restantes de list1 (se houver) + while ptr1 < len(list1): + merged_list.append(list1[ptr1]) + ptr1 += 1 + # Adicionar quaisquer elementos restantes de list2 (se houver) + while ptr2 < len(list2): + merged_list.append(list2[ptr2]) + ptr2 += 1 - if list2: - list1.extend(list2) - list2.clear() # Esvazia list2 - - return list1 \ No newline at end of file + return merged_list \ No newline at end of file