2 koty w Quine


30

Wyzwanie

Utwórz dwa programy, A i B, które są programami dla kotów w tym samym języku. Po połączeniu, AB (również w tym samym języku) powinno być quine.

Załóżmy na przykład, helloi worldto zarówno programy Cat in języka XYZ. Jeśli helloworldjest to quine w tym języku, to twoje rozwiązanie jest ważne.

Dla tych, którzy nie znają kotów i quinesów, program cat to taki, który drukuje dokładnie to, co zostało mu przekazane przez stdin, a quine to program, który drukuje własny kod źródłowy.

Punktacja i zasady

  • Całkowita liczba bajtów skonkatowanego programu AB to Twój wynik. Ponieważ jest to kod golfowy, wygrywa najniższy wynik.
  • Standardowe luki są zabronione
  • Dane wejściowe muszą być pobierane ze standardowego wejścia, a wyjściowe muszą być przesyłane na standardowe wyjście.
  • Programy kotów nie muszą brać argumentów; muszą tylko skopiować stdin na stdout.
  • Quine powinno działać, gdy program nie otrzymuje danych wejściowych, ale nie musi działać poprawnie (ale może) dla innych danych wejściowych.
  • Quine nie musi się kończyć, pod warunkiem, że wydrukuje dokładnie swój kod źródłowy, nic więcej.
  • Quine musi mieć co najmniej jeden bajt.
  • A i B mogą być tym samym programem.
  • BA nie musi być quine ani nawet prawidłowym programem.

Nie sądzę, że powinieneś mieć A i B może być taka sama reguła programowa
Muhammad Salman

2
@MuhammadSalman Moim pierwotnym pomysłem było podwoić program dla kotów, aby stał się quine. Chciałem tylko otworzyć drzwi na łatwiejsze rozwiązania, ponieważ nie byłem całkowicie pewien, czy to możliwe. Wygląda na to, że się myliłem w obu kwestiach, ale nie mam nic przeciwko.
Beefster

3
Prawdopodobnie powinieneś dodać, że ABmusi być niepusty, ponieważ wiele języków ma kota 0-bajtowego, co pozwala na quinę 0-bajtową.
DJMcMayhem

9
@DJMcMayhem 0-bajtowa quine nie byłaby jednak poprawną quine.
Nissa

4
Co to jest program dla kotów?
Pedro A

Odpowiedzi:


32

V , 2 + 2 == 4 bajty

2i2i

Wypróbuj quine!

Wypróbuj kota!

A jest2i

B jest również2i

Jak to działa?

Po pierwsze, kilka wyjaśnień na temat działania V. Jedną z godnych uwagi rzeczy, które umożliwiają tę odpowiedź, jest to, że w V pusty program jest programem cat. To nie jest szczególny przypadek, jest nieodłączny od sposobu działania V. Podczas uruchamiania wszystkie dane wejściowe są ładowane do „bufora”, każde polecenie w jakiś sposób modyfikuje bufor, a następnie, gdy program jest wykonywany, bufor jest domyślnie drukowany. Oznacza to, że dowolny ciąg NOP jest również programem cat.

Te iśrodki sterowania trybu Insert , co oznacza, że każda postać w wyniku zastosowania izostaną dodane do bufora. Z liczbą poprzedzającą ten tekst zostanie zduplikowany n razy.

Oznacza to, że w przypadku programu cat nic nie zostanie dodane do bufora i zostanie wydrukowane podczas odczytu. Innymi słowy:

        " (Implicitly) Load all input
2       " 2 times,
 i      " Insert the following text into the buffer...
        " (nothing)
        " (Implicitly) Print the buffer

Ale w przypadku quine po tekście jest tekst i:

2       " 2 times,
 i      " Insert the following text into the buffer...
  2i    "   "2i"
        " (Implicitly) Print the buffer

Bezczelny brak odpowiedzi

V , 0 bajtów

Wypróbuj online!

A jest pustym programem.

B jest również pustym programem.

: P


21
Każdy inny język: Oy, znaleźliśmy się w ślepym zaułku! . V: * publikuje standardowy quine * .
Erik the Outgolfer

