Quine durcie par rayonnement


39

Comme vous le savez (espérons-le), une quine durcie aux radiations est une quine à partir de laquelle vous pouvez supprimer n’importe quel caractère et continuer d’imprimer sa source originale, préalablement modifiée. Le fait est qu'avec la plupart d'entre eux, vous ne pouvez supprimer qu'un seul caractère; sinon tout tombe en panne. C'est là que ça entre; votre objectif est de construire un quine durci par radiation capable de supprimer autant de personnages que possible. Toute langue conforme aux règles convient.

Règles

  • Le programme doit comporter au moins un caractère.
  • La langue utilisée doit être complète (les langues comme HQ9 + ne sont donc pas admissibles)
  • Toutes les autres règles applicables aux règles normales s'appliquent également ici.
  • La solution avec le moins program_length^(2/n)dans laquelle n'importe quel jeu de ncaractères exacts peut être supprimé tout en imprimant le code source original l'emporte.

1
J'essaie de trouver une solution dans Subleq. Je pense que ce serait idéal pour ce genre de défi!


Peut-être changerons-nous le nom, étant donné que ce n'est pas la même chose qu'une quine durcie par radiation? Peut-être " quine résistant aux radiations "?
Cyoce

@Cyoce La seule différence que je peux dire, c'est que ce défi concerne un nombre quelconque de retraits, alors que la plupart (sinon la totalité) des autres quines durcis par rayonnement ne le permettent que pour un seul.
takra

Solution rubis du célèbre "mame". github.com/mame/radiation-hardened-quine
mbomb007

Réponses:


57

Perl, 1116 1124 octets, n = 3, score = 1124 ^ (2/3) ou environ 108,1

Mise à jour : j'ai maintenant vérifié que cela fonctionne avec n = 3 via la force brute (ce qui a pris quelques jours); Avec un programme aussi complexe, il est difficile de vérifier manuellement la résistance aux radiations (et j'ai commis une erreur dans une version précédente, c'est pourquoi le nombre d'octets a augmenté). Fin de la mise à jour

Je recommande de rediriger stderr quelque part que vous ne le verrez pas; ce programme produit une tonne d'avertissements sur la syntaxe douteuse même lorsque vous ne supprimez pas de caractères de celle-ci.

Il est possible que le programme puisse être raccourci. Travailler dessus est assez pénible, ce qui permet de rater facilement les micro-optimisations possibles. Je visais surtout à obtenir le plus grand nombre possible de caractères supprimables (car c’est là la partie la plus difficile du programme), et j’ai considéré la rupture de comme un objectif agréable à atteindre, mais que je ne mettrais pas. effort ridicule d’optimisation (sur la base du fait qu’il est très facile de casser la résistance aux radiations par accident).

Le programme

Remarque: il y a un _caractère de contrôle littéral (ASCII 31) immédiatement avant chacune des quatre occurrences de -+. Je ne pense pas qu'il soit correctement copié-collé sur StackOverflow, vous devrez donc le rajouter avant d'exécuter le programme.

eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;
eval+<eval+<eval+<eval+(q(FoPqOlengthFoBBPP181XXVVVVJJJKKKNdoWchopJFtPDevalMODx4KNFrPIPA-MN-TUV-ZPINFsPIFoPqOI.Fo.IQNevalFoINevalIFsPZyI.Fr.IT-UPINsayDFtJqJFsKPZyPT-UFWrYrKD.DEEEEQDx6NsayDNDforB1..4YforB1..4NexitQNevalFo)=~y=A-Z=-+;-AZz-~=r)####>####>####>####>####>####>
;
;
;
;

L'explication

Clairement, ce programme est constitué de quatre programmes identiques plus petits concaténés ensemble. L'idée de base est que chaque copie du programme vérifie si elle a été trop endommagée pour être exécutée ou non. si cela a été le cas, il ne fera rien (à part peut-être émettre des avertissements) et laissera la copie suivante être exécutée; s'il ne l'a pas été (c.-à-d. aucune suppression, ou si le caractère qui a été supprimé ne fait aucune différence dans le fonctionnement du programme), il fera son petit geste (afficher le code source du programme complet; c'est un bon quine, avec chaque partie contenant un codage du code source complet) puis quittez (en empêchant toute autre copie non endommagée d’imprimer à nouveau le code source et de ruiner ainsi la séquence en imprimant trop de texte).

Chaque partie est à son tour composée de deux parties qui sont effectivement indépendantes sur le plan fonctionnel; un wrapper extérieur et un code interne. En tant que tels, nous pouvons les considérer séparément.

Emballage extérieur

