Jak omówiono w salonie w przepełnieniu stosu:
jeśli nie możesz wdrożyć algorytmu Quicksort podanego en.wikipedia.org/wiki/Quicksort w dowolnym języku, który znasz minimalnie, możesz rozważyć inny zawód. @sbi
ale SBI zauważyło również, że może BrainF *** był wyjątkiem.
Oto zagadka / wyzwanie: zaimplementuj QuickSort w BrainF *** . Wdrożenie musi
code-challenge
sorting
brainfuck
Ronald
źródło
źródło
Odpowiedzi:
BrainF * (697 bajtów)
Poniżej znajduje się wersja z adnotacjami. Aby śledzić, co miało się wydarzyć podczas jego opracowywania, użyłem notacji komentarza, która wygląda następująco:
|a|b=0|c=A0|@d|A0|A1|```|
Pamięć jest ułożona z rosnącym w lewo stosem partycji do przetwarzania po lewej stronie, miejscem na zarysowania pośrodku i tablicą sortowaną po prawej stronie. Indeksowanie tablic odbywa się poprzez przeniesienie „szyny danych” zawierającej indeks i przestrzeń roboczą przez tablicę. Na przykład 3-szerokościowy autobus
|i|data|0|A0|A1|A2
stanie się|A0|i-1|data|0|A1|A2
po zmianie o jeden. Partycjonowanie odbywa się poprzez utrzymanie magistrali między elementami wysokimi i niskimi.Oto pełna wersja:
źródło
if (i<j) {} else {}
wymagały kilku prób poprawnego działania. A skrzynki na krawędzi to zabójcy. Nie wiem, ile razy myślałem „pozostała tylko jedna drobna rzecz…”, a potem odkryłem przypadek testowy, który spowodował, że poradziłem sobie z kilkoma godzinami pracy. Myślę, że mogę to zmniejszyć o kilkadziesiąt znaków, ale nie jestem pewien, czy chcę się w to włożyć.brainfuck (178 bajtów)
Nawet jeśli pieprzenie mózgu jest uciążliwe, pomaga pracować z ziarnem języka. Zadaj sobie pytanie „Czy muszę wyraźnie przechowywać tę wartość w komórce?” Często można uzyskać szybkość i zwięzłość, robiąc coś bardziej subtelnego. A gdy wartość jest indeksem tablicowym (lub dowolną liczbą naturalną), może nie zmieścić się w komórce. Oczywiście możesz zaakceptować to jako ograniczenie swojego programu. Ale zaprojektowanie programu do obsługi dużych wartości często poprawi go na inne sposoby.
Jak zwykle moja pierwsza działająca wersja była dwa razy dłuższa niż potrzebna - 392 bajty. Liczne modyfikacje i dwa lub trzy duże przepisywania spowodowały, że ta stosunkowo wdzięczna 178-bajtowa wersja. (Choć zabawnie, sortowanie według czasu liniowego ma tylko 40 bajtów.)
Wartości wejściowe są rozmieszczone co trzy komórki: dla każdej (V) komórki alue jest komórka abel (L) (używana do nawigacji) i jeszcze jedna komórka dla (S) przestrzeni do rysowania. Ogólny układ tablicy to
0 1 0 0 0 SVLSVL ... SVL 0 0 0 0 0 0 ...
Początkowo wszystkie komórki L są ustawione na 1, aby oznaczyć części tablicy, które nadal wymagają sortowania. Kiedy skończymy dzielenie podtablicy, dzielimy ją na mniejsze podgrupy, ustawiając komórkę L jej osi przestawnej na 0, a następnie lokalizujemy skrajnie prawą komórkę L, która wciąż jest 1, i dzielimy tę podtablicę dalej. Dziwne, to wszystko, czego potrzebujemy do prowadzenia księgowości, aby poprawnie obsłużyć rekurencyjne przetwarzanie subarrays. Po wyzerowaniu wszystkich komórek L cała tablica jest sortowana.
Aby podzielić tablicę podrzędną, przeciągamy jej skrajną prawą wartość do komórki S, aby działała jako oś obrotu, i pozostawiamy ją (i odpowiadającą jej pustą komórkę V) w lewo, porównując ją ze sobą w podtablicy i zamieniając w razie potrzeby. Na końcu oś przestawiana jest z powrotem, przy użyciu tego samego kodu wymiany (co oszczędza około 50 bajtów). Podczas dzielenia dwie dodatkowe komórki L są ustawione na 0, aby zaznaczyć dwie komórki, które mogą wymagać wymiany; pod koniec podziału lewe 0 połączy się z 0 po lewej stronie podtablicy, a prawe 0 zakończy się zaznaczeniem jego osi obrotu. Ten proces pozostawia dodatkowo 1 w komórce L na prawo od podtablicy; główna pętla zaczyna się i kończy w tej komórce.
źródło