Quines sécurisés


17

Votre tâche est simple: écrire un programme (ou une fonction) qui ne prend aucune entrée et génère (ou retourne) son code source. Le hic, c'est que lorsque le programme est encapsulé "quotes"(caractère Unicode 34), il devrait à nouveau sortir son code source (maintenant cité).

Les règles standard pour les quines s'appliquent. Il s'agit de , donc le programme le plus court (en octets) gagne.


8
@ATaco pense de façon créative. Le code entre guillemets n'est normalement pas exécuté, mais lorsque le programme entier est entouré de guillemets, ces sections sont exécutées.
Pavel

1
Hmm, bon point.
ATaco

Cela pourrait fonctionner avec BF sur des implémentations qui prennent en charge !...
Esolanging Fruit

1
Devez-vous utiliser "? Certaines langues prennent en charge deux ou trois guillemets.
Neil

1
@tkellehe Meta: Qu'est-ce qui constitue une quine appropriée? Pour autant que je comprends votre quine 1 octet, il viole l'exigence de code / données formulée dans le poste le plus voté.
Laikoni

Réponses:


4

Noodel , 9 7 octets

Cette version fonctionne de la même manière que l'autre, juste que j'ai oublié que Noodel a un moyen d'exécuter un bloc de code une fois et j'ai fait le langage ...

Ḷ1ḥ-Ð1ḥ@€

ḷḥ-Ðḥ@ḅ

Essayez-le :)


Comment ça fonctionne

ḷḥ-Ðḥ@ḅ # Single statement that builds itself as a string.
ḷ       # Loop the following block of code unconditionally.
 ḥ-     # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
   Ð    # Push the stack as an array to stdout (since is an array it is done by reference).
    ḥ@  # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
      ḅ # Break out of the given loop. (The stack is now ["ḷ", "ḥ-Ðḥ@ḅ"]).

        # The top of the stack is popped off and displayed which modifies the array to produce {["ḷ"], "ḥ-Ðḥ@ḅ"} in stdout.

Devis-Sécurité

Placer le "caractère avant et après le programme fonctionne car Noodel dispose d'un ensemble de caractères dédiés à ce que j'appelle les imprimables . Ceux-ci sont immédiatement analysés en tant que littéraux de chaîne lorsqu'ils sont placés par eux-mêmes et permettent d'imprimer facilement quelque chose à l'écran. Ainsi, contrairement à la plupart des langues, Noodel considère l' ensemble ASCII normal qui est considéré comme digne d'être imprimé comme des littéraux de chaîne directs (sauf pour l'espace et le saut de ligne) qui y cite le code est simplement considéré comme poussant sur les chaînes.

"ḷḥ-Ðḥ@ḅ"

"         # Pushes on the string literal "\"" onto the stack.

 ḷḥ-Ðḥ@ḅ  # Same execution as before, simply builds the Quine for this loop.
 ḷ        # Loop the following block of code unconditionally.
  ḥ-      # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
    Ð     # Push the stack as an array to stdout (since is an array it is done by reference).
     ḥ@   # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
       ḅ  # Break out of the given loop. (The stack is now ["\"", "ḷ", "ḥ-Ðḥ@ḅ"]).

        " # Pushes on the string literal "\"" onto the stack.

          # The top of the stack is popped off and displayed which modifies the array to produce {["\"", "ḷ", "ḥ-Ðḥ@ḅ"], "\""} in stdout.

"Essayez-le :)"


Extraits

<div id="noodel" code='ḷḥ-Ðḥ@ḅ' input="" cols="10" rows="1"></div>
<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>


<div id="noodel" code='"ḷḥ-Ðḥ@ḅ"' input="" cols="10" rows="1"></div>
<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>


Je ne pense pas que l'utilisation esoit valide. La question ne demande pas le caractère codé en octet 34, mais le caractère Unicode 34. Quel que soit le codage que vous utilisez, il n'y en a qu'un:"
Dennis

@ Dennis, je suppose que ce que vous dites est que la référence au caractère Unicode 34 était juste pour s'assurer que tout le monde utilisait la même chose "? (Désolé, j'essaie juste de m'assurer que je comprends ce que vous dites) De plus, dois-je supprimer tout le texte de la réponse concernant l'utilisation e?
tkellehe

1
Oui, il existe des milliers d'encodages, mais un seul jeu de caractères Unicode. Depuis les "travaux, je supprimerais simplement la discussion et utiliserais simplement ".
Dennis