13

Rubinowy, 71 bajtów

2;puts (<<2*2+?2)[/.+2/m]||$<.read
2;puts (<<2*2+?2)[/.+2/m]||$<.read
2

Można podzielić na koty w następujący sposób:

2;puts (<<2*2+?2)[/.+2/m]||$<.read
2

i

;puts (<<2*2+?2)[/.+2/m]||$<.read
2

Dwa koty są identyczne, z wyjątkiem wiodącej 2, która nie ma możliwości we wszystkich trzech programach. The<<2Jest herestring, co oznacza, że wszystko, począwszy od następnej linii, aż do końcowej 2 z własnej linii jest ciągiem znaków, które możemy łączyć do siebie ( *2) i dołączyć do tyłu 2. W Koty herestring jest dobrze uformowane, ale pusty, więc wyrażenie regularne nie pasuje do niego i przejdziemy do $<.readwyrażenia i wyprowadzimy STDOUT. Kiedy jednak połączymy koty, łańcuch nie zakończy się aż do trzeciego wiersza, więc wyrażenie regularne pasuje, a my zwiemy i wyprowadzamy quine.


11

Pyth, 29 bajtów (5 + 24) 27 bajtów (5 + 22)

pz=T0?TzjN*2]"pz=T0?TzjN*2]     # Quine
pz=T0                           # Cat A
     ?TzjN*2]"pz=T0?TzjN*2]     # Cat B

To było zabawne.
Wypróbuj quine tutaj
Wypróbuj pierwszego kota tutaj
Wypróbuj drugiego kota tutaj

Objaśnienia

Cat A
pz=T0
pz       Print the input.
  =T0    (Irrelevant for cat)

Cat B
?TzjN*2]"pz=T0?TzjN*2]
?Tz                      If T (10) is truthy, output the input.
   jN*2]"pz=T0?TzjN*2]   (Irrelevant for cat)

Quine
pz=T0?TzjN*2]"pz=T0?TzjN*2]
pz                            Print the (empty) input (without a newline).
  =T0                         Set T to 0.
     ?Tz                      If T (0) is truthy, output the input.
             "pz=T0?TzjN*2]   Otherwise, get this string...
          *2]                 ... take two copies...
        jN                    ... and join them with a quote.

11

C # (kompilator Visual C #) , 551 bajtów

Odp .: 95 bajtów

class A{public static int i=2;static void Main(string[]args){System.Console.Write(args[0]);}}//

Wypróbuj online!

B: 438 + 18 bajtów

