Wzajemne ujemne Quines

22

Zostało to zainspirowane przez Print Negative of Your Code i Golf a quine quine .


Rozważ prostokąt znaków, które spełniają następujące ograniczenia:

  1. Składa się wyłącznie z drukowalnych znaków ASCII
  2. Wymiary oba większe niż 1
  3. Każdy wiersz i każda kolumna zawiera co najmniej jedną spację.
  4. Każdy wiersz i każda kolumna zawiera co najmniej jeden znak spacji.

Na przykład poniżej jest prawidłowy prostokąt 6x4:

%n 2e 
1  g 3
 &* __
 3  

Ujemny tego prostokąta jest zdefiniowana jako prostokąt o równych wymiarach i zastąpiono wszystkie miejsca w postaci innych niż miejsca, a wszystkie nie-space zastąpione przestrzeni. Negatyw powyższego prostokąta może być:

  f  ^
 33 > 
9  $  
^ }|Q'

Do zamiany spacji można użyć dowolnego drukowalnego znaku ASCII spacji.

Zadanie

Twoim zadaniem jest napisanie programu z prostokątnym kodem źródłowym, który wyprowadza do siebie ważny negatyw. Wynik negatywny musi być również poprawnym programem w tym samym języku, co oryginał, i musi generować źródło oryginału.

Żadnych końcowych białych znaków nie można dodawać ani usuwać, z wyjątkiem jednej końcowej nowej linii na końcu obu danych wyjściowych, która jest opcjonalna.

Żaden program nie może odczytać kodu źródłowego żadnego z nich; nie można również zakładać środowisk REPL.

Punktacja

Twój wynik jest iloczynem wymiarów twojego kodu (tj. Jeśli twój kod źródłowy znajduje się w prostokącie 12 na 25, twój wynik to 12 * 15 = 180). Dodatkowo, za każdy znak użyty w komentarzu, twój wynik zwiększa się o 2 (jeśli użyjesz /* .. */raz w kodzie, a twój kod znajduje się w prostokącie 10 na 10, twój wynik wyniesie 10 * 10 + 8 * 2 = 116).

Najniższy wynik wygrywa.

W przypadku remisu wygrywa zgłoszenie z najmniejszą liczbą spacji w programie (oryginalne lub negatywne, w zależności od tego, która z nich ma mniej spacji).

Jeśli nadal pozostaje remis, wcześniejsza odpowiedź wygrywa.

Istnieje premia w wysokości -52% , jeśli połączenie oryginału i negatywu razem daje normalny quine. Na przykład:

Original   Negative   Combined
 A A       B B        BABA
A A         B B       ABAB
es1024
źródło
@Optimizer Dlatego nie wprowadziłem obowiązkowej premii.
es1024
1
Mówię tylko o negatywnej wzajemnej części quine;)
Optimizer
@ MartinBüttner Ah, mój zły. Myślałem dziwnie.
Optymalizator
1
Czy ktoś może to zrobić wc? +1 każdemu, kto pierwszy!
MegaTom,

Odpowiedzi:

15

CJam, ( 51 49 47 46 45 42 x 2) * 48% = 40,32

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

Uruchomienie powyższego kodu daje następujące dane wyjściowe:

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

uruchomiony, który drukuje oryginalne źródło.

Źródło i dane wyjściowe to po prostu zamienione linie.

Teraz nadchodzi magia.

Nakładanie się źródła i danych wyjściowych powoduje powstanie następującego kodu:

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

który jest idealnym quine!

Wypróbuj je online tutaj


Jak to działa

Cała logika drukowania znajduje się w samym pierwszym wierszu, który obsługuje wszystkie trzy przypadki wyjaśnione później.

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~
{                                     }_~   "Copy this code block and execute the copy";
 ]                                          "Wrap everything before it in array";
  )                                         "Pop the last element out of it";
   "_~"+                                    "Append string '_~' to the copied code block";
        S41*                                "Create a string of 41 spaces";
            'R+                             "Append character R to it";
               @,                           "Rotate the array to top and get its length";
                 [{   }{   }{     }]=~      "Get the corresponding element from this"
                                            "array and execute it";

Tablica w ostatnim wierszu powyżej to tablica, która zawiera bloki kodu odpowiadające wszystkim trzem przypadkom.

Przypadek 1

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

