Quines négatives mutuelles

22

Cela a été inspiré par Print a Negative of your Code et Golf a quine mutual .


Considérez un rectangle de caractères répondant aux restrictions suivantes:

  1. Se compose uniquement de caractères ASCII imprimables
  2. Dimensions supérieures à 1
  3. Chaque ligne et chaque colonne contient au moins un espace.
  4. Chaque ligne et chaque colonne contient au moins un caractère non espace.

Par exemple, ce qui suit est un rectangle 6x4 valide:

%n 2e 
1  g 3
 &* __
 3  

Un négatif pour ce rectangle est défini comme un rectangle de dimensions égales, avec tous les espaces remplacés par des caractères non-espace et tous les caractères non-espace remplacés par des espaces. Un négatif du rectangle ci-dessus pourrait être:

  f  ^
 33 > 
9  $  
^ }|Q'

Tout caractère ASCII imprimable non-espace peut être utilisé pour remplacer un espace.

Tâche

Votre tâche consiste à écrire un programme avec un code source rectangulaire, qui génère un négatif valide pour lui-même. Le négatif émis doit également être un programme valide, dans la même langue que l'original, et il doit sortir la source de l'original.

Aucun espace de fin ne peut être ajouté ou supprimé, à l'exception d'une seule nouvelle ligne de fin à la fin de chaque sortie, qui est facultative.

Aucun programme n'est autorisé à lire le code source de l'un ou l'autre; les environnements REPL ne peuvent pas non plus être supposés.

Notation

Votre score est le produit des dimensions de votre code (c'est-à-dire si votre code source est dans un rectangle de 12 x 25, votre score est de 12 * 15 = 180). De plus, pour chaque caractère utilisé dans un commentaire, votre score augmente de 2 (si vous utilisez /* .. */une fois dans votre code et que votre code est dans un rectangle de 10 x 10, votre score serait de 10 * 10 + 8 * 2 = 116).

Le score le plus bas l'emporte.

S'il y a égalité, la soumission avec le moins d'espaces dans le programme (l'original ou le négatif, selon le moins d'espaces) gagne.

S'il y a encore égalité, la réponse précédente l'emportera.

Il y a un bonus de -52% si la combinaison de l'original et du négatif produit une quine normale. Par exemple:

Original   Negative   Combined
 A A       B B        BABA
A A         B B       ABAB
es1024
la source
@Optimizer C'est la raison pour laquelle je n'ai pas rendu le bonus obligatoire.
es1024
1
Je ne parle que de la partie quine mutuelle négative;)
Optimizer
@ MartinBüttner Ah, ma mauvaise. Je pensais en termes étranges.
Optimizer
1
Quelqu'un peut-il faire cela en c? +1 à celui qui sera le premier!
MegaTom

Réponses:

15

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

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

L'exécution du code ci-dessus donne cette sortie:

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

en cours d'exécution, imprime la source d'origine.

La source et la sortie sont simplement des lignes permutées.

Maintenant vient la magie.

Superposition de la source et des résultats de sortie dans le code suivant:

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

ce qui est une quine parfaite!

Essayez-les en ligne ici


Comment ça marche

Toute la logique d'impression est dans la première ligne elle-même qui gère les trois cas expliqués plus loin.

{])"_~"+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";

Le tableau dans la dernière ligne ci-dessus est le tableau qui a des blocs de code correspondant aux trois cas.

Cas 1

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