class A{public static int i=0;}
class B{static void Main(string[]args){if(A.i<1){System.Console.Write(args[0]);return;}var a=@"class A{{public static int i=2;static void Main(string[]args){{System.Console.Write(args[0]);}}}}//class A{{public static int i=0;}}
class B{{static void Main(string[]args){{if(A.i<1){{System.Console.Write(args[0]);return;}}var a=@{0}{1}{0};System.Console.Write(a,'{0}',a);}}}}";System.Console.Write(a,'"',a);}}

Wypróbuj online!

A + B: 533 + 18 bajtów

class A{public static int i=2;static void Main(string[]args){System.Console.Write(args[0]);}}//class A{public static int i=0;}
class B{static void Main(string[]args){if(A.i<1){System.Console.Write(args[0]);return;}var a=@"class A{{public static int i=2;static void Main(string[]args){{System.Console.Write(args[0]);}}}}//class A{{public static int i=0;}}
class B{{static void Main(string[]args){{if(A.i<1){{System.Console.Write(args[0]);return;}}var a=@{0}{1}{0};System.Console.Write(a,'{0}',a);}}}}";System.Console.Write(a,'"',a);}}

Wypróbuj online!

A i B przyjmują dane wejściowe jako argument wiersza poleceń. A + B ignoruje każde wejście. Dodano 18 bajtów B i A + B dla/p:StartupObject=B opcji wysyłanej do MSBuild. Jest to konieczne tylko w A + B, ale wydawało się, że oszustwo nie ma go również w B. W ten sposób flagi kompilatora dla A + B są flagami kompilatora dla A (brak) plus flagami kompilatora dla B.

Wyjaśnienie

Program A jest prosty. Klasa A zawiera (nieużywaną) zmienną statyczną izainicjowaną do 2i wypisuje swój pierwszy argument po uruchomieniu. //Na końcu jest ważna dla kodu A + B, ale nie robi nic w sobie.

Program B jest dziwny w izolacji, ale zasadniczo taki sam. Tworzy klasę A zawierającą iinicjowaną zmienną statyczną0 , a następnie uruchamia główną metodę klasy B, która robi to samo co program A, ponieważ A.ima mniej niż 1, i zwraca przed jakimkolwiek dziwnym zjawiskiem. Nowe wiersze nie są tutaj konieczne, ale są ważne dla A + B.

W połączeniu //z programu A komentuje deklarację klasy A z programu B, ale z powodu nowej linii klasa B jest w porządku, pozwalając zamiast tego A.iodwoływać się do 2wartości z programu A. Flaga kompilatora powoduje uruchomienie programu przez B.Main (), ponieważ A.Main () również istnieje. Rezultat jest taki, że program A + B nie wyświetla swojego argumentu, ale zamiast tego przechodzi do następnego segmentu B.Main (), który jest w zasadzie tylko standardowym quine C # .


1
„programy dla kotów… muszą skopiować stdin na stdout”
Jakob

9

Haskell , 116 + 20 = 187 175 174 136 bajtów

Kilka bajtów zapisanych, odkąd pokazał mi Ørjan Johansen interact

Cat 1

g=";main|idmain<-(++\"g=\"++show g++g)=interact idmain|1>0=interact id";main|idmain<-(++"g="++show g++g)=interact id

Wypróbuj online!

Cat 2

main|1>0=interact id

Wypróbuj online!

Quine

g=";main|idmain<-(++\"g=\"++show g++g)=interact idmain|1>0=interact id";main|idmain<-(++"g="++show g++g)=interact idmain|1>0=interact id

Wypróbuj online!


Podstawową zasadą w pracy jest to, że gdy dodamy drugiego kota pierwszy możemy zmienić nazwę funkcji mamy do interakcji z od ado idmain. Ponieważ interact idjest kotem, chcemy idmaindla mnie funkcji, która zwraca quine. Oczywistym rozwiązaniem byłoby jednak zastosowanie const, ponieważ możemy założyć, że dane wejściowe również są puste (++). Stąd znajdujemy kod źródłowy za pomocą dość standardowych środków, mamy zmienną, gktóra koduje źródło i używamy specjalnego opakowania do wydrukowania go w postaci ciągu i kodu. Istnieje niewielki wyjątek, że musimy umieścić nasz koder z przodu, ponieważ musimy już zakończyć interact id. To oznacza dodatekg=nie jest zakodowany i musi być obsługiwany ręcznie. Nasz następny kot jest dość standardem, z wyjątkiem tego, że musimy go ustawić jako poprawny kod, gdy zostanie przyczepiony do końca drugiego kota, więc potrzebujemy obu kotów jako instancji strażników wzorców.

Strategia alternatywna, 43 + 105 = 186 148

Cat 1

g="";main|idmain<-(++g++show g)=interact id

Wypróbuj online!

Cat 2

main|1>0=interact id where g="g=\"\";main|idmain<-(++g++show g)=interact idmain|1>0=interact id where g="

Wypróbuj online!

Quine

g="";main|idmain<-(++g++show g)=interact idmain|1>0=interact id where g="g=\"\";main|idmain<-(++g++show g)=interact idmain|1>0=interact id where g="

Wypróbuj online!


1
Można skrócić ten trochę zastępując getContents+ putStrz interact id. Wypróbuj online! (Quine nie działa już z niepustymi danymi wejściowymi, co pozwala na użycie (++ ...)sekcji dla idmain.)
Ørjan Johansen

@ ØrjanJohansen Thanks! Nie wiedziałem o tym interact, chyba dlatego, że rzadko robię rzeczy związane z IO z Haskellem. Zredagowałem post.
Wheat Wizard

8

Python 3, 286 bajtów

Mój pierwszy golf w Python i moja pierwsza quine! Niezbyt elegancki, ale działa.

Program A (238 bajtów)

from atexit import*;s="from atexit import*;s=%r;register(lambda:print(end='b'in globals()and s%%s or open(0).read()));b=0\nif's'not in vars():print(end=open(0).read())";register(lambda:print(end='b'in globals()and s%s or open(0).read()));

(brak końcowego nowego wiersza)

Program B (48 bajtów)

b=0
if's'not in vars():print(end=open(0).read())

(brak końcowego nowego wiersza)

Wypróbuj online

Podziękowanie