11

Python 2 3, 181 152 130 130 124 122 octets

""" """>" "or exec("oct=0");p='"""" """>" "or exec("oct=0");p=%r;a=oct==0;print(p[a:~a]%%p)#".';a=oct==0;print(p[a:~a]%p)#

Essayez-le en ligne! Le TIO est livré avec un en-tête et un pied de page qui testent automatiquement la validité du quine. Vous pouvez les effacer pour simplement exécuter la quine.

Ce code fonctionne en utilisant les chaînes entre guillemets triples en Python. """ """est égal à ' 'et """" """est égal à '" '.

Le code utilise exec , mais pas pour la façon "non quiney" d'exécuter des données en tant que code, juste pour définir une variable à l'intérieur d'une expression. Le execest également correctement encodé dans les données.

La première instruction compare la chaîne, éventuellement avec un guillemet ajouté, à " " , et définit la variableoct conséquence. (La variable aurait pu être une courte fonction intégrée.)

Le reste du code implémente ensuite le quine Python traditionnel en utilisant %r le formatage de chaîne, avec du code supplémentaire qui supprime les guillemets supplémentaires sioct est inchangé.

Une version alternative utilisant le "cheaty" exec arrive à 126 octets avec du code moins répété:

""" """>" "and exec("oct=0");s='"""" """>" "and exec("oct=0");s=%r;p=%r;exec(p)#".';p='a=oct!=0;print(s[a:~a]%(s,p))';exec(p)#

Essayez-le en ligne!


7

StandardML , 182 176 108 octets

";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))

Version non cotée : essayez-la sur codingground.
Version citée: Essayez-la sur codingground.

Notez que la sortie ressemble à ceci

> val it = "{some string}" : string
> val it = "{some string}" : string
{output to stdout}> val it = fn : string -> unit

car le code est interprété déclaration par déclaration (chacun ;termine une déclaration) et montre la valeur et le type de chaque déclaration.


Contexte

En SML, il y a un quine de la forme <code>"<code in quotes>":

str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))" 

et un sous la forme "<code in quotes>"<code>:

";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it)

Les deux s'appuient sur le fait que la <code>partie-ne contient pas de guillemets et peut donc être citée sans avoir besoin de s'échapper quoi que ce soit, les éléments "nécessaires pour sortir le quine sont donnés parstr(chr 34) .

Ils s'appuient également fortement sur l'identifiant implicite itqui est utilisé quand aucun identifiant explicite n'est donné dans une déclaration.

Dans le premier quine str(chr 34);se lie ità la chaîne contenant ", fn x=>démarre une fonction anonyme prenant un argument x, puis concatène x^it^x^itet imprime la chaîne résultante. Cette fonction anonyme est directement appliquée à une chaîne contenant le code du programme, donc la concaténation x^it^x^itdonne<code>"<code>" .

La deuxième quine commence avec juste le code du programme en tant que chaîne ";str(chr 34)^it;print(it^it)";qui est liée à it. str(chr 34)^it;Concatène ensuite une citation au début de la chaîne et comme encore aucun identificateur explicite n'est donné, la chaîne résultante "<code>est liée à it. Enfin print(it^it)concatène la chaîne avec elle-même, "<code>"<code>qui est ensuite imprimée.


Explication

Edit: n'est plus à jour avec la version 108 octets, mais on pourrait aussi le comprendre après avoir lu cette explication.

Le quine sans danger pour les devis combine les deux approches ci-dessus et est lui-même de la forme "<code>"<code>. Remettre cela entre guillemets donne ""<code>"<code>"donc une chaîne vide, puis une quine de l'autre forme.

Cela signifie que le programme reçoit soit sa propre source sous la forme "<code>de l'identifiant it, soit itjuste "et nous recevons notre propre source <code>comme argument et doit donc être une fonction qui gère un tel argument.

(if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it))

Pour identifier dans ce cas , nous sommes, nous vérifions si la taille itest supérieure à 1. Sinon, itest "et nous sommes dans le second cas, de sorte que les elserendements -Part une fonction anonyme fn x=>print(it^it^x^it^x^it)qui est alors appelé parce que son suivi par la source en tant que chaîne . Notez le it^it^début qui est nécessaire pour la chaîne vide au début du programme.

