Wyzwanie
W tym wyzwaniu określasz język źródłowy S
i docelowy T
. Twoim zadaniem jest napisanie następującego programu P
w języku S
. Jeśli jako program wejściowy podano poprawny program Q
w języku , wyświetli on prawidłowy program w języku, który nie przyjmuje danych wejściowych i wyjściowych , to znaczy program zastosowany do kodu źródłowego . Ponadto powinieneś przedstawić w swojej odpowiedzi nietrywialny przykładowy program (im bardziej interesujący, tym lepszy, choć nie zdobywasz za to punktów), wynikowy program i wynik działania . To jest kod-golf, więc najkrótszy kod wygranych.T
P
R
T
Q(R)
Q
R
Q
R
R
P
Innymi słowy, jest to wyzwanie związane z napisaniem „uniwersalnego konstruktora quine”, który może tworzyć dowolne typy uogólnionych quines.
Wyjaśnienia
- Twoje języki źródłowe i docelowe mogą być identyczne.
- Program
P
powinien pobrać jeden ciąg jako dane wejściowe (z STDIN lub równoważnego) i wyprowadzić jeden ciąg (do STDOUT lub równoważnego), tak jak każdy program wyjściowyR
. - Programy wejściowe
Q
powinny także przekształcać ciąg znaków na inny, ale ich forma jest bardziej elastyczna: mogą to być funkcje ciąg-ciąg, fragmenty kodu modyfikujące zmienną o określonej nazwie, fragmenty modyfikujące stos danych, jeśli język docelowy ma jeden itp. Możesz także dodatkowo ograniczyć formę tychQ
plików, stwierdzając, że na przykład nie mogą one zawierać żadnych komentarzy. Jednak musisz być w stanie zaimplementować dowolną obliczalną funkcję typu string-to-string jako program wejściowyQ
i musisz wyraźnie określić, jak one działają i jakie dodatkowe ograniczenia na nich nakładasz. - Program wyjściowy
R
powinien być naprawdę (uogólnionym) quine, więc nie może czytać żadnych danych wejściowych (danych wejściowych użytkownika, plików itp.), ChybaQ
że tak się stanie. - Standardowe luki są niedozwolone.
Przykład
Załóżmy, że wybrałem Python jako język źródłowy i Haskell jako język docelowy, a ponadto wymagam, aby program wejściowy był definicją String -> String
funkcji o jednym wierszu f
. Jeśli dam program do odwracania łańcucha
f x = reverse x
jako dane wejściowe do mojego programu Python P
, wypisze kod źródłowy innego programu Haskell R
. Ten program wypisuje do STDOUT kod źródłowy R
, ale jest odwrócony. Jeśli P
podano funkcję tożsamości
f x = x
jako wejście program wyjściowy R
jest quine.
źródło
Wyrażenia Haskell → Wyrażenia Haskell, 41 bajtów
Wypróbuj online!
Jak to działa
P $ "Q"
=((++)<*>show).('(':).(++")$(++)<*>show$") $ "Q"
konstruuje"R"
przez(++")$(++)<*>show$")
: dołączanie ciągu")$(++)<*>show$"
,('(':)
: poprzedzanie postaci'('
oraz(++)<*>show
(=\x->x++show x
): dołączając cytowaną wersję tego,powodując
"R"
="(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""
.R
=(Q)$(++)<*>show$"(Q)$(++)<*>show$"
działa według"(Q)$(++)<*>show$"
,(++)<*>show
: dołączając cytowaną wersję tego,Q
do tego,powodując
Q "(Q)$(++)<*>show$\"(Q)$(++)<*>show$\""
=Q "R"
.(Parens wokół
Q
są konieczne, ponieważQ
mogą zawierać$
tak samo łatwo, jak toR
robi, i$
niestety są odpowiednio skojarzone).Próbny
źródło
$
wymaga nawiasów, ale również spływulet
,do
lub wyrażeń lambda.let
/if
/case
/,do
jeśli sam ich nie wyemituję. Być może równie dobrze, że nie musiałem.Źródło = Cel = JavaScript, 66
Założenia dla Q:
Q
powinna być anonimową funkcją JavaScript typu string-to-string.Przykłady:
function(s) { return s.split('').reverse().join(''); }
W tym przypadku
P(Q)
(lubR
) będzie:,function a(){console.log(function(s) { return s.split('').reverse().join(''); }(a+'a()'))}a()
a po jego wykonaniu otrzymamy:)(a}))')(a'+a(} ;)''(nioj.)(esrever.)''(tilps.s nruter { )s(noitcnuf(gol.elosnoc{)(a noitcnuf
co jest dokładnie takie samo jakQ(R)
.function(s) { return s; }
w tym przypadku
P(Q)
(lubR
) będzie:function a(){console.log(function(s) { return s; }(a+'a()'))}a()
który jest Quine JavaScript . Nie trzeba dodawać, żeQ(R)
będzie to samo, ponieważ Q jest funkcją tożsamości.Niektóre uwagi:
STDIN w JavaScript jest tradycyjnie
prompt()
, jednak pozwoliłem sobie powstrzymać się od tradycjialert()
jako STDOUT, aby ułatwić uruchamianie wyjścia jako progrem przy użyciu kopiuj-wklej. (Zdaję sobie sprawę, że mogę zapisać do 12 znaków po zmianie naalert()
).Mogę także znacznie skrócić czas działania w ES6, ale na razie chcę pozostać przy Native JavaScript. Rozważam przesłanie w przyszłości odpowiedzi S = Scala, T = ECMA6, tylko dla doświadczenia.
Zdaję sobie również sprawę, że JavaScript prawie nigdy nie pokonuje CJam w golfa kodu , ale musiałem podjąć to wyzwanie! To było naprawdę zabawne.
źródło
Galaretka → 7 , 9 bajtów
Wypróbuj online!
Q jest funkcją 7 (tj. Która nie wykracza poza górny element stosu i wykonuje operacje wejścia / wyjścia przez stos) i jest podana jako argument wiersza poleceń.
Wyjaśnienie
Program 7
Uniwersalny konstruktor quine w 7, którego tu używam, to:
Pierwszą rzeczą, na którą należy zwrócić uwagę jest to, że wiodące 7 jest odpowiednikiem wiodących białych znaków i nie ma żadnego wpływu na program. Jedynym powodem, dla którego istnieje, jest przestrzeganie reguł PPCG przeciwko literalnym literom (jest zakodowane przez sekundę
1
w programie, a nie przez siebie).Reszta programu jest pojedynczym elementem stosu (ma zbilansowane
7
si6
s), który wykonuje następujące czynności po uruchomieniu:Innymi słowy, ten element stosu jest programem, który drukuje górę stosu, z przygotowanym
7
wyprzedzeniem, w formacie wyjściowym 7 (co oznacza „drukuj dosłownie, używając tego samego kodowania co kod źródłowy”, a zatem jest zdecydowanie najlepszym kodowaniem dla Quines). Jest to na szczęście szczęście, że możemy ponownie użyć literału7
do dwóch celów (format wyjściowy i wiodące białe znaki). Oczywiście, wstawiając coś tuż przed końcem3
, możemy wyprowadzić funkcję7
+ danych wejściowych, a nie tylko danych wyjściowych7
i wejście bezpośrednio.W jaki sposób ten element stosu otrzymuje własny kod źródłowy? Po osiągnięciu końca programu
eval
domyślnie górny element stosu wynosi 7 sekund. Jednak w rzeczywistości nie wyskakuje ze stosu, więc dosłownie element stosu, który byłeval
prowadzony, wciąż tam jest. (Innymi słowy, program nie odczytuje własnego źródła - o czym świadczy fakt, że nie jest w stanie zobaczyć7
na początku programu, który jest separatorem elementów stosu, a nie częścią literału - ale raczej składa się głównie z literału, któryeval
domyślnie jest prowadzony).Program galaretki
Jest to być może jeden z najmniej podobnych do Jelly programów Jelly, które napisałem; składa się ona z trzech nilads (
“ṚƓ^ṾṂ’
,³
,3
), które są po prostu wyjście w kolejności, ponieważ żadne operacje są wykonywane na nich. Jest3
to dość oczywiste, po prostu bycie stałą całkowitą. Jest³
to również proste, jeśli znasz Jelly: to wyraźna notacja Jelly dla pierwszego argumentu wiersza poleceń (w którym Jelly zwykle bierze swój wkład). Reszta programu Jelly reprezentuje większość mojego 7 uniwersalnego konstruktora quine: wykorzystując fakt, że wszystkie polecenia w 7 można przedstawić za pomocą cyfr ASCII, możemy zinterpretować717162234430
nie jako seria poleceń, a nawet jako liczba ósemkowa (tak jak jest koncepcyjnie), ale jako liczba dziesiętna, co oznacza, że nie potrzebujemy żadnego specjalnego formatowania danych wyjściowych. Ta liczba dziesiętna staje się“ṚƓ^ṾṂ’
w skompresowanym zapisie liczb całkowitych Jelly.Przykład
Jeśli podamy
24053
jako program Q, otrzymamy następujące dane wyjściowe:Wypróbuj online!
2405
łączy element najwyższego stosu z samym sobą:(Ostatni krok może wydawać się trochę mylący; dzieje się tak, że ucieczka elementu stosu konwertuje każde polecenie w nim z „uruchom to polecenie” na „dołącz to polecenie na górze stosu”, więc każde polecenie dołącza się do oryginału element najwyższego stosu podczas działania).
W związku z tym uruchomienie wynikowego programu R daje nam dwie kopie R:
źródło
CJam → CJam, 13 bajtów
Wypróbuj online!
Dane wejściowe
Q
powinny być fragmentem kodu, który modyfikuje jedyny ciąg w stosie.Q
jest czytane ze standardowego wejścia.Przykład
Wejście:
Dodaje spację między dwoma znakami i odwraca ciąg.
Wynik:
Dane wyjściowe uogólnionego quine:
Wyjaśnienie
Najpierw ocenia quine, dzięki czemu możemy uzyskać jego ciąg znaków bez zbędnych podwójnych cudzysłowów. Następnie zamień ładunek na dane wejściowe.
Może to być miejsce, w
{`"_~"+ }_~7qt
którym przestrzeń jest symbolem zastępczym ładunku. Ale zmiana ładunku w celu7
zaoszczędzenia bajtu.źródło
Węgiel drzewny → Perl (5),
2933 bajtówWypróbuj online!
Program Perla Q powinien zwrócić fragment kodu, który pobiera dane wejściowe jako ciąg znaków po swojej prawej stronie i udostępnia dane wyjściowe w zmiennej
$_
. (Arbitralne funkcje Perla można przekonwertować na tę formę, pakując je jakosub x {…}; $_=x
. W większości przypadków jednak składnia Perla oznacza, że nie jest wymagane zawijanie).Wyjaśnienie
The Perl
Oto jak wygląda uniwersalny konstruktor quinu dla Perla:
(W większości przypadków chciałbyś zagrać w golfa do tego stopnia
$_=q(say…"\$_=q($_);eval");eval
, ale nie jestem pewien, czy możesz tam wstawić dowolny kod Perla…
.)Innymi słowy, mamy zewnętrzne opakowanie,
$_=q(…);eval
które przypisuje ciąg,$_
a następnie go ocenia. Wewnątrz opakowania znajduje"\$_=q($_);eval"
się rekonstrukcja opakowania wraz z jego zawartością za pomocą wartości, którą zapamiętaliśmy$_
, oraz kodu Q określonego przez użytkownika orazprint
do wydrukowania wyniku. (Niestety nie możemy tego użyćsay
; dodaje nową linię i ma to znaczenie w quinesach).Węgiel drzewny
„Istotą” tej odpowiedzi było stworzenie uogólnionych quinesów w Perlu, więc kiedy już miałem do tego strategię gry w golfa (której użyłem w wielu innych odpowiedziach), nadszedł czas, aby napisać program P, który w zasadzie po prostu zastępuje ciąg do szablonu. Chciałem tutaj języka, który był dobry w drukowaniu ciągów ciągłych (najlepiej trochę je kompresując) i interpolowaniu danych wejściowych użytkownika.
Po wypróbowaniu kilku, zdecydowałem się na węgiel drzewny, którego nigdy wcześniej nie używałem (i który naprawdę mógłby zrobić z pewną dokumentacją); jest zaprojektowany dla sztuki ASCII, ale może również pisać ciągi w jednym wymiarze. Znaki ASCII są drukowane dosłownie na węglu drzewnym, co oznacza, że drukowanie ciągów ciągów nie wymaga płyty kotłowej i możemy użyć
S
polecenia do interpolacji ciągu pobranego z danych wprowadzonych przez użytkownika do programu.Można jednak (nieco) skrócić. Uniwersalny konstruktor quine Perla zawiera dwie dość długie powtarzające się sekcje. Możemy zatem użyć
A
polecenia, aby przypisać je do zmiennych (np.A…α
Przypisuje do zmiennejα
) i po prostu interpolować zmienne w ciągu, który drukujemy, używając ich nazw. To oszczędza kilka bajtów po prostu dosłownie napisując ciąg.Niestety, węgiel drzewny dodaje także nowy wiersz do programu, ale to nie jest wielka sprawa;
\n
dodanie tego nowego wiersza do wejścia Q również kosztuje dwa bajty .Przykład
Jeśli podamy dane wejściowe
$_=reverse
(które odwracają ciąg), otrzymamy następujące dane wyjściowe:Wypróbuj online!
który jest podobny do quine, który drukuje swoje źródło wstecz, zgodnie z oczekiwaniami.
źródło
Galaretka → Niedociążenie , 15 bajtów
Wypróbuj online!
Pobiera wejściową funkcję niedociążenia Q jako argument podobny do polecenia. Q musi pobierać dane wejściowe ze stosu i przekazywać dane wyjściowe na stos, bez próby sprawdzania głębszych elementów stosu (ponieważ nie będą one istnieć).
Wyjaśnienie
Niedociążenie
Zastosowany tutaj uniwersalny konstruktor quine Underload to:
Większość programu jest dosłowna. Śledzimy to przez
:^
, który go kopiuje, a następnie ocenia jedną kopię (pozostawiając drugą kopię na stosie).Kiedy literał zaczyna się oceniać, uruchamiamy
a
(escape, który przywraca go do tej samej postaci, co oryginalny program A) i(:^)*
(który dołącza:^
), rekonstruując w ten sposób kod źródłowy całego programu. Następnie możemy uruchomić funkcję Q, aby przekształcić to w dowolny sposób, i wydrukować wynik za pomocąS
.Galaretka
Tym razem nie mogę użyć węgla drzewnego, ponieważ sprawdzający poprawność interpretera niedociążenia ulega awarii na końcu programu, jeśli program kończy się na nowej linii. (Niektóre interpretery niedociążenia, takie jak ten na TIO, nie egzekwują tej reguły, ale chciałem być odpowiednio przenośny.) Niestety, węgiel drzewny w naturalny sposób dodaje końcowe znaki nowej linii. Zamiast tego użyłem galaretki, która jest tak samo zwięzła w takich prostych przypadkach; program składa się z literału listy z dwoma elementami (
““”
) i łączy je na input (j
), interpolując w ten sposób dane wejściowe użytkownika do programu.Przykład
Za pomocą danych wejściowych
:S^
(wydrukuj kopię, a następnie oceń oryginał) otrzymujemy następujący program niedociążenia:Wypróbuj online!
Drukuje się nieskończenie wiele razy, w dość interesujący sposób: po wykonaniu normalnego zachowania quine, następnie uruchamia się
eval
na kopii tego, co wyświetla. To powoduje, że cały zrekonstruowany program uruchamia się ponownie w nieskończoność (niedociążenie jest rekurencyjne). Quiting się i robienieeval
jest tak naprawdę jedynym sposobem na wykonanie nieskończonej pętli w Underload.źródło
RProgN 2 , 11 bajtów
Objaśnienie programu
Quine Explination
Wygenerowana Quine jest prosta, ale wykorzystuje funkcjonalność niedopasowanych programów obsługi funkcji w RProgN2 do stworzenia krótkiej i słodkiej quine, zwanej quine „Looping”. Jest to zaskakująco podobna koncepcja do quine <> <.
Oczywiście, ze względu na strukturę tego quine, po funkcji konkatenate można umieścić wszystko oprócz prawdziwych operacji no-ops (których nie można powiązać), i
Niektóre kołki
{`{.i}{
: Wyjścia{}i.{`{
.i
jest tylko funkcją „odwrotną”, więc ten program sam się odwraca.{`{.S§.}{
: Wyjścia..S`{{{}§
.S
konwertuje ciąg znaków na stos znaków,§
sortuje stos leksykograficznie, a następnie.
łączy go z powrotem, sam sortując .Wypróbuj online!
źródło