Dans ce cas, la longueur de la pile restante était de 0 car lorsque le bloc a été exécuté, il ne disposait que de la copie du bloc lui-même, qui a été initialement extraite à la troisième étape ci-dessus. Nous retirons donc l'index 0du dernier tableau et l'exécutons:

 {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";

Dans ce cas, la deuxième ligne est un no-op en ce qui concerne l'impression de la sortie.

Cas 2

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

Dans ce cas, la pile contenait déjà une chaîne vide, donc lorsque le bloc de code copié a été exécuté, elle avait 2 éléments - une chaîne vide et le bloc de code lui-même. Nous retirons donc l'index 1du dernier tableau et l'exécutons:

{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";

Cas 3

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

Dans ce cas, la pile comporte 6 éléments. Ainsi, après avoir sauté le dernier bloc de code, la longueur restante du tableau est 5. Nous prenons l'index 5du tableau et l'exécutons. (Notez que dans un tableau d' 3éléments, index 5est index 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";
Optimiseur
la source
27

Python, 97x2 + 2 = 196

Pas une bonne solution pour commencer, mais au moins ça marche (je pense).

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

Sortie:

                                                                                                #
c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%0) 
grc
la source
8
+1 pour la seule soumission jusqu'à présent à utiliser une vraie langue
WinnieNicklaus
Il ne semble pas non plus trop éloigné du bonus.
mbomb007
23

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

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

qui imprime

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

Les caractères non-espace dans chaque ligne restent les mêmes entre les deux quines mutuelles.

Mais maintenant, la partie vraiment douce:

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

est une quine! :)

Testez-le ici.

Comment ça marche

Je vous recommande de lire d'abord l'explication de mon autre soumission, car elle explique les bases du quining dans CJam en général.

Celui-ci est un peu plus délicat. Pour le quine mutuel, comme dans l'autre cas, je modifie la représentation sous forme de chaîne du bloc en ajoutant des espaces avant ou après chaque ligne, et en échangeant un 0 avec un 2, de sorte que le programme résultant place les espaces à l'extrémité opposée.

Notez que les espaces n'affectent pas du tout les quines mutuelles. Dans le premier, ils sont dans un bloc, qui n'est pas vraiment utilisé, et dans le second, ils sont autour du code entier.

Pour obtenir une quine régulière lors de la combinaison des deux, nous devons trouver un moyen d'éviter de faire toute cette modification. Notez que la structure des espaces et du code signifie qu'en combinant les deux, nous insérons l'intégralité d'une quine dans l'autre. Donc, si nous mettons le code de modification entier dans un bloc, nous pouvons exécuter ce bloc en fonction de son contenu réel.

Alors maintenant, j'ai ce bloc ... pour les quines mutuelles, il ne contient que le code que je veux réellement exécuter. Pour le quine combiné, il contient également à nouveau le quine entier, dans une position aléatoire, ce qui n'a aucun sens ... mais comme c'est un bloc, il n'est pas exécuté automatiquement. Nous pouvons donc déterminer s'il faut modifier la chaîne en fonction du contenu de ce bloc. C'est pour ça _`'"#)!. Il duplique le bloc, le convertit en chaîne, recherche le caractère "(qui, dans les quines mutuelles, n'apparaît qu'en dehors du bloc) - la recherche retourne -1si le caractère n'est pas trouvé et un entier positif sinon -, incrémente le résultat et le nie logiquement. Donc, si un a "été trouvé, cela donne 0sinon il donne 1. Maintenant on fait juste*, qui exécute le bloc une fois, si le résultat était 1 et pas du tout autrement.

Enfin, voici comment fonctionne le code de modification:

_,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.";

Réclamant la prime, (12 x 10) * 48% = 57,6

Il s'avère que ce code peut être divisé sur plusieurs lignes très facilement avec quelques modifications. Nous ajoutons 2 caractères, pour obtenir 48 de suite, que nous pouvons ensuite facilement diviser par 8, de sorte que nous avons 8 lignes avec 6 caractères de code et 6 espaces. Pour ce faire, nous devons également modifier quelques chiffres et réorganiser un ou deux opérateurs afin qu'ils ne soient pas répartis sur les deux lignes. Cela nous donne une version de travail avec une taille 12 x 8 ... une sur l'exigence. Nous ajoutons donc simplement deux lignes qui ne font rien (poussez un 1, poussez un 1, poussez un 1, piquez un 1 ...), alors obtenez 12 x 10 :

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

Comme le précédent, cela produit

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

(Remarque: il n'est pas nécessaire de continuer à alterner gauche et droite sur les lignes intermédiaires, seule la position de la première et de la dernière ligne est importante. Gauche et droite peuvent être choisies arbitrairement pour toutes les autres lignes.)

Et par pure coïncidence, le quine complet fonctionne toujours:

{`"_~"{`"_~"
+{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*
}_`'"#}_`'"#      
)!*}_~)!*}_~