W tym przypadku długość pozostałego stosu wynosiła 0, ponieważ gdy blok był wykonywany, miał tylko kopię samego bloku, który początkowo wyskoczył w trzecim kroku powyżej. Więc wyjmujemy indeks 0z ostatniej tablicy i wykonujemy go:

 {N@S}          "Note that at this point, the stack is something like:"
                "[[<code block that was copied> '_ '~ ] <41 spaces and R string>]";
  N             "Add newline to stack";
   @            "Rotate the code block to top of stack";
    S           "Put a trailing space which negates the original R";

W tym przypadku druga linia nie ma opozycji, jeśli chodzi o drukowanie danych wyjściowych.

Przypadek 2

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

W tym przypadku stos zawierał już pusty ciąg, więc gdy wykonano skopiowany blok kodu, miał 2 elementy - pusty ciąg i sam blok kodu. Więc wyjmujemy indeks 1z ostatniej tablicy i wykonujemy go:

{SN@}            "Note at this point, the stack is same as in case 1";
 SN              "Push space and newline to stack";
   @             "Rotate last three elements to bring the 41 spaces and R string to top";

Przypadek 3

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

W tym przypadku stos ma 6 elementów. Zatem po usunięciu ostatniego bloku kodu pozostała długość tablicy wynosi 5. Wyjmujemy indeks 5z tablicy i wykonujemy go. (Zauważ, że w tablicy 3elementów indeksem 5jest indeks 5%3 = 2)

{W=N]_}          "Note at this point, the stack is same as in case 1";
 W=              "Take the last character out of the 41 spaces and R string, i.e. R";
   N]            "Add a new line to stack and wrap the stack in an array";
     _           "Copy the array to get back the source of Case 3 itself";
Optymalizator
źródło
27

Python, 97x2 + 2 = 196

Nie jest to świetne rozwiązanie na początek, ale przynajmniej działa (tak myślę).

c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%1) 
                                                                                                #

Wydajność:

                                                                                                #
c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%0) 
grc
źródło
8
+1 za jedyne jak dotąd zgłoszenie używania prawdziwego języka
WinnieNicklaus
Wydaje się też, że nie jest zbyt daleko od bonusu.
mbomb007
23

CJam, ( 58 56 54 48 46 x 2) * 48% = 44,16