Le wrapper extérieur est, en gros, eval<+eval<+eval< ... >####>####...>###(plus un groupe de points-virgules et de nouvelles lignes dont le but doit être assez évident; il s'agit de s'assurer que les parties du programme resteront séparées, que les sémicules ou les nouvelles lignes qui les précèdent soient supprimés. ). Cela peut paraître assez simple, mais c'est subtile de plusieurs façons et c'est la raison pour laquelle j'ai choisi Perl pour ce défi.

Tout d’abord, examinons le fonctionnement du wrapper dans une copie non endommagée du programme. evalanalyse en tant que fonction intégrée, qui prend un argument. Parce qu'un argument est attendu, +voici un unaire +(qui sera maintenant très familier aux golfeurs de Perl; ils sont d'une utilité surprenante souvent). Nous attendons toujours un argument (nous venons de voir un opérateur unaire), donc le <qui vient ensuite est interprété comme le début de l' <>opérateur (qui ne prend pas d'argument préfixe ou postfix, et peut donc être utilisé en position d'opérande).

<>est un opérateur assez bizarre. Son but est d' habitude de lire handles de fichiers, et vous placez le nom filehandle dans les crochets. Sinon, si l'expression n'est pas valide en tant que nom de descripteur de fichier, elle est globalisée (processus identique à celui utilisé par les shells UNIX pour traduire le texte entré par l'utilisateur en une séquence d'arguments de ligne de commande; des versions bien plus anciennes de Perl étaient effectivement utilisées). le shell pour cela, mais de nos jours Perl gère le globbing en interne). L’utilisation prévue va donc dans le sens de <*.c>, qui devrait normalement renvoyer une liste semblable à ("foo.c", "bar.c"). Dans un contexte scalaire (tel que l’argument deeval), il retourne simplement la première entrée trouvée lors de la première exécution (l'équivalent du premier argument) et renvoie d'autres entrées sur des exécutions hypothétiques futures qui ne se produisent jamais.

Maintenant, les shells gèrent souvent des arguments en ligne de commande; si vous donnez quelque chose comme -rsans argument, il sera simplement transmis intégralement au programme, qu'il y ait ou non un fichier portant ce nom. Perl agit de la même manière. Par conséquent, tant que nous nous assurons qu'il n'y a pas de caractères spéciaux pour le shell ou entre Perl <et les correspondances >, nous pouvons efficacement utiliser ceci comme une forme vraiment maladroite de littéral de chaîne. Mieux encore, l'analyseur Perl pour les opérateurs de type devis a une tendance compulsive à faire correspondre les crochets même dans des contextes comme celui-ci où cela n'a aucun sens, afin que nous puissions imbriquer en <>toute sécurité (ce qui est la découverte nécessaire pour que ce programme soit possible). Le principal inconvénient de tous ces éléments imbriqués <>est que l’échappement du contenu de la<>est presque impossible; il semble y avoir deux couches de fuites avec chacune <>, donc pour échapper à quelque chose à l'intérieur des trois, il faut le faire précéder de 63 barres obliques inverses. J'ai décidé que même si la taille du code n'était qu'une considération secondaire dans ce problème, cela ne valait certainement pas la peine de payer ce type de pénalité à mon score, alors j'ai simplement décidé d'écrire le reste du programme sans utiliser les caractères incriminés.

Alors que se passe-t-il si des parties de l'emballage sont supprimées?

  • Les suppressions dans le mot evalfont qu'il se transforme en mot simple , une chaîne sans signification. Perl n'aime pas cela, mais il les traite comme s'ils étaient entourés de guillemets. eal<+eval<+...est donc interprété comme"eal" < +eval<+.... Cela n'a aucun effet sur le fonctionnement du programme, car il ne prend en fait que le résultat des évaluations fortement imbriquées (que nous n'utilisons pas de toute façon), en le convertissant en un entier et en effectuant des comparaisons inutiles. (Ce type de produit génère de nombreux spams de mise en garde car ce n’est manifestement pas une chose utile à faire dans des circonstances normales; nous l’utilisons simplement pour absorber les suppressions.) Cela change le nombre de crochets dont nous avons besoin (parce que le est maintenant interprété comme un opérateur de comparaison), mais la chaîne de commentaires à la fin garantit que la chaîne se terminera en toute sécurité, quel que soit le nombre de fois où elle est imbriquée. (Il y a plus de #signes que strictement nécessaire ici; je l'ai écrit comme je l'ai fait afin de rendre le programme plus compressible, me permettant d'utiliser moins de données pour stocker le quine.)
  • Si un <est supprimé, le code est analysé comme eval(eval<...>). L'extérieur, secondaire evaln'a aucun effet, car les programmes que nous évaluons ne renvoient aucun élément ayant des effets réels en tant que programme (s'ils retournent normalement, c'est normalement une chaîne nulle ou un mot simple; plus généralement, ils retournent via exception, ce qui a evalpour effet de renvoyer une chaîne null ou de l’utiliser exitpour éviter de tout renvoyer).
  • Si a +est supprimé, cela n’a pas d’effet immédiat si le code adjacent est intact; unaire +n'a aucun effet sur le programme. (Les raisons d'origine +existent pour aider à réparer les dommages; elles augmentent le nombre de situations dans lesquelles un <interprète est considéré comme unaire, <>plutôt que comme un opérateur relationnel, ce qui signifie que vous avez besoin de plus de suppressions pour générer un programme invalide.)