(Je dis une coïncidence, parce que la partie qui se charge de ne pas exécuter le code interne est maintenant étrangement entrecoupée de l'autre quine, mais cela se passe toujours bien.)

Cela étant dit, j'aurais pu ajouter 44 lignes 1;à ma soumission d'origine pour répondre à l'exigence de prime, mais 12 x 10ça a l'air beaucoup plus net. ;)

Edit: Haha, quand j'ai dit "pure coïncidence", je n'aurais pas pu être plus précis. J'ai regardé comment fonctionne actuellement le quine final, et c'est absolument ridicule. Il y a trois blocs imbriqués (4 en fait, mais le plus interne n'est pas pertinent). La seule partie importante de l'intérieur de ces 3 blocs est qu'il contient un "(et pas celui qu'il a fait dans la soumission d'origine, mais le même '"qui est utilisé à la fin pour vérifier ce même caractère). La structure de base du quine est donc:

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

Disséquons cela:

{`"_~"                               }_~ "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.";

Donc, cela fait en effet de la magie drôle, mais parce que le bloc intérieur laisse une seule chaîne sur la pile, )!*il se trouve que cela se transforme en une chaîne vide. La seule condition est que le contenu du bloc intérieur +ne fasse rien d'autre à la pile, alors regardons cela:

             {___'"___}                  "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
la source
4
TLDR; upvote;)
Optimizer
Cela ne devrait-il pas être Y/2dans le quine combiné?
schnaader
"Et par pure coïncidence" nah;)
Timtech
@Timtech Voir ma modification. La pure coïncidence n'était pas un euphémisme. ^^
Martin Ender
10

CJam, 42 37 33 x 2 = 66

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

qui imprime

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

(Les lignes sont inversées et un 1se transforme en a 0.)

Testez-le ici.

Comment ça marche

Tout d'abord, vous devez comprendre le quine de base CJam:

{"_~"}_~

Les accolades définissent simplement un bloc de code, comme une fonction, qui n'est pas immédiatement exécuté. Si un bloc non exécuté reste sur la pile, son code source (y compris les accolades) est imprimé. _duplique le bloc et ~exécute la deuxième copie. Le bloc lui-même pousse simplement la chaîne contenant _~. Donc, ce code laisse la pile dans l'état suivant:

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

Le bloc et la chaîne sont simplement imprimés dos à dos à la fin du programme, ce qui en fait une quine.

La beauté de ceci est que nous pouvons faire tout ce que nous voulons dans le bloc, et cela reste une quine, car chaque morceau de code sera automatiquement imprimé dans le contenu du bloc. Nous pouvons également modifier le bloc, en obtenant sa représentation de chaîne avec `(qui est juste une chaîne du bloc avec des accolades).

Voyons maintenant cette solution. Notez que l'une ou l'autre partie du quine mutuel contient du bloc de type quine avec _~, et an L. Le Lpousse une chaîne vide sur la pile, ce qui ne contribue pas à la sortie. Voici donc ce que fait le bloc:

`                             "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.";

Donc, cela fera la partie quine, mais échangez un 1 pour un 0, et cela ajoutera également une autre ligne à un L, où le code ci-dessus a un espace. Le hic, c'est que l'ordre de ces deux lignes est déterminé par l'échange à l'intérieur { }*. Et parce que la partie extérieure du quine mutuel a le 0devant remplacé par un 1, il n'exécute jamais cet échange, et produit donc à nouveau l'ordre d'origine.

Martin Ender
la source
5

CJam, 27 × 2 = 54

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

Sortie:

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

'A'B>compare les caractères A et B. ' '\n >renvoie 1 car 32> 10 et ' \n' >renvoie 0 car les deux espaces sont égaux.

jimmy23013
la source
2

CJam, 30 29 x 2 = 58

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

Les sorties:

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

qui sort la source d'origine.

Ceci est basé sur le même principe que mon autre solution.

Essayez-le en ligne ici

Optimiseur
la source