{`"_~"+{_,94\m2/S*a_+\*                       
                       N/23f/Wf%N*}_`'"#)!*}_~

który drukuje

                       {`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~                       

Znaki spacji w każdym wierszu pozostają takie same między dwoma wzajemnymi quinesami.

Ale teraz naprawdę słodka część:

{`"_~"+{_,94\m2/S*a_+\*{`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~N/23f/Wf%N*}_`'"#)!*}_~

jest quine! :)

Sprawdź to tutaj.

Jak to działa

Radzę najpierw przeczytać wyjaśnienie mojego drugiego przesłania, ponieważ wyjaśnia ono podstawy quitingu w CJam w ogóle.

Ten jest nieco trudniejszy. W przypadku wzajemnego quine, podobnie jak w drugim przypadku, modyfikuję reprezentację ciągu bloku, dodając spacje przed lub po każdej linii i zamieniając 0 na 2, tak aby wynikowy program umieszczał spacje na przeciwległym końcu.

Zauważ, że spacje w ogóle nie wpływają na wzajemne quiny. W pierwszym są one w bloku, który tak naprawdę nie jest używany, aw drugim są wokół całego kodu.

Aby uzyskać regularny quine podczas łączenia obu, musimy znaleźć sposób, aby uniknąć wykonywania wszystkich tych modyfikacji. Zauważ, że struktura białych znaków i kodu oznacza, że ​​łącząc oba, wstawiamy całość jednego quine do drugiego. Jeśli więc umieścimy cały kod modyfikacji w bloku, możemy uruchomić ten blok w zależności od jego rzeczywistej zawartości.

Więc teraz mam ten blok ... dla wzajemnych quinesów, zawiera on tylko kod, który faktycznie chcę uruchomić. W przypadku połączonego quine zawiera on ponownie cały quine, w losowej pozycji, co nie ma żadnego sensu ... ale ponieważ jest to blok, nie jest uruchamiany automatycznie. Możemy więc ustalić, czy zmodyfikować ciąg w oparciu o zawartość tego bloku. Po to _`'"#)!jest. "Duplikuje blok, konwertuje go na ciąg znaków, wyszukuje znak (który we wspólnych znakach pojawia się tylko poza blokiem) - wyszukiwanie powraca, -1jeśli znak nie zostanie znaleziony, a dodatnia liczba całkowita w przeciwnym razie - zwiększa wynik i logicznie to neguje. Więc jeśli "znaleziono a, to daje 0to inaczej 1. Teraz po prostu to robimy*, który wykonuje blok raz, jeśli wynik to 1, a wcale nie.

Wreszcie, tak działa kod modyfikujący:

_,94\m2/S*a_+\*N/23f/Wf%N*
_,                         "Duplicate the quine string and get its length.";
  94\m                     "Subtract from 94.";
      2/                   "Divide by two.";
        S*                 "Create a string with that many spaces. This will be
                            an empty string for the first mutual quine, and contain
                            23 spaces for the second mutual quine.";
          a_+              "Create an array that contains this string twice.";
             \*            "Join the two copies together with the quine string.";
               N/          "Split into lines.";
                 23f/      "Split each line into halves (23 bytes each).";
                     Wf%   "Reverse the two halves of each line.";
                        N* "Join with a newline.";

Odbieranie nagrody (12 x 10) * 48% = 57,6

Okazuje się, że ten kod można bardzo łatwo podzielić na kilka wierszy z pewnymi modyfikacjami. Dodajemy 2 znaki, aby uzyskać 48 z rzędu, które następnie możemy wygodnie podzielić przez 8, dzięki czemu mamy 8 linii z 6 znakami kodu i 6 spacjami. Aby to zrobić, musimy również zmienić kilka liczb i zmienić operator lub dwa, aby nie były podzielone na obie linie. To daje nam działającą wersję o wymiarach 12 x 8 ... jednym z wymagań. Więc dodajemy dwie linie, które nic nie robią (popchnij 1, pop 1, popchnij 1, pop 1 ...), więc przejdź do 12 x 10 :

{`"_~"      
      +{129X
$,m2/S      
      *a_+\*
N/6f/1      
      ;1;1;1
;1;1;1      
      ;Wf%N*
}_`'"#      
      )!*}_~

Tak jak poprzedni, to produkuje

      {`"_~"
+{129X      
      $,m2/S
*a_+\*      
      N/6f/1
;1;1;1      
      ;1;1;1
;Wf%N*      
      }_`'"#
)!*}_~      

(Uwaga dodatkowa: nie ma potrzeby utrzymywania na przemian lewej i prawej linii pośredniej, ważna jest tylko pozycja pierwszej i ostatniej linii. Lewą i prawą stronę można wybrać dowolnie dla wszystkich innych linii).

I przez czysty zbieg okoliczności cały quine nadal działa:

{`"_~"{`"_~"
+{129X+{129X
$,m2/S$,m2/S
*a_+\**a_+\*
N/6f/1N/6f/1
;1;1;1;1;1;1
;1;1;1;1;1;1
;Wf%N*;Wf%N*
}_`'"#}_`'"#      
)!*}_~)!*}_~

(Mówię przypadek, ponieważ część, która zajmuje się niewykonywaniem wewnętrznego kodu, jest teraz dziwnie przeplatana z innym quine, ale nadal działa dobrze.)

Biorąc to pod uwagę, mogłem właśnie dodać 44 wiersze 1;do mojego oryginalnego zgłoszenia, aby spełnić wymóg nagrody, ale 12 x 10wygląda to znacznie ładniej. ;)

Edycja: Haha, kiedy powiedziałem „czysty zbieg okoliczności”, nie mogłem być bardziej na miejscu. Spojrzałem na to, jak teraz działa ostatnia quine, i jest to absolutnie śmieszne. Istnieją trzy zagnieżdżone bloki (właściwie 4, ale najbardziej wewnętrzna nie ma znaczenia). Jedyną ważną częścią najbardziej wewnętrznego z tych 3 bloków jest to, że zawiera "(a nie ten, który zrobił w oryginalnym zgłoszeniu, ale ten, '"który jest używany na końcu, aby sprawdzić ten sam znak). Podstawowa struktura quine to:

