Tekst aromatyzujący
Stos oparte esolang niedoci¿eniem ma jakieś ciekawe powiązania programowania funkcjonalnego. Jednym z nich jest traktowanie liczbowego typu danych - podobnie jak rachunek lambda, reprezentujesz liczbę naturalną N za pomocą funkcji, która wykonuje akcję N razy.
Aby uprościć sprawę, rozważymy tylko następujący podzbiór poleceń niedociążenia:
:
- To polecenie powiela najwyższy element na stosie.*
- To polecenie łączy dwa górne elementy stosu w jeden element.
Określamy niedociążenia liczbowy N jako łańcuch :
i *
która, gdy jest wykonywany, zajmują pozycję górną na stosie, i wytwarzania N kopii tego elementu sklejone. Kilka przykładów:
- Nie ma cyfr niedociążenia 0, -1, 1/2, π.
- Pusty ciąg
jest liczbą niedociążoną 1, ponieważ pozostawia stos nietknięty.
:*
jest liczbą niedociążoną 2, ponieważ kopiuje najwyższy element, a następnie łączy te dwie kopie razem w jeden element:(A):*
=(A)(A)*
=(AA)
.::**
jest liczbą niedociążenia 3:(A)::**
=(A)(A):**
=(A)(AA)*
=(AAA)
.:::***
jest liczbą niedociążenia 4.:*:*
jest również liczbą niedociążenia 4:(A):*:*
=(AA):*
=(AA)(AA)*
=(AAAA)
.
Ogólnie rzecz biorąc, przekonasz się, że jeśli M
i N
są liczbami niedociążenia M i N, to :N*
jest liczbą N + 1 i MN
jest liczbą M × N.
Wyzwanie
Twoim zadaniem jest napisanie najkrótszego programu (przyjmującego dane wejściowe na STDIN) lub funkcji (przyjmującego dane wejściowe za pomocą argumentu), który tworzy najkrótszą reprezentację liczby niedociążenia dla jej danych wejściowych w postaci łańcucha. To znaczy, jeśli wejściowa liczba jest dodatnią liczbą naturalną N> 1, musisz utworzyć liczbę niedociążenia N, której długość w znakach jest mniejsza lub równa długości każdej innej liczby niedociążenia N.
Przykładowe wejścia i wyjścia: („Input - OUTPUT
.”)
- 1 -
.
- 2 -
:*
. - 5 -
::*:**
(2 × 2 + 1). - 7 -
::*::***
(2 × 3 + 1) lub:::**:**
(3 × 2 + 1). - 33 -
::*:*:*:*:**
(2 × 2 × 2 × 2 × 2 + 1). - 49 -
::*:*:*:*::***
(16 × 3 + 1, długość 14), ale nie::*::***::*::***
(7 × 7, długość 16).
Jeśli dane wejściowe nie są dodatnią liczbą naturalną, możesz zwrócić błąd, wywołać niezdefiniowane zachowanie, a nawet nie zakończyć działania. Docenione zostanie wyjaśnienie metody przesłania odpowiedzi.
Standardowe ograniczenia loophole zastosowania: brak dodatkowego nakładu, żadnych żądań internetowych, wartość wyjściowa / powrót musi być dokładnie taka odpowiedź i nie nieskończony strumień losowych :
i *
itp
x
jest2*A117498(x)
tam, gdzie A117498 daje optymalną kombinację metod binarnych i czynnikowych do znalezienia łańcucha dodatków.Odpowiedzi:
GolfScript (
61 60 55 5453 znaków)Jest to mniej skomplikowane niż moja wcześniejsza wersja i ma nieco inne podejście, ale wciąż jest brutalne. Wiemy, że
':'X*'*'X*+
jest to rozwiązanie kandydujące, więc jeśli wygenerujemy wszystkie dobrze zbalansowane łańcuchy do tej długości i weźmiemy najkrótszy, który ocenia właściwą rzecz, możemy być pewni, że go znajdziemy.Dzięki Howardowi, z którego rozwiązania ukradłem kilka drobnych usprawnień.
źródło
.&
bezpośrednio za pętlą wewnętrzną (tj. Między~}%
i}*
.GolfScript (
5453 znaki)Jest to podejście zgodne z duchem Howarda (budowanie łańcuchów, które oceniają na prawidłową wartość i wybieranie najkrótszej, a nie brutalnej siły poprzez łańcuchy kandydatów, aby znaleźć te, które oceniają na prawidłową wartość), ale jest wystarczająco inne, niż myślę należy do osobnej odpowiedzi.
Demo online nie jest dostępne, ponieważ działa błędna wersja interpretera.
źródło
3+
go)
(wykorzystując fakt, że[]0=
nic nie pozostawia na stosie), gdyby nie[]2>
prowadziło to do błędu.[]2>
daje[]
bez błędu.'1'
.((=
zamiast-1=
.Python 2.7 -
878492Objaśnienie:
Jest to dość proste rozwiązanie. Rekurencyjnie testuje wszystkie możliwe reprezentacje n jako iloczyn dwóch liczb lub jako
:(n-1)*
, a następnie znajduje rozwiązanie minimalnej długości. zakres (2, n) jest konieczny, aby rekursja ograniczała głębokość, a n <2 daje przypadek podstawowy.Uwagi:
i oraz n / i to dwa czynniki n. ... i ... lub ... zamiennik ... jeśli ... inaczej ... nie działa, ponieważ '' zwraca wartość false. min ciągów daje jeden z najkrótszych ciągów. Python 2.7 zapisuje 1 znak przy użyciu / zamiast //.
Edycja: przeniesiono podstawową skrzynkę na tył wyrażenia, pozwalając mi użyć ... i ... lub ... i ogolić kilka miejsc.
Przypadki testowe:
źródło
key=len
. Daje leksykograficznie najwcześniejszy ciąg. ( Przykład ). Ponieważ'*' < ':'
oznacza to, że masz tendencję do rozwiązywania problemów z potęgami 2, ale czy zawsze są one najkrótsze?u(33)
, dla którego sortowanie leksykograficzne daje 14 znaków,::**::*::*:***
ale sortowanie według długości daje 12 znaków::*:*:*:*:**
GolfScript,
635856 znakówKod pobiera dane wejściowe STDIN i drukuje wynik.
Przykłady:
Możesz przetestować własne przypadki online .
źródło
:x(=
. Ponadto +1 za możliwość uruchomienia 49 w rozsądnym czasie.x,2>{x\%!},
podaje wszystkie prawdziwe dzielnikix
,{.v=x@/v=+}/
a następnie konkatenuje rozwiązania dlad
ix/d
dla wszystkich dzielnikówd
.{,}$
sortuje je według długości i0=
zajmuje najkrótszą z nich (plus początkowy:(x-1)*
przypadek).Brachylog 2 , 30 (może w końcu 26) bajtów, wyzwanie dla postdate języka
Oto funkcja, która działa z bieżącą implementacją Brachylog 2 (i zwraca listę kodów znaków, ponieważ obecna implementacja ma pewne problemy z obsługą łańcuchów):
Wypróbuj online!
Język jest wciąż bardzo nowy. Oto 26-bajtowa wersja programu, która powinna działać zgodnie ze specyfikacją, ale wykorzystuje pewne niezaimplementowane funkcje, a zatem nie jest jeszcze ważna, ale może będzie w przyszłości (jest nawet jeszcze mniej wydajna):
Wyjaśnienie
Podstawowa idea jest dość prosta: na przemian rozkładamy liczbę na (1 lub więcej) czynników (niekoniecznie czynniki pierwsze, ale czynniki 1 nie są dozwolone) i wyrażamy każdy z nich jako 1 + (reprezentacja uzyskana z rekurencyjnego połączenie). Gwarantuje to przeszukanie wszystkich możliwych reprezentacji niedociążenia liczby (możemy zastosować etap mnożenia „dwa razy z rzędu” przez pomnożenie razem więcej niż 2 liczb oraz etap przyrostu dwa razy z rzędu poprzez oddzielenie ich od etapu mnożenia, który zwielokrotnia razem tylko jedna liczba). Nie potrzebujemy wyraźnego przypadku podstawowego, ponieważ rozkład 1 na czynniki pierwsze daje nam pustą listę, a zatem tworzymy ją z etapem mnożenia, który zwielokrotnia liczby zerowe razem.
Program jest dość nieefektywny, szczególnie dlatego, że podałem wskazówkę dotyczącą kolejności oceny (generuję odpowiedzi od najkrótszych do najdłuższych pod względem wielkości ostatecznego wyniku), a jednocześnie rozwiązując „najkrótszą” część pytania, nie jest tak świetne pod względem faktycznie sprawiając, że program szybko się skompletuje (o wiele bardziej użyteczną wskazówką byłoby „generowanie tylko najkrótszej odpowiedzi na każdym etapie rekurencyjnym”, ale to zajmuje więcej bajtów…). Dodatkowo
ḋp~c×ᵐ
może generować multiplikatywne partycje kilka razy, co powoduje, że program wykonuje wiele zbędnych czynności.źródło
J - 81 znaków
Dla potomności było to najlepsze, co mogłem zrobić w J.
Tworzymy listę wyników, zaczynając od dwóch pustych ciągów (to jest
,~
ia:
) reprezentujących 0 (nigdy nie używanych) i 1, a następnie iterujemy nad nimi czasownik (podstępne użycie haków, pociągów i&
), który dołącza najkrótszą reprezentację następnego numeru.Rzeczywisty czasownik, który iterujemy, wykorzystuje długość listy jako wskaźnik tego, na jakiej liczbie operujemy. Najpierw dzielimy tę liczbę na pary czynników (
#(#~]-:"1<.)@(],.%)2}.i.@#
) i pobieramy każdą parę, wyciągając z tablicy ({~
). Zamieniamy każdą z tych par (może być 0, jeśli liczba jest liczbą pierwszą) na pojedyncze ciągi (<@;"1
).Następnie dołączyć do tej listy wpis dla poprzedniego wyniku nawiasie
:
i*
oraz sortowania tej listy długości ((/:#&>)
). Na koniec bierzemy pierwszy wynik z tej listy (0{
) i dołączamy go na końcu tablicy podstawowej ([,
). Po zakończeniu iteracji pętli mamy listę o długości 2 większą niż dane wejściowe, zaczynając od 0. Więc to, co musimy zwrócić, to ciąg znaków „od końca do ostatniego” (_2{::
).źródło
Galaretka , 33 bajty, wyzwanie dla postdate języka
Wypróbuj online!
Proste rozwiązanie brutalnej siły.
Wyjaśnienie
Główny program
Program główny używa funkcji pomocnika do wyliczenia wszystkich możliwych sposobów generowania wartości przez mnożenie, a następnie próbuje wygenerować wartość przez dodanie i zwraca najkrótszą możliwość. Obsługuje również skrzynkę podstawową (wejście
1
).Funkcja pomocnika
Funkcja pomocnika próbuje wszystkich możliwych metod wyrażania danych wejściowych jako mnożenia dwóch liczb i wzajemnie rekurencyjnie wywołuje program główny w celu uzyskania ich najkrótszych reprezentacji.
źródło
GNU Prolog, 96 bajtów
Pierwszy wiersz to gramatyka, która implementuje ocenę niedociążenia i działa w odwrotnym kierunku (w rzeczywistości nie działa całkiem do przodu z powodu
A#<B
ograniczenia; zmień toA#<N
na wolniejszy program, który działa w obie strony). Drugi wiersz definiuje predykat podobny do funkcjis
(która jest funkcją zaimplementowaną jako rozwiązanie tego programu), która znajduje najkrótszy możliwy ciąg, który ocenia na liczbę podaną jako dane wejściowe (jest to frustrująco szczegółowe dla tego, co jest stosunkowo prostym zadaniem, ale to dla ciebie Prolog…).Program powinien być dość zrozumiały, biorąc pod uwagę, że jest to mniej więcej bezpośrednie tłumaczenie specyfikacji na gramatykę, a następnie na składnię Prologu; definicja
v
mówi, żeN
jest to 1 w pustym łańcuchu lubN
jestA
×B
(zA
mniej niżB
mniej niżN
), a łańcuch jest konkatenacjąv(A)
iv(B)
, lubN
jestM
+ 1, a łańcuch jest:
konkatenowany zv(M)
konkatenacją z*
. Druga linia jest nieco subtelniejsza;length(S,_)
oznacza „S ma pewną długość”, ale określenie tego jako pierwszej rzeczy w wierszu działa jako wskazówka dla implementacji Prologa, że powinien najpierw sprawdzić najmniejsze długości (co oznacza, że otrzymamy możliwie najkrótszą długość dla wartości zwracanej) .źródło