zsh, 603 594 566 561 548 440 415 399 378 370 octets
ec
ho \\n;ca t<<<$'\x20';exi t
d$c -e8BC6P
d0c -eKp
$'\172\163\150' $'\055\143' $'\146\157\162 v \151\156 \173\043\056\056\134\175\175\073\173 \146\147\162\145\160 \055\161 $\166 '$0$'\174\174\074\074\074$\166\073\175'
$'\145v\141\154' $':\073\072\046\046\145\170\151\164';#%&()*+,/9=>?@ADEFGHIJLMNOQRSTUVWXYZ[]^_`jklmsuwy
0# $#;for b in {$..z};{ fgrep -q $b $0||<<<$b;}
Dépend de coreutils + dc
.
Essayez-le en ligne!
C'était ... un voyage.
Cette réponse comporte trois parties. Les 4 premières lignes gèrent certains cas particuliers pour simplifier le code qui suit. Les 2 lignes suivantes et la dernière ligne accomplissent toutes deux essentiellement la même chose, mais exactement une est exécutée avec la suppression d'un caractère donné. Ils sont écrits avec des jeux de caractères pour la plupart complémentaires, de sorte que la suppression de tout caractère ne rompt qu'un seul, permettant à l'autre de continuer à fonctionner.
En regardant la première partie, nous nous occupons d'abord
- suppression de la nouvelle ligne avec
ec\nho \\n
- suppression d'espace avec
ca t<<<$'\x20'
(suivi de exi t
pour éviter d'exécuter du code plus tard, ce qui entraînerait une sortie étrangère)
$
suppression avec d$c -e8BC6P
( 8BC6
= 9226
is 36*256 + 10
, et 36 et 10 sont les valeurs d'octet des $
caractères et newline respectivement; nous utilisons des chiffres hexadécimaux en décimal pour éviter d'avoir à les inclure dans le grand commentaire de la ligne 6)
0
suppression avec d0c -eKp
( K
obtient la précision décimale, qui est 0
par défaut)
Dans la partie suivante, les seuls caractères utilisés (à part les ordures à la fin de la deuxième ligne) sont $'\01234567v;
, l'espace et la nouvelle ligne. Parmi ceux-ci, quatre ont été pris en compte, de sorte que le reste ( '\1234567v
) ne peut pas apparaître sur la dernière ligne. En développant les échappements octaux ( $'\123'
représente le caractère ASCII avec la valeur 123 8 ), on obtient:
zsh -c 'for v in {#..\}};{ fgrep -q $v '$0'||<<<$v;}'
eval ':;:&&exit'
La première ligne parcourt tous les caractères utilisés dans le programme et recherche chacun dans son propre code source ( $0
c'est le nom de fichier du script en cours d'exécution), en imprimant tout caractère introuvable.
La deuxième ligne semble un peu étrange et semble faire la même chose exit
qu'avec un tas de nops. Cependant, le codage exit
en octal entraîne directement $'\145\170\151\164'
ce qui ne contient pas 2
ou 3
. Nous devons en fait rendre cela moins résistant aux renvois. En effet, si l'un d'entre eux '\014567v
est supprimé, la première ligne est rompue, la deuxième ligne se rompt également, permettant au reste du code de s'exécuter. Cependant, nous avons besoin qu'il se casse également si 2
ou 3
sont supprimés pour que les lignes 3 et 4 puissent s'exécuter. Ceci est accompli par le cordage des chaussures dans :
et ;
, qui ont respectivement 2 et 3 dans leur représentation octale.
La jonque à la fin de la ligne 2 est simplement là pour s'assurer que chaque caractère ASCII imprimable apparaît au moins une fois, car la manière dont la vérification est effectuée en bouclant à travers chacun l'exige.
Si exit
n'a pas été appelé dans la première section (c'est-à-dire qu'il a été mutilé par la suppression de l'un '\01234567v
), nous passons à la seconde, dans laquelle nous devons accomplir la même chose sans utiliser aucun de ces caractères. La dernière ligne est similaire à la première ligne décodée, sauf que nous pouvons réduire la plage de la boucle pour économiser quelques octets, car nous savons déjà que tous les caractères, à l'exception de, '\01234567v
ont été couverts. Il a également 0# $#
devant lui, qui le commente et l'empêche de produire une sortie étrangère si 0
ou a $
été supprimé.