{`"_~"{`"_~"+{___'"___}_`'"#)!*}_~)!*}_~

Przeanalizujmy:

{`"_~"                               }_~ "The standard CJam quine.";
      {`"_~"+                  }_~       "Another CJam quine. Provided it doesn't do 
                                          anything in the rest of that block, this 
                                          will leave this inner block as a string on 
                                          the stack.";
                                  )      "Slice the last character off the string.";
                                   !     "Negate... this yields 0.";
                                    *    "Repeat the string zero times.";

To rzeczywiście robi zabawną magię, ale ponieważ blok wewnętrzny pozostawia pojedynczy stos na stosie, )!*zdarza się, że zamienia go w pusty ciąg. Jedynym warunkiem jest to, że elementy w wewnętrznym bloku później +nie robią nic więcej na stosie, więc spójrzmy na to:

             {___'"___}                  "Push a block which happens to contain 
                                          quotes.";
                       _`'"#)!*          "This is from the original code and just 
                                          removes the block if it does contain 
                                          quotes.";
Martin Ender
źródło
4
TLDR; upvote;)
Optymalizator
Czy nie powinno być Y/2w połączonym quine?
schnaader
„I przez czysty zbieg okoliczności”, nie;)
Timtech,
@Timtech Zobacz moją edycję. Czysty zbieg okoliczności nie był niedopowiedzeniem. ^^
Martin Ender,
10

CJam, 42 37 33 x 2 = 66

{`As_W%er"_~"+S 33*F'Lt1{\}*N\}_~
               L                 

który drukuje

               L                 
{`As_W%er"_~"+S 33*F'Lt0{\}*N\}_~

(Linie są zamieniane, a a 1zamienia się w a 0.)

Sprawdź to tutaj.

Jak to działa

Po pierwsze, powinieneś zrozumieć podstawową quine CJam:

{"_~"}_~

Nawiasy klamrowe po prostu definiują blok kodu, taki jak funkcja, która nie jest natychmiast wykonywana. Jeśli niewykorzystany blok pozostaje na stosie, drukowany jest jego kod źródłowy (w tym nawiasy klamrowe). _powiela blok i ~wykonuje drugą kopię. Sam blok po prostu popycha ciąg zawierający _~. Tak więc ten kod pozostawia stos w następującym stanie:

Stack: [{"_~"} "_~"]

Blok i ciąg znaków są po prostu drukowane jeden po drugim na końcu programu, co czyni to quine.

Piękno tego polega na tym, że możemy robić, co chcemy w bloku, i pozostaje to quine, ponieważ każdy fragment kodu zostanie automatycznie wydrukowany w zawartości bloku. Możemy również zmodyfikować blok, uzyskując jego reprezentację ciągu `(który jest tylko ciągiem bloku z nawiasami klamrowymi).

Teraz spójrzmy na to rozwiązanie. Zauważ, że każda część wzajemnej quine zawiera blok podobny do quine z _~i an L. LPopycha pusty ciąg na stosie, który nie przyczynia się do wyjścia. Oto, co robi blok:

`                             "Convert block to its string representation.";
 As                           "Push 10 and convert to string.";
   _W%                        "Duplicate and reverse, to get another string 01.";
      er                      "Swap 0s and 1s in the block string.";
        "_~"+                 "Append _~.";
             S 33*            "Push a string with 33 spaces.";
                  F'Lt        "Set the character at index 15 to L.";
                      1{ }*   "Repeat this block once.";
                        \     "Swap the code string and the space string.";
                           N\ "Push a newline and move it between the two lines.";

To zrobi część quine, ale zamieni 1 na 0, a także wstawi kolejną linię z L, gdzie w powyższym kodzie jest spacja. Połów polega na tym, że kolejność tych dwóch linii jest określona przez zamianę wewnątrz { }*. A ponieważ zewnętrzna część wzajemnego quine ma 0przednią część zastąpioną przez 1, nigdy nie wykonuje tej zamiany, a tym samym ponownie generuje pierwotny porządek.

Martin Ender
źródło
5

CJam, 27 × 2 = 54

{ ` " _ ~ " + N - ) 2 * ' '
 > @ t s G B + / N * } _ ~ 

Wydajność:

 { ` " _ ~ " + N - ) 2 * ' 
' > @ t s G B + / N * } _ ~

'A'B>porównuje znaki A i B. ' '\n >zwraca 1, ponieważ 32> 10 i ' \n' >zwraca 0, ponieważ dwie spacje są równe.

jimmy23013
źródło
2

CJam, 30 29 x 2 = 58

{"_~"SN]_,4=S28*'R+\{N@}*}_~ 
                            R

Wyjścia:

                            R
{"_~"SN]_,4=S28*'R+\{N@}*}_~ 

który wyprowadza oryginalne źródło.

Jest to oparte na tej samej zasadzie, co moje inne rozwiązanie.

Wypróbuj online tutaj

Optymalizator
źródło