Znalazłem tę sekwencję podczas pracy nad Ewolucją OEIS , ale nigdy nie udało mi się opublikować jej jako odpowiedzi. Po napisaniu referencyjnej implementacji w Mathematica pomyślałem, że jest to zabawne ćwiczenie jako osobne wyzwanie, więc proszę bardzo.
Zbudujmy numeryczny reaktor rozszczepiający! Rozważ dodatnią liczbę całkowitą N
. Jako przykład przyjrzymy się 24
. Aby rozdzielić tę liczbę, musimy znaleźć największą liczbę kolejnych liczb całkowitych dodatnich, które sumują się N
. W tym przypadku tak jest 7 + 8 + 9 = 24
. Podzieliliśmy się 24
na trzy nowe liczby. Ale to nie byłby duży reaktor rozszczepiający bez reakcji łańcuchowych. Powtórzmy więc rekurencyjnie proces dla tych komponentów:
24
/|\
/ | \
/ | \
7 8 9
/ \ /|\
3 4 / | \
/ \ / | \
1 2 2 3 4
/ \
1 2
Zauważ, że zatrzymujemy proces, ilekroć liczby nie można rozłożyć na mniejsze kolejne liczby całkowite. Zauważ też, że moglibyśmy napisać 9
jako 4 + 5
, ale 2 + 3 + 4
ma więcej składników. Liczba Rozszczepienie z N
obecnie definiowany jako liczba całkowitych otrzymywanych w tym procesie, w tym N
sam. Powyższe drzewo ma 13 węzłów, więc F(24) = 13
.
Ta sekwencja to pozycja OEIS A256504 .
Pierwsze 40 warunków, począwszy od N = 1
, są
1, 1, 3, 1, 5, 6, 5, 1, 6, 7, 12, 10, 12, 11, 12, 1, 8, 16, 14, 17, 18, 18,
23, 13, 21, 18, 22, 23, 24, 19, 14, 1, 22, 20, 23, 24, 31, 27, 25, 26
Pierwsze 1000 haseł można znaleźć w tym pastebin .
Wyzwanie
Biorąc pod uwagę dodatnią liczbę całkowitą N
, określ jej numer rozszczepienia F(N)
. (Więc nie musisz obejmować wiodących 0
wymienionych w OEIS.)
Możesz napisać program lub funkcję, pobierając dane wejściowe przez STDIN (lub najbliższą alternatywę), argument wiersza poleceń lub argument funkcji i wypisując wynik przez STDOUT (lub najbliższą alternatywę), wartość zwracaną funkcji lub parametr funkcji
To jest kod golfowy, więc wygrywa najkrótsza odpowiedź (w bajtach).
Dodatkowe pytanie: czy możesz znaleźć jakieś interesujące właściwości tej sekwencji?
źródło
Odpowiedzi:
Pyth,
232221 bajtówDefiniuje to funkcję rekurencyjną
y
. Wypróbuj online: DemonstracjaWyjaśnienie:
źródło
Rozszczepienie ,
1328989887797 bajtówTa odpowiedź jest nieco nieuzasadniona długa (szkoda, że nie mieliśmy zwijanych regionów ) ... proszę nie zapomnij przewinąć obok tego i pokazać innym odpowiedziom trochę miłości!
Praca nad tym kodem była tym, co zainspirowało to wyzwanie. Chciałem dodać odpowiedź w Fission do EOEIS, co doprowadziło mnie do tej sekwencji. Jednak faktyczne nauczenie się rozszczepienia i jego wdrożenie zajęło kilka tygodni nad jego włączeniem i wyłączeniem. W międzyczasie sekwencja naprawdę mnie rozrosła, więc postanowiłem postawić dla niej osobne wyzwanie (plus, i tak nie byłoby to szczególnie daleko na drzewie w EOEIS).
Przedstawiam wam więc Monstrum:
Oczekuje, że na wejściu nie ma końcowego znaku nowej linii, więc możesz chcieć go tak nazwać
echo -n 120 | ./Fission oeis256504.fis
.Układ prawdopodobnie prawdopodobnie byłby bardziej wydajny, więc myślę, że wciąż jest tu dużo miejsca na ulepszenia (na przykład zawiera on
911581461374 spacji).Zanim przejdziemy do wyjaśnienia, uwaga na temat przetestowania tego: oficjalny tłumacz nie działa tak jak jest. a)
Mirror.cpp
nie kompiluje się na wielu systemach. Jeśli napotkasz ten problem, po prostu skomentuj obraźliwą linię - dotknięty komponent (losowe lustro) nie jest używany w tym kodzie. b) Istnieje kilka błędów, które mogą prowadzić do nieokreślonego zachowania (i prawdopodobnie tak będzie w przypadku tak złożonego programu). Możesz zastosować tę poprawkę, aby je naprawić. Gdy to zrobisz, powinieneś być w stanie skompilować interpreteraCiekawostka: ten program wykorzystuje prawie każdy element, jaki ma do zaoferowania Fission, z wyjątkiem
#
(losowego lustra),:
(pół lustra)-
lub|
(zwykłego lustra) i"
(trybu drukowania).Co u licha
Ostrzeżenie: potrwa to dość długo ... Zakładam, że naprawdę interesujesz się działaniem Fission i tym, jak można w nim zaprogramować. Ponieważ jeśli nie, nie jestem pewien, jak mógłbym to podsumować. (Następny akapit zawiera jednak ogólny opis języka.)
Rozszczepienie jest dwuwymiarowym językiem programowania, w którym zarówno przepływ danych, jak i sterowania są reprezentowane przez atomy poruszające się po siatce. Jeśli widziałeś lub używałeś Marbelous wcześniej, koncepcja powinna być niejasno znana. Każdy atom ma dwie właściwości całkowite: nieujemną masę i dowolną energię. Jeśli masa kiedykolwiek stanie się ujemna, atom zostanie usunięty z siatki. W większości przypadków można traktować masę jako „wartość” atomu, a energię jako rodzaj meta-właściwości, która jest wykorzystywana przez kilka składników do określania przepływu atomów (tzn. Większość rodzajów przełączników zależy od znaku energia). W
(m,E)
razie potrzeby oznaczę atomy . Na początku programu siatka zaczyna się od kilku(1,0)
atomy z dowolnego miejsca na czterech składnikachUDLR
(gdzie litera wskazuje kierunek, w którym początkowo porusza się atom). Płytka jest następnie wypełniona całą masą składników, które zmieniają masę i energię atomów, zmieniają ich kierunki lub robią inne, bardziej wyrafinowane rzeczy. Pełna lista znajduje się na stronie esolangów , ale większość z nich przedstawię w tym objaśnieniu. Innym ważnym punktem (z którego program korzysta kilka razy) jest to, że siatka jest toroidalna: atom, który uderza w którąkolwiek ze stron, pojawia się po przeciwnej stronie, poruszając się w tym samym kierunku.Napisałem program w kilku mniejszych częściach i na końcu je zmontowałem, więc w ten sposób przejdę przez wyjaśnienie.
atoi
Ten element może wydawać się raczej nieciekawy, ale jest ładny i prosty i pozwala mi wprowadzić wiele ważnych pojęć dotyczących arytmetyki i przepływu sterowania Fission. Dlatego przejrzę tę część z bardzo drobiazgowymi szczegółami, więc mogę zredukować inne części do wprowadzenia nowej mechaniki rozszczepienia i wskazania komponentów wyższego poziomu, których szczegółowy przepływ kontroli powinieneś być w stanie śledzić.
Rozszczepienie może odczytać tylko wartości bajtów z pojedynczych znaków, a nie z całych liczb. Chociaż jest to akceptowalna praktyka tutaj, pomyślałem, że będąc przy tym, mogę to zrobić poprawnie i przeanalizować rzeczywiste liczby całkowite na STDIN. Oto
atoi
kod:Dwa najważniejsze elementy rozszczepienia to reaktory rozszczepienia i syntezy jądrowej. Reaktory rozszczepienia są dowolnymi
V^<>
(powyższy kod używa<
i>
). Reaktor rozszczepienia może przechowywać atom (wysyłając go do klina postaci), domyślnie(2,0)
. Jeśli atom uderzy w wierzchołek postaci, dwa nowe atomy zostaną wysłane na boki. Ich masę określa się dzieląc przychodzącą masę przez masę przechowywaną (tj. Domyślnie o połowę) - atom lewostronny otrzymuje tę wartość, a atom prawostronny otrzymuje resztę masy (tj. Masa jest zachowana w rozszczepieniu) . Oba wychodzące atomy będą miały przychodzącą energię minuszmagazynowana energia. Oznacza to, że możemy wykorzystać reaktory rozszczepienia do arytmetyki - zarówno do odejmowania, jak i dzielenia. Jeśli reaktor rozszczepiony zostanie trafiony z miejsca, atom jest po prostu odbijany po przekątnej, a następnie porusza się w kierunku wierzchołka postaci.Reaktory termojądrowe są dowolnymi
YA{}
(powyższy kod używaY
i{
). Ich funkcja jest podobna: mogą przechowywać atom (domyślnie(1,0)
), a po trafieniu ze szczytu dwa nowe atomy zostaną wysłane na boki. Jednak w tym przypadku dwa atomy będą identyczne, zawsze zachowując przychodzącą energię i mnożąc przychodzącą masę przez zmagazynowaną masę. To znaczy, że reaktor termojądrowy po prostu powiela każdy atom uderzający w jego wierzchołek. Po uderzeniu z boku reaktory termojądrowe są nieco bardziej skomplikowane: atom teżprzechowywane (niezależnie od innej pamięci), aż atom uderzy w przeciwną stronę. Kiedy tak się dzieje, nowy atom zostaje uwolniony w kierunku wierzchołka, którego masa i energia są sumą dwóch starych atomów. Jeśli nowy atom uderzy w tę samą stronę, zanim dopasowany atom dotrze do przeciwnej strony, stary atom zostanie po prostu nadpisany. Reaktory termojądrowe można wykorzystać do realizacji dodawania i mnożenia.Kolejnym prostym składnikiem, który chcę usunąć z drogi,
[
i]
który po prostu ustawia kierunek atomu odpowiednio w prawo i w lewo (niezależnie od kierunku nadchodzącego). Pionowe odpowiedniki toM
(w dół) iW
(w górę), ale nie są używane watoi
kodzie.UDLR
działają również jakWM][
po uwolnieniu swoich początkowych atomów.W każdym razie spójrzmy na kod tam. Program zaczyna się od 5 atomów:
R
IL
u dołu po prostu uzyskać ich przyrost masy (w+
), aby się(10,0)
, a następnie przechowywano w rozszczepienia i reaktor syntezy, odpowiednio. Użyjemy tych reaktorów do parsowania danych wejściowych base-10.L
prawym górnym rogu jego masa jest zmniejszana (za pomocą_
), aby stać się(0,0)
i jest przechowywana z boku reaktora termojądrowegoY
. Ma to na celu śledzenie liczby, którą czytamy - stopniowo zwiększamy i mnożymy ją, gdy czytamy liczby.R
lewym górnym rogu ustawiono masę na kod znaku0
(48) za pomocą'0
, następnie masę i energię zamieniono na,@
a na koniec raz zwiększono masę,+
aby dać(1,48)
. Następnie jest przekierowywany za pomocą zwierciadeł ukośnych\
i/
przechowywany w reaktorze rozszczepiającym. Użyjemy48
do odejmowania, aby przekształcić dane wejściowe ASCII w rzeczywiste wartości cyfr. Musieliśmy także zwiększyć masę,1
aby uniknąć podziału według0
.U
w lewym dolnym rogu jest to, co faktycznie wprawia wszystko w ruch i początkowo jest używane tylko do sterowania przepływem.Po przekierowaniu w prawo atom kontrolny uderza
?
. To jest komponent wejściowy. Odczytuje znak i ustawia masę atomu na odczytaną wartość ASCII i energię na0
. Jeśli zamiast tego uderzymy w EOF, energia zostanie ustawiona na1
.Atom kontynuuje, a następnie uderza
%
. To jest przełącznik lustrzany. W przypadku energii dodatniej działa to jak/
lustro. Ale dla energii dodatniej działa jak\
(i zmniejsza energię o 1). Tak więc, gdy czytamy postacie, atom zostanie odbity w górę i możemy przetworzyć postać. Ale kiedy skończymy z wprowadzaniem danych, atom zostanie odbity w dół i możemy zastosować inną logikę, aby uzyskać wynik. FYI, przeciwny składnik to&
.Więc na razie ruszamy atomem. Dla każdego znaku chcemy odczytać jego wartość cyfrową, dodać to do naszej sumy bieżącej, a następnie pomnożyć tę sumę bieżącą przez 10, aby przygotować się do następnej cyfry.
Atom postaci najpierw uderza w (domyślny) reaktor termojądrowy
Y
. Dzieli to atom i używamy lewej kopii jako atomu kontrolnego, aby zapętlić się z powrotem do komponentu wejściowego i odczytać następny znak. Odpowiednia kopia zostanie przetworzona. Rozważ przypadek, w którym przeczytaliśmy postać3
. Nasz atom będzie(51,0)
. Zamieniamy masę i energię@
, dzięki czemu możemy skorzystać z odejmowania następnego reaktora rozszczepiającego. Reaktor odejmuje48
energię (bez zmiany masy), więc wysyła dwie kopie(0,3)
- energia odpowiada teraz odczytanej cyfrze. Nadchodząca kopia jest po prostu odrzucana za pomocą;
(komponentu, który po prostu niszczy wszystkie przychodzące atomy). Będziemy kontynuować pracę z poniższą kopią. Musisz podążać jego ścieżką przez/
i\
trochę odzwierciedla.@
Tuż przed reaktora termojądrowego swapy masy i energii znowu tak, że dodamy(3,0)
do naszej uruchomiony w sumieY
. Zauważ, że sama bieżąca suma zawsze będzie miała0
energię.Teraz
J
jest skok. To, co robi, to przeskakuje każdy nadchodzący atom do przodu dzięki swojej energii. Jeśli tak0
, atom po prostu idzie prosto. Jeśli tak,1
pominie jedną komórkę, jeśli tak,2
pominie dwie komórki i tak dalej. Energia jest wydawana w skoku, więc atom zawsze kończy się energią0
. Ponieważ suma bieżąca ma zerową energię, skok jest na razie ignorowany, a atom zostaje przekierowany do reaktora termojądrowego,{
który zwielokrotnia jego masę10
. Pobrana kopia jest odrzucana,;
podczas gdy kopia wysyłana jest z powrotem doY
reaktora jako nowa suma robocza .Powyższe powtarza się (w zabawny sposób, w którym nowe cyfry są przetwarzane przed wykonaniem poprzednich), dopóki nie trafimy do EOF. Teraz
%
wyśle atom w dół. Chodzi o to, aby przekształcić ten atom(0,1)
teraz przed uderzeniem w działający reaktor całkowity, aby a) nie wpłynęło to na sumę (masa zerowa) ib) otrzymamy energię1
przeskakiwania[
. Możemy łatwo zadbać o energię$
, która zwiększa energię.Problem polega na tym
?
, że masa nie resetuje się, gdy uderzasz w EOF, więc masa nadal będzie równa masie ostatniego odczytanego znaku, a energia będzie0
(ponieważ%
zmniejszyła się z1
powrotem do0
). Chcemy więc pozbyć się tej masy. Aby to zrobić, ponownie zamieniamy masę i energię@
.Muszę wprowadzić jeszcze jeden komponent przed kończąc ten rozdział:
Z
. Jest to zasadniczo to samo co%
lub&
. Różnica polega na tym, że przepuszcza on atomy energii dodatniej (jednocześnie zmniejszając energię) i odchyla atomy energii nie dodatniej o 90 stopni w lewo. Możemy to wykorzystać do wyeliminowania energii atomu, zapętlając ją wZ
kółko - gdy tylko energia zniknie, atom zostanie odchylony i opuści pętlę. To jest ten wzór:gdzie atom przesunie się w górę, gdy energia wyniesie zero. Będę używał tego wzorca w takiej czy innej formie kilka razy w innych częściach programu.
Kiedy więc atom opuści tę małą pętlę, zostanie
(1,0)
i zamieniany na(0,1)
nią@
przed uderzeniem w reaktor termojądrowy, aby uwolnić końcowy wynik wejścia. Jednak suma bieżąca zostanie zmniejszona 10-krotnie, ponieważ wstępnie pomnożono ją dla innej cyfry.Więc teraz z energią
1
ten atom przeskoczy[
i wskoczy do/
. To odchyla go do reaktora rozszczepienia, który przygotowaliśmy do podzielenia przez 10 i naprawienia naszego zewnętrznego mnożenia. Ponownie odrzucamy jedną połowę z,;
a drugą zachowujemy jako wyjście (tutaj reprezentowaneO
tym, po prostu wydrukujemy odpowiedni znak i zniszczymy atom - w pełnym programie zamiast tego używamy atomu).itoa
Oczywiście musimy również przekonwertować wynik z powrotem na ciąg i wydrukować go. Po to jest ta część. Zakłada się, że dane wejściowe nie pojawiają się przed kleszczem 10 lub więcej, ale w pełnym programie, który można łatwo podać. Ten bit można znaleźć na dole pełnego programu.
Ten kod wprowadza nowy, bardzo wydajny komponent rozszczepienia: stos
K
. Stos jest początkowo pusty. Kiedy atom z energią nieujemną uderza w stos, atom jest po prostu wpychany na stos. Kiedy atom o ujemnej energii trafi na stos, jego masa i energia zostaną zastąpione atomem na szczycie stosu (który w ten sposób pęknie). Jeśli stos jest pusty, kierunek atomu jest odwrócony, a jego energia staje się dodatnia (tzn. Jest mnożona-1
).OK, wracając do faktycznego kodu. Ideą tego
itoa
fragmentu jest wielokrotne przyjmowanie wejściowego modulo 10 w celu znalezienia następnej cyfry, przy jednoczesnym dzieleniu liczby całkowitej przez 10 na następną iterację. To da wszystkie cyfry w odwrotnej kolejności (od najmniej znaczącej do najbardziej znaczącej). Aby ustalić kolejność, wypychamy wszystkie cyfry na stos, a na końcu usuwamy je jeden po drugim, aby je wydrukować.Górna połowa kodu wykonuje obliczenia cyfrowe: za
L
pomocą plusów daje 10, które klonujemy i wprowadzamy do rozszczepienia i reaktora termojądrowego, abyśmy mogli podzielić i pomnożyć przez 10. Pętla zasadniczo zaczyna się po[
lewym górnym rogu . Bieżąca wartość jest dzielona: jedna kopia jest dzielona przez 10, a następnie mnożona przez 10 i przechowywana w reaktorze rozszczepiającym, który następnie trafia drugą kopią na szczycie. To jest obliczanei % 10
jakoi - ((i/10) * 10)
. Zauważ też, żeA
dzieli wynik pośredni po dzieleniu i przed pomnożeniem, tak że możemy przejśći / 10
do następnej iteracji.%
Przerywa pętlę raz zmienna iteracji uderza 0. Ponieważ jest to mniej lub bardziej do-while, kod ten będzie jeszcze praca do drukowania0
(bez tworzenia zer inaczej). Po opuszczeniu pętli chcemy opróżnić stos i wydrukować cyfry.S
jest przeciwieństwemZ
, więc jest to przełącznik, który odchyli nadchodzący atom o nie dodatniej energii o 90 stopni w prawo. Tak więc atom faktycznie przesuwa się nad krawędzią odS
prostej do linii,K
aby wyskoczył z cyfry (zwróć uwagę na to,~
co zapewnia, że nadchodzący atom ma energię-1
). Ta cyfra jest zwiększana o,48
aby uzyskać kod ASCII odpowiedniego znaku cyfry.A
Dzieli cyfrę, aby wydrukować jedną kopię z!
i podaj drugą kopię z powrotem doY
reaktora na następną cyfrę. Wydrukowana kopia jest używana jako następny wyzwalacz dla stosu (zwróć uwagę, że lustra wysyłają ją również wokół krawędzi, aby trafićM
w lewą stronę).Kiedy stos jest pusty,
K
odbija atom i zamienia jego energię w+1
taki sposób, że przechodzi on prosto przezS
.N
wypisuje nowy wiersz (tylko dlatego, że jest czysty :)). A potem atomR'0
znów idzie przez tor, by znaleźć się po stronieY
. Ponieważ w pobliżu nie ma już żadnych atomów, nie zostanie to nigdy uwolnione, a program się zakończy.Obliczanie numeru rozszczepienia: ramy
Przejdźmy do faktycznego mięsa programu. Kod jest w zasadzie portem mojej referencyjnej implementacji Mathematica:
gdzie
div
jest liczbą całkowitą w maksymalnej partycji.Główne różnice polegają na tym, że w Fission nie możemy sobie poradzić z wartościami całkowitymi, więc robię wiele rzeczy pomnożonych przez dwa i że w Fission nie ma rekurencji. Aby obejść ten problem, wypycham wszystkie liczby całkowite na partycji w kolejce do przetworzenia później. Dla każdej liczby, którą przetwarzamy, zwiększamy licznik o jeden, a gdy kolejka jest pusta, zwalniamy licznik i wysyłamy go do wydrukowania. (Kolejka
Q
działa dokładnie takK
samo, tylko w kolejności FIFO.)Oto ramy tej koncepcji:
Najważniejsze nowe elementy to cyfry. To są teleportery. Wszystkie teleportery o tej samej cyfrze należą do siebie. Gdy atom uderzy w dowolny teleporter, natychmiast przeniesie następny teleporter w tej samej grupie, gdzie następny jest ustalany w zwykłej kolejności od lewej do prawej, od góry do dołu. Nie są one konieczne, ale pomagają w układaniu (a więc i golfie). Są też takie,
X
które po prostu kopiują atom, wysyłając jedną kopię do przodu, a drugą do tyłu.Do tej pory możesz samodzielnie rozwiązać większość frameworka. W lewym górnym rogu jest kolejka wartości do przetworzenia i zwalniane są pojedynczo
n
. Jedna kopian
jest teleportowana na dół, ponieważ potrzebujemy jej podczas obliczania zakresu, druga kopia trafia do bloku u góry, który obliczadiv
(jest to zdecydowanie największa pojedyncza sekcja kodu). Podiv
obliczeniu jest duplikowany - jedna kopia inkrementuje licznik w prawym górnym rogu, w którym jest przechowywanyK
. Druga kopia jest teleportowana na dół. Jeślidiv
tak1
, natychmiast odchylamy go w górę i używamy jako wyzwalacza do następnej iteracji, bez kolejkowania żadnych nowych wartości. W przeciwnym razie używamydiv
in
w dolnej części, aby wygenerować nowy zakres (tj. strumień atomów o odpowiednich masach, które są następnie umieszczane w kolejce), a następnie zwolnić nowy wyzwalacz po zakończeniu zakresu.Gdy kolejka jest pusta, wyzwalacz zostanie odzwierciedlony, przechodząc prosto przez
S
i pojawiając się ponownie w prawym górnym rogu, skąd uwalnia licznik (wynik końcowy), zA
którego następnie zostaje teleportowanyitoa
przez8
.Obliczanie numeru rozszczepienia: ciało pętli
Pozostały więc tylko dwie sekcje do obliczenia
div
i wygenerowania zakresu. Komputerydiv
to ta część:Prawdopodobnie widziałeś już teraz wystarczająco dużo, aby rozwiązać to z cierpliwością. Podział wysokiego poziomu jest następujący: pierwsze 12 kolumn generuje strumień dzielników
2n
. Następne 10 kolumn odfiltrowuje te, które nie spełniająOddQ@# == IntegerQ[n/#]
. Następne 8 kolumn odfiltrowuje te, które nie spełniająn/# > (# - 1)/2)
. W końcu wpychamy wszystkie prawidłowe dzielniki na stos, a gdy skończyliśmy, opróżniamy cały stos do reaktora termojądrowego (nadpisując wszystkie oprócz ostatniego / największego dzielnika), a następnie zwalniamy wynik, a następnie eliminujemy jego energię (która nie była -zero od sprawdzania nierówności).Jest tam wiele szalonych ścieżek, które tak naprawdę nic nie robią. Przeważnie
\/\/\/\/
szaleństwo na górze (5
s są również jego częścią) i jedna ścieżka na dole (która przechodzi przez7
s). Musiałem je dodać, aby poradzić sobie z trudnymi warunkami wyścigowymi. Rozszczepienie może wykorzystywać składnik opóźniający ...Kod, który generuje nowy zakres
n
idiv
jest następujący:Najpierw obliczamy
n/div - (div + 1)/2
(oba wyrażenia zmiennoprzecinkowe, co daje ten sam wynik) i przechowujemy na później. Następnie generujemy zakres od wdiv
dół do1
i dodajemy zapamiętaną wartość do każdego z nich.W obu z nich są dwa nowe wspólne wzorce, o których powinienem wspomnieć: Jeden jest
SX
lubZX
trafiony od dołu (lub wersje obrócone). Jest to dobry sposób na duplikowanie atomu, jeśli chcesz, aby jedna kopia szła prosto przed siebie (ponieważ przekierowanie wyjść reaktora termojądrowego może czasami być kłopotliwe). TeS
iZ
obraca atom wX
a następnie obraca lustrzaną kopiowania z powrotem do pierwotnego kierunku propagacji.Drugi wzór to
Jeśli przechowujemy jakąkolwiek wartość
K
, możemy wielokrotnie ją odzyskać, uderzającK
ujemną energią z góry.A
Powiela wartość jesteśmy zainteresowani i wysyła co skopiować z powrotem na stos na następny raz my go potrzebujemy.Cóż, to był całkiem tome ... ale jeśli rzeczywiście to przeżyłeś, mam nadzieję, że wpadłeś na pomysł, że Fission i͝s̢̘̗̗ ͢i̟nç̮̩r̸̭̬̱͔e̟̹̟̜͟d̙i̠͙͎̖͓̯b̘̠͎̭̰̼l̶̪̙̮̥̮y̠̠͎̺͜ ͚̬̮f̟͞u̱̦̰͍n͍ ̜̠̙t̸̳̩̝o ̫͉̙͠p̯̱̭͙̜͙͞ŕ̮͓̜o̢̙̣̭g̩̼̣̝r̤͍͔̘̟ͅa̪̜͇m̳̭͔̤̞ͅ ͕̺͉̫̀ͅi͜n̳̯̗̳͇̹.̫̞̲̞̜̳
źródło
Now with 100% fewer scrollbars.
więc mówisz ... i nadal jest to kontynuacja ...CJam,
4241 bajtówProsta szerokość pierwszego przejścia i stan zatrzymania pustego następnego poziomu.
Jak to działa :
Wypróbuj online tutaj
źródło
Python 3, 112 bajtów
4 bajty zapisane dzięki @FryAmTheEggman.
Wyjaśnienie nastąpi później ...
Dodatkowy fakt: Każda potęga 2 ma liczbę rozszczepienia równą 1. Jest tak, ponieważ suma sekwencji o parzystej długości jest zawsze sumą dwóch środkowych liczb, która jest nieparzysta, pomnożona przez połowę długości sekwencji, która jest liczbą całkowitą . Suma sekwencji nieparzystej długości to środkowa liczba pomnożona przez długość sekwencji, która jest nieparzysta. Ponieważ potęga 2 nie ma dziwnego dzielnika, można ją wyrazić jedynie jako sumę samego siebie.
źródło
Python 2,
11110297 bajtówNieco czytelne:
Niezbyt czytelne:
Oba 97 bajtów.
b
ton
minus(a-1)th
trójkątna liczba. Jeślib % a == 0
,n
to sumaa
kolejnych liczb zaczynająca się odb
.źródło
1else
. Działa tylko drugie rozwiązanie. Dopiero Python 3else
może natychmiast podążać za liczbą.Python 2, 86
Mniej golfa:
Pomysł polega na przetestowaniu potencjalnych przebiegów kolejnych liczb całkowitych, które sumują się
n
. Przebieg jest przechowywany bezpośrednio bezpośrednio jako zestaw,R
a nie za pośrednictwem jego punktów końcowych.Sprawdzamy, jak suma bieżącego przebiegu porównuje się z żądaną sumą
n
poprzez ich różnicę.f
przebieg, sumując i dodając 1 dla bieżącego węzła. Jeśli przebieg jest{n}
, wypróbowaliśmy wszystkie nietrywialne możliwe kwoty, zatrzymaj rekurencję, usuwającn
najpierw.Dzięki Sp3000 za zapisanie 3 znaków.
źródło
Python 2, 85
Jestem bardzo dumny z tej odpowiedzi, ponieważ trwa ona już kilkadziesiąt sekund dla n = 9 i 5-10 minut dla n = 10. W code golf jest to uważane za pożądany atrybut programu.
Istnieje również wersja zwierająca, która nie trwa tak długo i wykorzystuje tę samą ilość bajtów:
Może być szybszy, ale przynajmniej przekracza domyślny limit rekurencji, gdy n przekroczy nieco 40.
Chodzi o to, aby wykonać wyszukiwanie brute force na liczbach
a
id
takie, żea + a+1 + ... + a+d == n
na wartości między 1 an
.f(n,a+d/n,d%n+1)
Gałąź rekursji przechodzi poprzez(a, d)
pary. W przypadku, gdy równość jest spełniona, udaje mi się uniknąć drogiegomap(range(...))
połączenia, dzieląc tylko na dwie gałęzie, niezależnie od długości sekwencji. Numerya+1
poprzezd
są skupione w jednym wywołaniuf
poprzez ustawieniea
parametru tak, że inny sposób podzielić się kolejność nie może być używany.źródło
Haskell,
7669 bajtówStosowanie:
Jak to działa:
źródło
Siatkówka , 66 bajtów
Pobiera dane wejściowe i drukuje dane wyjściowe jako jednoargumentowy.
Możesz umieścić każdą linię w jednym pliku lub uruchomić kod tak jak w przypadku
-s
flagi. Na przykład:Wyjaśnienie:
1
a resztę konwertujemy na1
.Stany ciągu w całym procesie z danymi wejściowymi
11111111111111 (unary 14)
:Wielkie dzięki za @MartinButtner za pomoc na czacie!
źródło
CJam (43 bajty)
Demo online
Jestem pewien, że brakuje mi trików z zaawansowanymi pętlami, ale to ładnie wykorzystuje właściwość CJam (która wcześniej mnie zirytowała), że w
%
mapie wyniki pozostają na stosie i dlatego można uzyskać do nich dostęp za$
pomocą przesunięcie ujemne.źródło
,
na początku./
i%
kilka innych domyślnie zamienia liczby w zakresy.,_m*
można zastąpić2m*
. Arytmetyczna wzór progresję można zastąpić~,>:Y_,+:+
i~\,>0\
staje się!Y
. Wreszcie, jeśli używasz{}#
zamiast{}=
, nie potrzebujesz)
późniejX
. Podsumowując:ri{):X2m*{~,>:Y_,+:+X=}#!Y{~$+}/)}%W=
Idź, 133 bajty
To jest mój pierwszy golfowy kod, przepraszam, jeśli popełniłem jakieś błędy.
Wykorzystuje to ideę, że „skład” rozszczepialny może być również postrzegany jako różnica między dwiema sekwencjami uporządkowanych liczb całkowitych. Weźmy na przykład „skład” rozszczepialny dla liczby 13. Jest to 6,7. Ale może to być postrzegane jako suma liczb całkowitych 1 ... 7 minus suma liczb całkowitych 1 ... 5
Przypomnijmy wzór z czasów szkolnych Gaussa, suma 1 ... n = (n ^ 2 + n) / 2. Aby więc znaleźć skład liczb całkowitych sekwencyjnych dla danego n, moglibyśmy również powiedzieć, że szukamy „punktów końcowych” p i q w zakresie 1 ... n, aby (p ^ 2 + p) / 2 - ( q ^ 2 + q) / 2 = n. W powyższym przykładzie szukalibyśmy „punktów końcowych” 5 i 7, ponieważ 7 ^ 2 + 7 = 56/2, 5 ^ 2 + 5 = 30/2, 56 / 2-30 / 2 = 28-15 = 13
Teraz istnieje wiele możliwych sposobów na skomponowanie liczby rozszczepialnej, jak zauważył Martin 9 = 2 + 3 + 4, ale także 4 + 5. Ale wydaje się oczywiste, że „najniższa” sekwencja początkowa również będzie najdłuższa, ponieważ zajmuje więcej małe liczby do zsumowania do dużej liczby niż liczby średnie. (Niestety nie mam dowodu)
Aby znaleźć skład 9, przetestuj każdą „parę punktów końcowych”, p i q, iterując zarówno p i q oddzielnie od 0 do 9, i sprawdź, czy p ^ p + p / 2 - q ^ 2 + q / 2 = 9. Lub prościej, pomnóż równanie przez 2, aby uniknąć problemów z dzieleniem zaokrąglania i zachować całą matematykę w liczbach całkowitych. Następnie szukamy p i q takich, że (p ^ p + p) - (q ^ q + q) = 9 * 2. Pierwszym znalezionym przez nas dopasowaniem będą punkty końcowe składu rozszczepialnego, ponieważ, jak zauważono, najniższa grupa liczb będzie również najdłuższa, a my szukamy od niskiej do wysokiej (od 0 do 9). Zrywamy się z pętli, gdy tylko znajdziemy dopasowanie.
Teraz funkcja rekurencyjna znajduje te „rozszczepialne punkty końcowe” p i q dla danego n, a następnie przywołuje sama dla każdego z „dzieci” w drzewie od p do q. Dla 9 znalazłby 1 i 4 (20-2 = 18), a następnie ponownie wywołałby się na 2, 3 i 4, sumując wyniki. W przypadku liczb takich jak 4 po prostu nigdy nie znajduje dopasowania, dlatego zwraca „1”. To może być skracalne, ale jest to jak mój trzeci program go i nie jestem ekspertem od rekurencji.
Dziękuje za przeczytanie.
źródło
CJam,
403533 bajtówDzięki @Optimizer za sugestie
few
, które pozwoliły zaoszczędzić 2 bajty.Wypróbuj online w interpretatorze CJam .
Jak to działa
źródło
ri{_,:)_few:+W%{1b1$=}=|{F}*}:F~],