L'empaquetage peut être endommagé avec suffisamment de suppressions, mais vous devez effectuer une série de suppressions afin de produire quelque chose qui n'est pas analysé. Avec quatre suppressions, vous pouvez faire ceci:

eal<evl<eval+<...

et en Perl, l'opérateur relationnel <n'est pas associatif et vous obtenez donc une erreur de syntaxe (identique à celle que vous obtiendriez 1<2<3). En tant que tel, le plafond du programme écrit est n = 3. Ajouter plus de unaires +semble un moyen prometteur de l’augmenter, mais comme cela rendrait de plus en plus probable que l’intérieur de l’emballage puisse aussi se briser, il peut être très difficile de vérifier que la nouvelle version du programme fonctionne.

La raison pour laquelle l'encapsuleur est si précieux est que evalPerl intercepte des exceptions, telles que (par exemple) l'exception que vous obtenez lorsque vous essayez de compiler une erreur de syntaxe. Comme il evals'agit d'un littéral de chaîne, la compilation de la chaîne a lieu au moment de l'exécution et si la compilation échoue, l'exception qui en résulte est interceptée. Cela a evalpour effet de renvoyer une chaîne null et de définir l'indicateur d'erreur $@, mais nous ne vérifions jamais non plus (sauf en exécutant occasionnellement la chaîne null renvoyée dans quelques versions mutées du programme). Surtout, cela signifie que si quelque chose devait arriver au code à l' intérieurle wrapper, causant une erreur de syntaxe, il ne fera que rendre le code inactif (et le programme continuera à s'exécuter pour tenter de trouver une copie non endommagée de lui-même). Par conséquent, le code interne ne doit pas nécessairement être aussi résistant aux radiations que l’emballage; tout ce qui nous importe est que s'il est endommagé, il agira de la même manière que la version non endommagée du programme, ou bien il plantera (permettant evald'attraper l'exception et de continuer) ou quittera normalement sans imprimer.

À l'intérieur de l'emballage

Le code à l'intérieur du wrapper, fondamentalement, ressemble à ceci (là encore, il y a un contrôle - _que Stack Exchange ne montrera pas immédiatement avant le -+):

eval+(q(...)=~y=A-Z=-+;-AZz-~=r)

Ce code est entièrement écrit avec des caractères globales, et vise à ajouter un nouvel alphabet de signes de ponctuation permettant d'écrire un programme réel, en effectuant une translittération et en évaluant un littéral de chaîne (nous ne pouvons ni utiliser 'ni "citer marques, mais q()est également un moyen valide de former une chaîne en Perl). (La raison du caractère non imprimable est que nous devons translittérer quelque chose dans le caractère espace sans caractère littéral dans le programme; nous formons ainsi une plage commençant à ASCII 31 et l'interceptons comme deuxième élément de la plage.) Évidemment, si nous produisons des caractères par translittération, nous devons sacrifier des caractères pour les translittérer de, mais les lettres majuscules ne sont pas très utiles et il est beaucoup plus facile d’écrire sans accès à celles-ci que sans accès aux signes de ponctuation.

Voici l'alphabet des signes de ponctuation qui deviennent disponibles à la suite du glob (la ligne supérieure indique l'encodage, la ligne inférieure le caractère qu'il code):

BCDEFGHIJKLMNOPQRSTUVWXYZ
 ! "# $% & '() * +; <=>? @ AZz {|} ~ 

Plus particulièrement, nous avons un tas de signes de ponctuation qui ne sont pas globalement sûrs mais qui sont utiles pour écrire des programmes Perl, ainsi que le caractère espace. J'ai également enregistré deux lettres majuscules, le littéral Aet Z(qui ne codent pas pour elles-mêmes, mais pour Tet U, car elles Aétaient nécessaires en tant que point final supérieur et inférieur); cela nous permet d'écrire l'instruction de translittération elle-même en utilisant le nouveau jeu de caractères codés (bien que les lettres majuscules ne soient pas très utiles, elles sont utiles pour spécifier les modifications à apporter aux lettres majuscules). Les caractères les plus remarquables dont nous ne disposons pas sont [, \et ], mais aucun n’est nécessaire (lorsque j’avais besoin d’une nouvelle ligne dans la sortie, je l’ai produite à l’aide de la nouvelle ligne implicite desayplutôt que d'avoir besoin d'écrire \n; chr 10aurait également fonctionné mais est plus prolixe).