  • -24 bajty dzięki Jo King
  • -82 bajty dzięki Jo King

Możesz robić end=open...i używać %rzamiast %snie robić nowego wiersza i cytatów
Jo King

Fajnie, zmieniłem na %r. Nie jestem jednak pewien, co masz na myśli o nowej linii.
Jakob

1
Zamiast %sformatować nowy wiersz, możesz po prostu zrobić literał \n. Możesz także użyć ;do podzielenia instrukcji zamiast \n(z wyjątkiem tego, że ifmusi znajdować się w osobnej linii). %można przez to uciec w ciągu %%. Jedynym argumentem wymaganym do sformatowania łańcucha jest sam łańcuch, wszystko inne można rozłożyć
Jo King

1
Program B (i jego tekst) może użyć locals()do zapisania 2 bajtów.
Jonathan Allan

6

C ++ (clang) , 313 + 102 = 415 bajtów

Program A (kończy się na nowej linii):

#include<cstdio>
#define Q(x,y)#x,B=#y;x
int c;auto I="#include<cstdio>",A=Q(int main(){if(c)printf("%s\n#define Q(x,y)#x\",\"#y;x\nint c;auto I=\"%s\",A=Q(%s,)\n#ifdef Q\nint n=++c;\n#else\n%s\n%s\n#endif",I,I,A,I,B);else while((c=getchar())>=0)putchar(c);},int c;int main(){while((c=getchar())>=0)putchar(c);})

Program B (nie kończy się na nowej linii):

#ifdef Q
int n=++c;
#else
#include<cstdio>
int c;int main(){while((c=getchar())>=0)putchar(c);}
#endif

Nie strasznie podstępny i jak zwykle C ++ nie jest świetny do quitingu. Nie zdziwi mnie to, że istnieją sposoby na ogolenie bajtów tu i tam z tego samego pomysłu. Jedynym małym haczykiem jest zmiana zachowania czegoś po jego zdefiniowaniu, a inicjalizacja zmiennej dynamicznej z efektem ubocznym załatwia sprawę. (Czy można to zrobić nawet w C bez rozszerzeń kompilatora?)

Wypróbuj online: A , B , AB

(Jedyny problem dotyczący przenośności, o którym wiem, to to, że program zakłada <cstdio>umieszczanie nazw zarówno w globalnej przestrzeni nazw, jak i wewnątrz std).



5

Python 3 , 100 + 37 = 137 bajtów

Program A:

s='s=%r;print(end=open(0).read())#print(end=open(0).read())\nprint(s%%s)';print(end=open(0).read())#

Wypróbuj online!

Program B:

print(end=open(0).read())
print(s%s)

Wypróbuj online!

Make Quine AB

s='s=%r;print(end=open(0).read())#print(end=open(0).read())\nprint(s%%s)';print(end=open(0).read())#print(end=open(0).read())
print(s%s)

Wypróbuj online!

Działa tylko, gdy dane wejściowe są puste, w przeciwnym razie poprzedza dane wejściowe do danych wyjściowych.


Podwójne cudzysłowy powinny być pojedyncze.
Jonathan Allan

Awarie są dozwolone?
Jakob

@Jakob Pytanie nie powiedzieć, że zawiesza się nie wolno, a typowo wyjście na stderr jest ignorowany
Jo Kinga

Ok, w porządku. Sprytne skróty!
Jakob

4

Attache , 15 + 126 = 141 bajtów

ZA:

AllInput[]|Echo

Wypróbuj online!

B:

@{If[_,s.="AllInput[]|Echo@{If[_,s.=%s;;Printf[s,Repr!s],AllInput[]|Echo]es}|Call";;Printf[s,Repr!s],AllInput[]|Echo]es}|Call

Wypróbuj online!

A + B:

AllInput[]|Echo@{If[_,s.="AllInput[]|Echo@{If[_,s.=%s;;Printf[s,Repr!s],AllInput[]|Echo]es}|Call";;Printf[s,Repr!s],AllInput[]|Echo]es}|Call

Wypróbuj online!

Wyjaśnienie

Każdy z programów cat koduje AllInput[]|Echo, co jest prostym programem cat. B jest główną fazą quine; sam jest to funkcja wektoryzowana (przez unarską @) wywoływana bez danych wejściowych (nazywana as |Call). Zatem pierwsze warunkowe If[_,A,B]wykonuje się B, co jest po prostu AllInput[]|Echo.

Po wykonaniu A + B jednoargumentowy @staje się binarny z @powodu Echopołączenia z lambda:

AllInput[]|Echo@{If[_, ...

Oznacza to, że lambda jest wykonywana wcześniej Echo. Wracając do warunkowej, ta funkcja ma teraz cały STDIN jako argument. Tak, If[_,A,B]wykonuje A, co jest standardem ramy Quine.


3

Stax , 16 + 12 = 28 bajtów

Cat 1:

"yi|d|ca34b4lr"y

Uruchom i debuguj

"yi|d|ca34b4lr"y Full program, implicit input
"yi|d|ca34b4lr"  Push the string
               y Push raw input
                 Implicit output of top item

Cat 2:

i|d|ca34b4lr

Uruchom i debuguj

i|d|ca34b4lr Full program, implicit input
i            Don't parse input (prefix directive)
 |d          Push main stack depth, always zero
   |c        Cancel because top item is falsy, and implicitly print
     a34b4lr Never executed

Quine:

"yi|d|ca34b4lr"yi|d|ca34b4lr

Uruchom i debuguj

"yi|d|ca34b4lr"yi|d|ca34b4lr Full program
"yi|d|ca34b4lr"              Push the string
               y             Push input
                i            No-op
                 |d          Push main stack depth, i.e. 2
                   |c        Do nothing because top is truthy
                     a       Get the string to the top
                      34     Push 34 (charcode of ")
                        b    Copy both
                         4l  Listify top 4
                           r Reverse
                             Implicit output

3

Cat 1:

Lua , 41 bajtów

a=io.read;while a(0)do io.write(a(1))end;

Wypróbuj online!


Cat 2:

Lua , 70 bajtów

if a then io.input(arg[0])end;a=io.read;while a(0)do io.write(a(1))end

Wypróbuj online!


Quine:

Lua , 111 bajtów

a=io.read;while a(0)do io.write(a(1))end
if a then io.input(arg[0])end;a=io.read;while a(0)do io.write(a(1))end

Wypróbuj online!

io.input(arg[0]) w Cat 2 ustawia bieżący plik jako standardowe wejście, w wyniku czego kot drukuje kod źródłowy


1
Witamy w PPCG
Muhammad Salman

Możesz zapisać jeden bajt w kat. 1, usuwając ostatni średnik?
Muhammad Salman

1
Niestety czytanie bieżącego pliku to standardowa luka. Ale i tak miła próba.
Beefster


0

JavaScript (Node.js) , 199 bajtów


a=()=>console.log(require('fs').readFileSync(0)+'');a();var a=a||0;b=()=>console.log(require('fs').readFileSync(0)+'');!a?b():c=()=>console.log(`a=${a};a();var a=a||0;b=${b};!a?b():c=${c},c()`),c()

Wypróbuj online!

Kat. A, 57 bajtów


a=()=>console.log(require('fs').readFileSync(0)+'');a();

Wypróbuj online!

Kat. B, 142 bajty

var a=a||0;b=()=>console.log(require('fs').readFileSync(0)+'');!a?b():c=()=>console.log(`a=${a};a();var a=a||0;b=${b};!a?b():c=${c},c()`),c()

Wypróbuj online!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.