Scalanie sortowania to algorytm sortowania, który działa poprzez podzielenie danej listy na pół, rekurencyjne sortowanie obu mniejszych list i scalenie ich z powrotem w jedną posortowaną listę. Podstawowy przypadek rekurencji dochodzi do listy singletonów, której nie można dalej dzielić, ale według definicji jest już posortowana.
Wykonanie algorytmu na liście [1,7,6,3,3,2,5]
można wizualizować w następujący sposób:
[1,7,6,3,3,2,5]
/ \ split
[1,7,6,3] [3,2,5]
/ \ / \ split
[1,7] [6,3] [3,2] [5]
/ \ / \ / \ | split
[1] [7] [6] [3] [3] [2] [5]
\ / \ / \ / | merge
[1,7] [3,6] [2,3] [5]
\ / \ / merge
[1,3,6,7] [2,3,5]
\ / merge
[1,2,3,3,5,6,7]
Zadanie
Napisz program lub funkcję, która pobiera listę liczb całkowitych w jakikolwiek rozsądny sposób jako dane wejściowe i wizualizuje różne partycje tej listy podczas sortowania według algorytmu sortowania po scaleniu. Oznacza to, że nie musisz generować wykresu jak powyżej, ale tylko listy są w porządku:
[1,7,6,3,3,2,5]
[1,7,6,3][3,2,5]
[1,7][6,3][3,2][5]
[1][7][6][3][3][2][5]
[1,7][3,6][2,3][5]
[1,3,6,7][2,3,5]
[1,2,3,3,5,6,7]
Co więcej, każda rozsądna notacja na liście jest w porządku, dlatego następujące dane byłyby również prawidłowymi danymi wyjściowymi:
1 7 6 3 3 2 5
1 7 6 3|3 2 5
1 7|6 3|3 2|5
1|7|6|3|3|2|5
1 7|3 6|2 3|5
1 3 6 7|2 3 5
1 2 3 3 5 6 7
Wreszcie sposób podzielenia listy na dwie mniejsze listy zależy od ciebie, o ile długość obu list wynikowych różni się co najwyżej o jedną. Oznacza to, że zamiast dzielić [3,2,4,3,7]
na [3,2,4]
i [3,7]
, możesz również dzielić, biorąc elementy o indeksach parzystych i nieparzystych ( [3,4,7]
i [2,3]
), a nawet za każdym razem losować podział.
To jest golf golfowy , więc wygrywa najkrótszy kod w dowolnym języku mierzony w bajtach.
Przypadki testowe
Jak wspomniano powyżej, faktyczny format i sposób podziału list na pół zależy od Ciebie.
[10,2]
[10][2]
[2,10]
[4,17,1,32]
[4,17][1,32]
[4][17][1][32]
[4,17][1,32]
[1,4,17,32]
[6,5,4,3,2,1]
[6,5,4][3,2,1]
[6,5][4][3,2][1]
[6][5][4][3][2][1]
[5,6][4][2,3][1] <- Important: This step cannot be [5,6][3,4][1,2], because 3 and 4 are on different branches in the the tree
[4,5,6][1,2,3]
[1,2,3,4,5,6]
źródło
[[1,2],[3],[4,5],[6]]
Etap jest właściwie właściwym rozwiązaniem, ponieważ sortowanie scalające działa rekurencyjnie. To znaczy, jeśli zaczniemy[1,2,3,4,5,6]
i podzielimy na[1,2,3]
i[4,5,6]
, a następnie wykazy te są przetwarzane niezależnie, dopóki nie zostaną połączone w końcowym etapie.[3]
i[2,1]
, to są one na różnych gałęziach, więc nie możemy się połączyć,[3]
a[2]
po[2,1]
jest podzielony na[2]
i[1]
.Odpowiedzi:
Haskell ,
137128127125121109106 bajtów(-2) + (- 4) = (- 6) bajtów dzięki Nimi ! Zmiana go w celu zebrania wszystkich kroków na liście (ponownie z powodu nich) pozwala zaoszczędzić jeszcze 12 bajtów.
Kolejne 3 bajty ze względu na Laikoni , z powiązaniem strażnika wzorca i sprytnym użyciem zrozumienia listy do zakodowania strażnika.
Wypróbuj online!
Podział list na nieparzyste i parzyste elementy jest krótszym kodem niż na dwie kolejne połówki, ponieważ nie musimy
length
wtedy mierzyć .Działa poprzez „drukowanie” list, a następnie rekurencję z listami podzielonymi (
x >>= h
), jeśli rzeczywiście dokonano podziału, i „drukowanie” posortowanych list; zaczynając od listy z jednym wejściem; przy założeniu niepustego wejścia. I zamiast faktycznego drukowania, wystarczy zebrać je na liście.Lista tworzona przez
g[[6,5..1]]
, drukowana linia po linii, to:źródło
p=print
i trzy razyp
. Wypróbuj online!g
możesz zebrać wszystkie kroki na liście i zwrócić ją. Wypróbuj online!g x|y<-x>>=h=x:[z|x/=y,z<-g y++[sort<$>x]]
oszczędza trochę więcej bajtów.Wolfram Language (Mathematica) ,
146127111102 bajtówWypróbuj online!
Zwraca a,
List
który zawiera kroki.Wyjaśnienie
Na wejściu podziel wszystkie
List
s zawierające 2 lub więcej liczb całkowitych na pół. Pierwsza lista podrzędna zawiera elementy nieparzyste (1 indeksowane), a druga ma elementy parzyste.Powtarzaj to, dopóki nic się nie zmieni (tzn. Wszystkie listy podrzędne mają długość-1). Zachowaj wszystkie wyniki pośrednie. Przechowuj to (
List
wszystkie kroki) wu
.Upuść ostatni element
u
i odwróć go.Na podstawie powyższego wyniku posortuj wszystkie wystąpienia listy liczb całkowitych.
źródło
Czysty ,
228206168157140121104 bajtówTworzy listę etapów od końców do wewnątrz, wykorzystując fakt, że
n
-ty element od końca jest posortowaną wersjąn
-tego elementu od początku.Pomysł z komentarza JungHwan Min
Wypróbuj online!
źródło
Węgiel drzewny ,
145133123122 bajtówWypróbuj online! Link jest do pełnej wersji kodu.
Wciąż muszę obejść błędy związane z węglem drzewnym ...Edycja: Zaoszczędziłem 5 bajtów, używając podwójnejMap
jako tablicy dla biednego człowieka. Zaoszczędzono 4 bajty, używającPop
do podwójnej iteracji po tablicy. Zaoszczędzono 3 bajty, używając konkatenacji zamiastPush
. Zaoszczędzono 10 bajtów, wprowadzającwhile
warunek golfisty , który pozwala również uniknąć błędu węgla drzewnego. Zaoszczędzono 1 bajt, odkrywając, że węgiel rzeczywiście ma operatora filtru. Wyjaśnienie:Podziel dane wejściowe na spacje, a następnie zawiń wynik w zewnętrznej tablicy, zapisując to w
q
.Powtarzaj, gdy pierwszy element
q
ma więcej niż jeden element. (Pierwszy elementq
zawsze ma najwięcej elementów ze względu na sposób podziału list na dwa).Wydrukuj elementy
q
połączonych spacjami i liniami pionowymi. (Tablica powoduje, że wynik jest drukowany we własnej linii. Istnieją inne sposoby osiągnięcia tego dla tej samej liczby bajtów.)Utwórz listę, powielając każdy element
q
, a następnie zmapuj tę listę i weź połowę każdej listy (stosując podejście do elementów alternatywnych), zapisując wynik z powrotemq
.Wydrukuj elementy
q
połączonych spacjami i liniami pionowymi. Właściwie w tym momencie elementyq
są albo listami pustymi, albo jednoelementowymi, więc połączenie ich po prostu przekształca je w puste łańcuchy lub ich elementy. Puste łańcuchy dodawałyby niepotrzebne końcowe linie, aby zostały odfiltrowane. Spłaszczony operator byłby jednak bardziej golfistą (coś w stylu⟦⪫Σθ|⟧
).Powtórz, gdy
q
ma więcej niż jeden element. (Poniższy kod wymaga parzystej liczby elementów).Skopiuj
q
doh
, ale cofnij (patrz poniżej) i zresetujq
do pustej listy.Powtarzaj, aż
h
będzie pusty.Wyciąg następny element
h
doe
. (Pop
wyciągi z końca, dlatego muszę cofnąćq
.)Zainicjuj
z
na pustej liście.Pętla nad elementami następnego elementu
h
.Skopiować
e
dod
i przywróciće
do pustej listy.Pętla nad elementami
d
.Popchnij je do
z
lub we
zależności od tego, czy są mniejsze niż bieżący element następnego elementuh
.Naciśnij bieżący element następnego elementu
h
doz
.Połącz
z
z pozostałymi elementamie
i popchnij to doq
. To kończy scalenie dwóch elementówh
.Wydrukuj elementy
q
połączonych spacjami i liniami pionowymi.źródło
while (...Map(...)...)
błąd, o którym już ci mówiłem.Python 2 ,
145144 bajtówPomysł z komentarza JungHwan Min
-1 bajt dzięki Jonathan Frech
Wypróbuj online!
źródło
<2
zamiast tego==1
.JavaScript (ES6), 145 bajtów
Pobiera dane wejściowe jako tablicę w obrębie tablicy, tj
f([[6,5,4,3,2,1]])
. Działa, generując pierwszy i ostatni wiersz wyniku, a następnie dzieląc i wywołując się ponownie, aż każda podgrupa ma długość 1. Oto podstawowa demonstracja tego, jak to działa:źródło
Łuska , 14 bajtów
Pobiera tablicę zawierającą pojedynczą tablicę. Wypróbuj online!
Wyjaśnienie
Wbudowany
½
pobiera tablicę i dzieli ją na środku. Jeśli jego długość jest nieparzysta, pierwsza część jest dłuższa o jeden element. Tablicy Singleton[a]
skutkuje[[a],[]]
i pusta tablica[]
daje[[],[]]
, więc jest to konieczne w celu usunięcia pustych tablic przed zastosowaniemU
.źródło
Stax ,
116 (÷ 3>)3829 bajtów CP437-9 bajtów na komentarz przez @recursive. Teraz dane wejściowe podano jako singleton, którego jedynym elementem jest tablica liczb do posortowania.
Wypróbuj online!
Wersja rozpakowana z 35 bajtami:
Wyjaśnienie
Kod można podzielić na dwie części. Pierwsza część wizualizuje podział, a druga wizualizuje scalanie.
Kod do wizualizacji podziału:
Kod wizualizacji scalania:
Stara wersja, właściwie budująca zagnieżdżoną strukturę listy.
cc0+=
jest używany trzy razy w kodzie, aby sprawdzić, czy szczyt stosu jest skalarem, czy tablicą.{{cc0+=!{x!}Mm',*:}}X
buduje blok, który rekurencyjnie wywołuje się, aby poprawnie wypisać zagnieżdżoną tablicę liczb. (Domyślne wyjście w Stax wektoryzuje zagnieżdżoną tablicę przed drukowaniem).Istnieją dwa inne bloki, które odpowiednio dzielą i scalają. Są zbyt gadatliwi i nie dbam o wyjaśnienia (w historycznej wersji tego postu jest nieco więcej informacji, ale nie oczekuję zbyt wiele).
źródło
cH!
można go użyć zamiastcH%!
.{Nd}M
można zastąpićT
również.