Comme d'habitude, nous devons nous inquiéter de ce qui se passe si l'intérieur du wrapper est endommagé en dehors du littéral string. Un corrompu evalempêchera tout en cours d'exécution; cela nous convient. Si les guillemets sont endommagés, l’intérieur de la chaîne n’est pas valide en Perl, et donc le wrapper l’attrapera (et les nombreuses soustractions sur les chaînes signifient que même si vous pouviez le rendre valide en Perl, il ne ferait rien, ce qui est un résultat acceptable). Si la translittération n’est pas une erreur de syntaxe, la chaîne en cours d’évaluation sera mutilée, ce qui en fera généralement une erreur de syntaxe; Je ne suis pas tout à fait sûr qu'il n'y ait pas de cas dans lequel cela se casse, mais je le force brute pour le moment, mais ce devrait être assez facile à réparer s'il y en a.

Le programme encodé

En regardant à l'intérieur du littéral de chaîne, en inversant l'encodage que j'ai utilisé et en ajoutant des espaces pour le rendre plus lisible, nous obtenons ceci (encore une fois, imaginons un contrôle-soulignement avant le -+, codé ainsi A):

$o=q<
  length$o  ==181 || zzzz((()));
  do {
    chop ($t = "eval+<"x4);
    $r = '=-+;-AZz-~=';
    $s = '$o=q<' . $o . '>;eval$o';
    eval '$s=~y' . $r . 'A-Z=';
    say "$t(q($s)=~y=A-Z${r}r)" . "####>"x6;
    say ";" for 1..4
  } for 1..4;
  exit>;
eval $o

Les personnes habituées à quines reconnaîtront cette structure générale. La partie la plus cruciale est au début, où nous vérifions que $ o n’est pas endommagé; si les caractères ont été supprimés, sa longueur ne correspondra pas à 181, donc nous courons zzzz((()))qui, si elle n'est pas une erreur de syntaxe en raison de supports inégalés, sera une erreur d'exécution même si vous supprimez tous les trois personnages, parce qu'aucun de zzzz, zzz, zz, et zest une fonction, et il n’ya aucun moyen de l’empêcher de l’analyser comme une fonction autre que la suppression (((et la génération d’une erreur de syntaxe évidente. Le chèque lui-même est également immunisé contre les dommages; cela ||peut être endommagé, |mais l' zzzz((()))appel sera exécuté sans condition; les variables ou les constantes préjudiciables causeront une disparité, car vous comparez l’un des éléments suivants 0,180, 179, 178Pour l' égalité à un sous - ensemble des chiffres 181; et en supprimer un =provoquera un échec d'analyse, et deux =obligeront inévitablement le LHS à se transformer en un entier égal à 0 ou en une chaîne nulle, les deux étant falsey.

Mise à jour : Cette vérification était légèrement fausse dans une version précédente du programme, j'ai donc dû la modifier pour résoudre le problème. La version précédente ressemblait à ceci après le décodage:

length$o==179||zzzz((()))

et il était possible de supprimer les trois premiers signes de ponctuation pour obtenir ceci:

lengtho179||zzz((()))

lengtho179, étant un mot simple, est la vérité et brise ainsi la vérification. J'ai corrigé cela en ajoutant deux Bcaractères supplémentaires (qui codent les espaces), ce qui signifie que la dernière version de la quine fait ceci:

length$o  ==181||zzzz((()))