Si size itest plus grand que 1, nous sommes dans la thenpartie -et exécutons juste print(it^it), non? Pas tout à fait, car j'ai négligé de vous dire que SML est fortement typé, ce qui signifie qu'un conditionnel if <cond> then <exp_1> else <exp_2>doit toujours avoir le même type, ce qui signifie à nouveau que les expressions <exp_1>et <exp_2>doivent avoir le même type. Nous connaissons déjà le type de la elsepartie: Une fonction anonyme qui prend une chaîne et appelle ensuite printa type string -> <return type of print>, et printa type string -> unit( unitest en quelque sorte similaire à voiddans d'autres langues), donc le type résultant est à nouveau string -> unit.

Donc, si la thenpièce était juste de print(it^it)type unit, nous obtiendrions une erreur de non-correspondance de type. Et alors fn _=>print(it^it)? (_ est un caractère générique pour un argument qui n'est pas utilisé) Cette fonction anonyme en elle-même a un type 'a -> unit'areprésente un type arbitraire, donc dans le contexte de notre conditionnel qui applique un string -> unittype, cela fonctionnerait. (La variable type 'aest instanciée avec type string.) Cependant, dans ce cas, nous n'imprimerions rien car la fonction anonyme n'est jamais appelée! Rappelez-vous, lorsque nous allons dans la thenpartie -le code global est "<code>"<code>, donc le<code> partie -évalue une fonction mais, comme rien ne vient après, elle n'est pas appelée.

Au lieu de cela , nous utilisons un sequentialisation qui a la forme (<exp_1>; ...; <exp_n>)<exp_1>à <exp_n-1>peut avoir des types arbitraires et le type de <exp_n>fournit le type de l'ensemble sequentialisation. D'un point de vue fonctionnel, les valeurs de <exp_1>à<exp_n-1> sont simplement ignorées, mais SML prend également en charge les constructions impératives afin que les expressions puissent avoir des effets secondaires. En bref, nous prenons (print(it^it);print)la thenpartie -part, imprimant donc d'abord et retournant ensuite la fonction printqui a le bon type.


7

V , 27 , 23 octets

éPñi"éP241"qpá"lxx|xÿ

Essayez-le en ligne!

Comme il contient des caractères non imprimables, voici une version lisible:

éPñi"éP<C-v>241<esc>"qpá"lxx|xÿ

et voici un hexdump:

00000000: e950 f169 22e9 5016 3234 311b 2271 70e1  .P.i".P.241."qp.
00000010: 226c 7878 7c78 ff                        "lxx|x.

Donc, la toute première chose que nous devons faire est de déterminer si le premier caractère est une citation. éPinsère un caractère «P», mais "éPest un NOOP. Après cela, nous exécutons une légère modification sur le quine extensible standard, qui est:

ñi<C-v>241<esc>"qpÿ

Nous allons toutefois procéder légèrement différemment. Tout d'abord, nous devons insérer le texte de départ "éP". Nous faisons donc

ñ                        " Start recording into register 'q'
 i                       " Enter insert mode
  "éP<C-v>241<esc>       " Enter the following text: '"éPñ'
                  "qp    " Paste the text in register 'q'
                     á"  " Append a '"'

Voici où la ramification se produit. Le texte actuellement dans le tampon est

"éPñi"éP<C-v>241<esc>"qpá"P
Cursor is here ----------^

Sauf si nous l'avons mis entre guillemets, dans ce cas, le «P» n'aurait jamais été inséré, et le tampon est:

"éPñi"éP<C-v>241<esc>"qpá"
Cursor is here ----------^

Puisque nous enregistrons toujours, nous pouvons faire ce que nous voulons ici, et il sera ajouté au tampon lorsque cela se produira "qp. Donc, à partir d'ici, il est assez facile de supprimer conditionnellement les guillemets:

l           " Move one character to the right. If there is no character to the right, 
            " then this is effectively a "break" statement, stopping playback of the recording
 xx         " Delete two characters (the '"P')
   |        " Move to the first character on this line
    x       " Delete one character
     ÿ      " End the program

3

JavaScript (ES6), 239 237 octets

Set=``;eval(";a='Set=``;eval(~;a=1;S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);~)';S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);")

Prenez soin d'essayer chaque version dans un nouvel environnement (par exemple, un nouvel onglet de navigateur)

Il doit y avoir au moins un moyen de simplifier cela ...


1
Je suppose que vous pourriez utiliser un tableau pour les remplacements comme ceci: [x = "replace"]. Pourrait casser des choses cependant, je ne suis pas très expérimenté avec les quines ...
Luke
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.