Maintenant, il est impossible de cacher les =signes et le $signe sans produire une erreur de syntaxe. (Je devais ajouter deux espaces plutôt qu'un, car une longueur 180mettrait un 0caractère littéral dans la source, ce qui pourrait être abusé dans ce contexte pour comparer zéro avec un mot simple, ce qui aboutit.) Fin de la mise à jour

Une fois que la vérification de la longueur est réussie, nous savons que la copie est intacte, du moins en termes de suppressions de caractères, de sorte que tout est mis en ordre à partir de là (les substitutions de signes de ponctuation dues à une table de décodage corrompue ne seraient pas capturées , mais j’ai déjà vérifié, par la force des brutes, qu’il n’existait pas trois suppressions provenant uniquement de la table de décodage, mais la plupart d’entre elles provoquaient probablement des erreurs de syntaxe. Nous avons $odans une variable déjà, donc tout ce que nous devons faire est de mettre en dur (avec des enveloppes à l' extérieur un petit degré de compression, je ne l' ai pas sauter le partie de la question tout à fait ). Une astuce consiste à stocker la majeure partie de la table de codage dans$r; nous pouvons soit l’imprimer littéralement afin de générer la section de la table de codage de l’emballage interne, soit concaténer du code autour de celle- evalci afin de lancer le processus de décodage à l’inverse (nous permettant ainsi de déterminer quelle est la version codée de $ o , seule la version décodée étant disponible à ce stade).

Enfin, si nous étions une copie intacte et pouvions ainsi sortir le programme original dans son intégralité, nous appelons exitafin d’empêcher les autres copies d’essayer également d’imprimer le programme.

Script de vérification

Pas très joli, mais l'affiche parce que quelqu'un l'a demandé. J'ai couru cela plusieurs fois avec une variété de paramètres (généralement en train de changer $minet $maxde vérifier différents domaines d'intérêt); ce n'était pas un processus entièrement automatisé. Il a tendance à s’arrêter en raison de la charge de processeur élevée ailleurs; lorsque cela se produisait, je venais juste de passer $minà la première valeur $xqui n'était pas entièrement vérifiée et je continuais à exécuter le script (assurant ainsi que tous les programmes de la gamme étaient vérifiés). J'ai seulement vérifié les suppressions de la première copie du programme, car il est assez évident que les suppressions des autres copies ne peuvent pas faire plus.

use 5.010;
use IPC::Run qw/run/;
undef $/;
my $program = <>;
my $min = 1;
my $max = (length $program) / 4 - 3;
for my $x ($min .. $max) {
    for my $y ($x .. $max) {
        for my $z ($y .. $max) {
            print "$x, $y, $z\n";
            my $p = $program;
            substr $p, $x, 1, "";
            substr $p, $y, 1, "";
            substr $p, $z, 1, "";
            alarm 4;
            run [$^X, '-M5.010'], '<', \$p, '>', \my $out, '2>', \my $err;
            if ($out ne $program) {
                print "Failed deleting at $x, $y, $z\n";
                print "Output: {{{\n$out}}}\n";
                exit;
            }
        }
    }
}

say "All OK!";

3
Le PO est un peu ambigu. mais je pensais que le score serait (1116 * 1116) / 3.
Greg Martin

@GregMartin: (1116 * 1116) / 3 est 415152, cette entrée serait donc toujours gagnante dans ces circonstances. Cependant, je ne pense pas que le PO puisse signifier cela, car cela donnerait très peu d'incitation à pouvoir supprimer plusieurs personnages. Cette quine peut être inférieure à la moitié de la longueur si vous n'en avez besoin que pour gérer la suppression d'un caractère; cela me donnerait un ÷ 4 effectif sur le score si nous l'interprétions comme cela, ce qui l'emporterait sur le ÷ 3 que je tire de n = 3, ce qui signifierait donc que les entrées les moins intéressantes n = 1 sont en réalité plus performantes.

2
J'ai rendu la notation plus claire. En tout cas, c'est absolument incroyable. ne pensais pas que quelqu'un aurait n> 1.
takra

1
Cela dit quelque chose à propos de Perl qu'il est plus facile d'écrire un programme sans lettres que sans ponctuation
Robert Fraser

35

Befunge-98 , 884, n = 14, score ≈ 2,636

f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx"""""""""""""""fffffffffffffff'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''000000000000000\\\\\\\\\\\\\\\'''''''''''''''fffffffffffffff\\\\\\\\\\\\\\\111111111111111---------------:::::::::::::::!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!000000000000000aaaaaaaaaaaaaaa---------------bbbbbbbbbbbbbbb---------------***************jjjjjjjjjjjjjjj$$$$$$$$$$$$$$$'''''''''''''''+++++++++++++++kkkkkkkkkkkkkkk,,,,,,,,,,,,,,,333333333333333kkkkkkkkkkkkkkk$$$$$$$$$$$$$$$000000000000000{{{{{{{{{{{{{{{'''''''''''''''888888888888888uuuuuuuuuuuuuuu'''''''''''''''!!!!!!!!!!!!!!!111111111111111+++++++++++++++'''''''''''''''xxxxxxxxxxxxxxx###############;;;;;;;;;;;;;;;:::::::::::::::!!!!!!!!!!!!!!!kkkkkkkkkkkkkkk@@@@@@@@@@@@@@@dddddddddddddddkkkkkkkkkkkkkkk:::::::::::::::eeeeeeeeeeeeeeekkkkkkkkkkkkkkk,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;

Essayez-le en ligne!

Cela ne fonctionne pas uniquement lorsque vous supprimez exactement 14 caractères, mais même lorsque vous supprimez un maximum de 14 caractères.

n = 14Cela peut sembler un choix très arbitraire, mais la technique que j'ai utilisée ne peut en fait être utilisée que pour les ordres de durcissement des radiations allant de 1 à 14, mais pas facilement au-delà (cela pourrait être possible, mais je ne sais pas comment.). Order-1 quine ne fait que 73 octets (bien qu’il utilise des astuces de golf qui ne s’appliquent pas aux plus grands n):

200 20 xx""''ÈÈ..aa22**..33kk$$00{{''!!uu''!!11++''xx##;;::!!kk@@::,,,,;;

Explication

Lorsque je travaillais sur cette réponse, j'ai découvert qu'il était possible de définir le delta du pointeur d'instruction sur (2,0)dans des conditions de durcissement extrême, avec l'extrait suivant:

20020xx

Voir cette réponse pour savoir pourquoi cela fonctionne. J'ai trouvé cela juste avec quelques manipulations à la main, mais cela a posé la question de savoir s'il existe des modèles similaires qui sont robustes lorsque plusieurs caractères sont supprimés. J'ai donc écrit un court script Mathematica pour rechercher ces éléments par force brute:

n = 14;
m = 4;
Print @ FromDigits @ {
      m + 1, 0, 
      ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
      m + 1, 0
} & /@ Select[
   Range[0, 2^(n - 4) - 1], 
   AllTrue[
     Subsets[{
         m + 1, 0, 
         ## & @@ ((m + 1) IntegerDigits[#, 2, n - 4]),
         m + 1, 0
       }, 
       {n - m, n - 1}
     ] //. {a___, _, m + 1} | {a___, 0, _} :> {a}, 
     MatchQ@{___, m + 1, 0}
  ] &
];

Cela a très vite révélé un motif. Pour obtenir un extrait correspondant qui permet de supprimer un maximum de ncaractères, vous pouvez utiliser (m0x){n}m0mest n+1et xest l'un mou l' autre 0. Ainsi, tous les éléments suivants fonctionneraient pour la suppression de deux caractères au maximum:

30030030
30030330
30330030
30330330

Je suis sûr qu'il est possible de le prouver, mais j'ai simplement vérifié njusqu'à 7. Bien sûr, cela ne fonctionne que tant que nous pouvons représenter n+1sous forme de chiffre unique, et le plus grand chiffre de ce type dans Befunge 98 fcorrespond à 15. C'est pourquoi mon approche est limitée à n = 14. Si quelqu'un trouve un moyen d' n+1augmenter de manière fiable le delta , il serait probablement possible d'augmenter l'ordre de ce quine durci aux radiations indéfiniment.

Regardons le code actuel. Il comporte essentiellement deux parties. Tout d'abord, nous plaçons le delta sur (15,0)comme je viens de le mentionner:

f00f00f00f00f00f00f00f00f00f00f00f00f00f00f0xxxxxxxxxxxxxxx

Et le reste du code a chaque commande répétée 15 fois et imprime la source. Si nous supprimons la répétition, cela ressemble à ceci:

"f'0\'0\'f\1-:!!0a-b-*j$'+k,3k$0{'8u'!1+'x#;:!k@dk:ek,;

Il "s'agit d'une technique de quining 2D standard: elle démarre le mode chaîne, place tous les caractères (sauf lui-même) sur la pile et termine le mode chaîne une fois le bouclé terminé. Cela nous aide à obtenir tous les points de code du second semestre, mais il ne parviendra pas à nous faire quelque chose d' utile de la première moitié, car tout au long du f00f00...f0bit, il n'enregistrera deux caractères (qui peuvent être soit fou 0selon lequel les caractères sont supprimés ) Mais comme cette partie n’est pas composée de caractères répétés 15 fois, nous aurons quand même besoin de l’imprimer séparément.

De manière plus pratique, dans le cas non modifié, la longueur de la chaîne avant le "est -1 (mod 15). Cela garantit que quel que soit le nombre de caractères (jusqu'à 14) que nous supprimons, le nombre de caractères enregistrés est toujours de 3 (un xet deux de fet 0). Ceci est vrai pour toute commande de radiation jusqu’à 14.

Nous commençons maintenant par imprimer la f00f00...f0pièce:

f'0\'0\'f\1-:!!0a-b-*j$'+k,

f          Push 15, a loop counter.
'0\'0\'f\  Put "00f" underneath the loop counter.
1-         Decrement the loop counter.
:!!        Copy it, and turn it into a 1 if it's positive.
0a-b-      Push -21.
*          Multiply by 0 if the loop counter is zero, or by 1 otherwise.
j          Jump that many steps. If the value was 0, this is a no-op and
           the loop ends. Otherwise, this brings us back after the f.
$          Pop the loop counter (which is now 0).
'+k,       Print the top of the stack 43 times, which gives us all of
           the "f00f00...f0" and leaves one "0" on top of the stack.

Le suivant 3k$ignore simplement cela 0ainsi que les trois personnages qui ont été poussés "depuis le début du programme. La pile ne contient plus que les caractères après le ", ainsi que des éléments indésirables sous l’original, en f00f00...f0fonction des caractères supprimés.

Il ne nous reste plus qu’à inverser le haut de la pile (contenant les caractères restants) et à les imprimer 15 fois.

0{     Start a new, empty stack. This pushes two zeros onto the original stack.
'8u    Move the top 56 values from the original stack to the new one, which
       is the 54 characters after the " as well as those two zeros. This is
       implemented as pop-push loop, so it reverses the order of those elements.
'!1+   Push a " by incrementing a !.
'x     Push an x. Now we've got all the characters that are repeated 15 times.
#;     Enter a loop. This is a standard technique for Befunge-98: the ; is
       a bit like a comment character, that ignores everything until the next
       ;, but we jump over the first one with #, so that from now on only
       the code inside will be executed (over and over).
  :!     Copy the top of the stack, and compute logical NOT (1 if 0, 0 otherwise).
  k@     Terminate the program that many times (i.e. when the top of the
         stack is zero).
  dk:    Make 14 copies of the top of the stack.
  ek,    Print 15 characters from the top of the stack.
;

Et c'est tout. :)


16

JavaScript (ES6), 927 octets, n = 1, score = 859329

remarque: n'utilisez pas de REPL (comme une console de navigateur) pour l'exécuter.

Cela a été écrit avant que la longueur du code ne soit un facteur important, donc il n'est pas encore joué au golf.

C'était très difficile et mérite une explication approfondie. Ce que j'écrirai plus tard, après avoir exploré un peu plus ce défi!

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

note: il y a un retour à la ligne

Fondamentalement, la première ligne est construite avec soin pour renommer toutes les "fautes d'orthographe" setTimeouten fonctions valides, de sorte que si un caractère est supprimé de l'un des setTimeouts, le code ne sera pas en erreur et la version non endommagée pourra être exécutée. Il est également écrit de sorte que si un caractère quelconque est supprimé de la première ligne, il n'y aura pas d'erreur et le reste du code pourra être exécuté sans être affecté.

Les deuxième et troisième blocs sont exactement équivalents. Si l'un d'entre eux est terminé, il définit la _variable de sorte que l'autre sache ne pas dupliquer le quine. Si l'un de ces blocs tombe en erreur, il n'affecte pas l'autre bloc car il a été appelé de manière asynchrone par setTimeout. L'erreur entraînera la _non définition, de sorte que l'autre bloc sera terminé avec succès. Le code principal est une chaîne dont la longueur est vérifiée dans chaque bloc pour s'assurer qu'il n'y a pas eu de suppression.

Les chaînes de modèle sur la ligne suivante avec des commentaires à la fin des chaînes de modèle protègent le code des erreurs si l'une des backticks formant la chaîne de modèle est supprimée. Si le backtick final est supprimé, la chaîne de modèle se termine par le backtick dans le commentaire. Si le backtick de départ est supprimé, setTimeout est évalué en tant que fonction non attribuée (no-op) et le code s'exécute normalement, sans setTimeout. Le backtick final est annulé par un autre commentaire.


Qu'est-ce que vous dites? Vous voulez l'essayer? Ne dis pas plus!

Mode pleine page recommandé.

Ignorer la zone de saisie, cet extrait ne prend aucune entrée.

Essayez de supprimer n'importe quel caractère du code!

Ne le crois pas? Le code normal fonctionnera toujours (mais il ne sera pas quine ...) Essayez quelque chose comme console.log(5)!

Remarque: l'extrait de code a dû être légèrement modifié pour désactiver la fonction REPL. J'ai donc supprimé plusieurs fonctionnalités de sortie pour cette réponse uniquement.

etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;
setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`

setTimeout
`c="function f(){x=String.fromCharCode(96);n=String.fromCharCode(10);q=String.fromCharCode(34);y='etTimeout=stTimeout=seTimeout=setimeout=setTmeout=setTieout=setTimout=setTimeut=setTimeot=setTimeou=unescape=>42;'+n;z='setTimeout'+n+x+'c='+q+f+';f();_=1'+q+';if(window._);else if(c.length>339)eval(c)//'+x+'///'+x+n+n;console.log(y+z+z)};f();_=1";if(window._);else if(c.length>339)eval(c)//`///`
<!--                               Try the test suite below!                              --><strong id="bytecount" style="display:inline; font-size:32px; font-family:Helvetica"></strong><strong id="bytediff" style="display:inline; margin-left:10px; font-size:32px; font-family:Helvetica; color:lightgray"></strong><br><br><pre style="margin:0">Code:</pre><textarea id="textbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><pre style="margin:0">Input:</pre><textarea id="inputbox" style="margin-top:5px; margin-bottom:5px"></textarea><br><button id="testbtn">Test!</button><button id="resetbtn">Reset</button><br><p><strong id="origheader" style="font-family:Helvetica; display:none">Original Code Output:</strong><p><div id="origoutput" style="margin-left:15px"></div><p><strong id="newheader" style="font-family:Helvetica; display:none">New Code Output:</strong><p><div id="newoutput" style="margin-left:15px"></div><script type="text/javascript" id="golfsnippet">var bytecount=document.getElementById("bytecount");var bytediff=document.getElementById("bytediff");var textbox=document.getElementById("textbox");var inputbox=document.getElementById("inputbox");var testbtn=document.getElementById("testbtn");var resetbtn=document.getElementById("resetbtn");var origheader=document.getElementById("origheader");var newheader=document.getElementById("newheader");var origoutput=document.getElementById("origoutput");var newoutput=document.getElementById("newoutput");textbox.style.width=inputbox.style.width=window.innerWidth-50+"px";var _originalCode=null;function getOriginalCode(){if(_originalCode!=null)return _originalCode;var allScripts=document.getElementsByTagName("script");for(var i=0;i<allScripts.length;i++){var script=allScripts[i];if(script.id!="golfsnippet"){originalCode=script.textContent.trim();return originalCode}}}function getNewCode(){return textbox.value.trim()}function getInput(){try{var inputText=inputbox.value.trim();var input=eval("["+inputText+"]");return input}catch(e){return null}}function setTextbox(s){textbox.value=s;onTextboxChange()}function setOutput(output,s){output.innerHTML=s}function addOutput(output,data){output.innerHTML='<pre style="background-color:'+(data.type=="err"?"lightcoral":"lightgray")+'">'+escape(data.content)+"</pre>"}function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}function onTextboxChange(){var newLength=getByteCount(getNewCode());var oldLength=getByteCount(getOriginalCode());bytecount.innerHTML=newLength+" bytes";var diff=newLength-oldLength;if(diff>0){bytediff.innerHTML="(+"+diff+")";bytediff.style.color="lightcoral"}else if(diff<0){bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgreen"}else{bytediff.innerHTML="("+diff+")";bytediff.style.color="lightgray"}}function onTestBtn(evt){origheader.style.display="inline";newheader.style.display="inline";setOutput(newoutput,"");setOutput(origoutput,"");var input=getInput();if(input===null){addOutput(origoutput,{type:"err",content:"Input is malformed. Using no input."});addOutput(newoutput,{type:"err",content:"Input is malformed. Using no input."});input=[]}doInterpret(getNewCode(),input,function(data){addOutput(newoutput,data)});doInterpret(getOriginalCode(),input,function(data){addOutput(origoutput,data)});evt.stopPropagation();return false}function onResetBtn(evt){setTextbox(getOriginalCode());origheader.style.display="none";newheader.style.display="none";setOutput(origoutput,"");setOutput(newoutput,"")}function escape(s){return s.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}window.alert=function(){};window.prompt=function(){};function doInterpret(code,input,cb){var workerCode=interpret.toString()+";function stdout(s){ self.postMessage( {'type': 'out', 'content': s} ); }"+" function stderr(s){ self.postMessage( {'type': 'err', 'content': s} ); }"+" function kill(){ self.close(); }"+" self.addEventListener('message', function(msg){ interpret(msg.data.code, msg.data.input); });";var interpreter=new Worker(URL.createObjectURL(new Blob([workerCode])));interpreter.addEventListener("message",function(msg){cb(msg.data)});interpreter.postMessage({"code":code,"input":input});setTimeout(function(){interpreter.terminate()},1E4)}setTimeout(function(){getOriginalCode();textbox.addEventListener("input",onTextboxChange);testbtn.addEventListener("click",onTestBtn);resetbtn.addEventListener("click",onResetBtn);setTextbox(getOriginalCode())},100);function interpret(code,input){_=undefined;window={};alert=function(s){stdout(s)};window.alert=alert;console.log=alert;prompt=function(s){if(input.length<1)stderr("not enough input");else{var nextInput=input[0];input=input.slice(1);return nextInput.toString()}};window.prompt=prompt;(function(){try{_=undefined;eval(code);if(typeof evalResult=="disabled_function_evaluation"){var callResult=evalResult.apply(this,input);if(typeof callResult!="undefined")stdout(callResult)}}catch(e){stderr(e.message)}})()};</script>

Une meilleure explication est à venir. En attendant, n'hésitez pas à me contacter sur le chat @jrich avec vos commentaires / questions / critiques!


ah ok, whoops: |
Downgoat

4
Utilisez thisau lieu de window.
Mama Fun Roll

3
+1 pour inclure le sens de la vie dans votre code source
Cyoce
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.