Il y a 95 caractères ASCII imprimables :
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Dans la police Consolas (le bloc de code Stack Exchange par défaut), certains des caractères ont des miroirs autour d'un axe vertical de symétrie:
- Ces paires de personnages sont des miroirs l'une de l'autre:
()
[]
{}
<>
/\
- Ces personnages sont des miroirs d'eux-mêmes:
! "'*+-.8:=AHIMOTUVWXY^_ovwx|
(Notez que l'espace est un.) - Ceux-ci n'ont pas de miroirs:
#$%&,012345679;?@BCDEFGJKLNPQRSZ`abcdefghijklmnpqrstuyz~
( i
, l
, 0
, #
, Et probablement d' autres personnages sont leurs propres miroirs dans certaines polices , mais nous allons en tenir aux formes Consolas.)
Une chaîne est considérée comme un miroir d'elle-même si elle est composée uniquement des 39 caractères miroir , disposés de telle sorte que la chaîne présente une ligne de symétrie verticale centrale. ](A--A)[
Est donc un miroir de lui-même mais ](A--A(]
ne l'est pas.
Écrivez un programme de longueur paire d'une ligne qui est un miroir de lui-même. Lorsque N copies de sa moitié gauche lui ont été ajoutées et que N copies de sa moitié droite lui ont été ajoutées, il devrait produire N + 1. N est un entier non négatif.
Par exemple, si le programme était ](A--A)[
(moitié gauche:, ](A-
moitié droite:) -A)[
, alors:
- L'exécution
](A--A)[
devrait sortir1
. (N = 0) - L'exécution
](A-](A--A)[-A)[
devrait sortir2
. (N = 1) - L'exécution
](A-](A-](A--A)[-A)[-A)[
devrait sortir3
. (N = 2) - L'exécution
](A-](A-](A-](A--A)[-A)[-A)[-A)[
devrait sortir4
. (N = 3) - . . .
- L'exécution
](A-](A-](A-](A-](A-](A-](A-](A-](A-](A--A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[
devrait sortir10
. (N = 9) - etc.
Règles
- Sortie vers stdout ou l'alternative la plus proche de votre langue. Il peut y avoir une nouvelle ligne de fin facultative. Aucune entrée ne doit être prise.
- Le processus devrait théoriquement fonctionner pour N jusqu'à 2 15 -1 ou au-delà, avec suffisamment de mémoire et de puissance de calcul.
- Un programme complet est requis, pas seulement une commande REPL .
Le programme initial le plus court (N = 0 cas) en octets gagne.
la source
#
c'est aussi sa propre reflexion, mais, vous avez raison, pas dans les consoles.Réponses:
Pip,
1284 octetsMaintenant avec 66% d'octets en moins!
x
est une variable, préinitialisée à""
. Dans le contexte numérique, cela devient0
.+
, exprime la formex+x+...+x
. Ceci est une déclaration valide qui ne fait rien.+
de la première mi-temps, exprime la forme++x+x+...+x
.++x
incrémentsx
à1
, et le reste l'ajoute à lui-même N fois. Étant donné que les expressions sont évaluées de gauche à droite dans Pip, l'incrément est garanti de se produire en premier et le résultat est égal au nombre de niveaux de miroir.Malheureusement, Pip ne traite pas bien les expressions énormes: cette solution provoque une
maximum recursion depth exceeded
erreur pour N au-dessus de 500 environ. Voici une solution précédente qui ne fonctionne pas, pour 8 octets :Plus sur Pip
la source
Fatal error: maximum recursion depth exceeded while calling a Python object
.x+x+...+x
génère une profondeur de récursion O (N). Peut-être que cela invalide cette réponse. Je vais ajouter une note.GolfScript, 10 octets
Essayez-le en ligne avec Web Golfscript: N = 0 , N = 1 , N = 2 , N = 3 , N = 41
Web GolfScript a une limite de 1024 caractères, mais l'interpréteur Ruby gère parfaitement N = 32767 :
Comment ça marche
Sans aucune entrée, GolfScript a initialement une chaîne vide sur la pile.
Dans la première moitié gauche, les événements suivants se produisent:
!
applique NOT logique à la chaîne vide. Cela pousse1
.:{
enregistre l'entier sur la pile dans la variable{
.Oui, c'est un identifiant valide, bien qu'il n'y ait aucun moyen de récupérer la valeur stockée.
)
incrémente l'entier sur la pile.:
est une instruction incomplète.Les moitiés gauche suivantes, les événements suivants se produisent:
:!
(où:
est un reste d'avant) enregistre l'entier sur la pile dans la variable!
.Oui, c'est aussi un identifiant valide. Cela rompt la
!
commande, mais nous ne l'utilisons plus.:{
,)
Et le:
travail comme avant.Dans la première moitié droite, les événements suivants se produisent:
::
(où:
est un reste d'avant) enregistre l'entier sur la pile dans la variable:
.Oui, même cela est un identifiant valide. Comme avec
{
, il n'y a aucun moyen de récupérer la valeur stockée.(
décrémente l'entier de la pile, donnant le nombre de moitiés gauches.}
, car il est inégalé et termine immédiatement l'exécution.Il s'agit d'une fonctionnalité non documentée. Je les appelle des super-commentaires .
Le code restant est simplement ignoré.
la source
}
dans la seconde moitié de votre code dans une compétition miroir."\""/"
, la quatrième citation double serait également inégalée puisque la seconde a été échappée.Code machine Z80,
86 octets *<8ww8>
* Suppose certaines conditions en entrant depuis Amstrad BASICA
est initialement 0 lorsqu'il est entré depuis BASIC. Il incrémenteA
n fois, puis l'écrit n fois dans le même emplacement mémoire (qui est défini sur un emplacement légèrement aléatoire par BASIC)! L'JR
opération Jump Relative ne fait jamais rien car leC
drapeau est toujours non défini, il est donc utilisé pour "commenter" l'octet suivant! Cette version triche légèrement en supposant certaines conditions d'entrée, à savoir la saisie à partir des garanties BASIC quiA
est toujours 0. L'emplacement de(HL)
n'est pas garanti pour être sûr, et en fait, est probablement un endroit dangereux. Le code ci-dessous est beaucoup plus robuste, c'est pourquoi il est tellement plus long.Code machine Z80, 30 octets
En ASCII:
o!.ww.!>A=o>{))((}<o=A<!.ww.!o
Fondamentalement, la première moitié garantit la création d'une valeur nulle et la seconde moitié l'incrémente et l'écrit en mémoire. Dans la version développée ci-dessous
##
désigne un code qui ne sert à rien dans sa moitié du miroir.Répartition des instructions autorisées:
Sur les 39 instructions autorisées, 28 sont des opérations de chargement (le bloc de 0x40 à 0x7F sont toutes des
LD
instructions à un octet ), dont la plupart ne sont d'aucune utilité ici! La seule instruction de chargement en mémoire encore autorisée estLD (HL), A
ce qui signifie que je dois stocker la valeur dansA
. PuisqueA
c'est le seul registre qui reste avec uneINC
instruction autorisée , c'est en fait assez pratique!Je ne peux pas charger
A
avec 0x00 pour commencer car ASCII 0x00 n'est pas un caractère autorisé! Toutes les valeurs disponibles sont loin de 0 et toutes les instructions mathématiques et logiques ont été interdites! Sauf que ... je peux encore le faireADD HL, HL
, ajouter du 16 bitsHL
à lui - même! Hormis le chargement direct de valeurs (inutile ici!), INCrementingA
et DECrementingA
,L
ouHL
c'est la seule façon dont j'ai de changer la valeur d'un registre! Il y a en fait une instruction spécialisée qui pourrait être utile dans la première moitié mais une douleur à contourner dans la seconde moitié, et une instruction complémentaire qui est presque inutile ici et prendrait juste de la place.J'ai donc trouvé la valeur la plus proche de 0 que je pouvais: 0x41. Comment est-ce proche de 0? En binaire, c'est 0x01000001. Je le décrémente donc, le charge
L
et le faisADD HL, HL
deux fois!L
est maintenant nul, dans lequel je charge de nouveauA
! Malheureusement, le code ASCII pourADD HL, HL
est)
donc je dois maintenant utiliser(
deux fois. Heureusement,(
estJR Z, e
, oùe
est l'octet suivant. Donc, il engloutit le deuxième octet et je dois juste m'assurer qu'il ne fait rien en faisant attention auZ
drapeau! La dernière instruction pour affecter l'Z
indicateur a étéDEC A
(contre-intuitivement,ADD HL, HL
ne le change pas) et puisque je sais queA
c'était 0x40 à ce point, il est garanti que ceZ
n'est pas défini.La première instruction de la seconde moitié
JR Z, #28
ne fera rien les 255 premières fois car l'indicateur Z ne peut être défini que si A a dépassé de 255 à 0. Après cela, la sortie sera erronée, cependant, car elle ne sauvegarde de toute façon que des valeurs de 8 bits qui ne devrait pas avoir d'importance. Le code ne doit pas être développé plus de 255 fois.Le code doit être exécuté comme un extrait de code, car tous les moyens disponibles pour retourner proprement ont été interdits. Toutes les instructions RETurn sont supérieures à 0x80 et les quelques opérations de saut autorisées ne peuvent que passer à un décalage positif, car toutes les valeurs négatives à 8 bits ont également été interdites!
la source
A
registre est toujours à 8 bits, sinon le processeur ne serait pas compatible avec le Z80. Je dirais que suffisamment de mémoire et de puissance de calcul ont été couverts ici!A
registre autre que 8 bits? Le changer en 16 bits casserait le code en se basant sur 255 + 1 = 0 par exemple. Il faudrait inventer un processeur, appelons-le le Z160, qui utilise un registre 16 bits par défaut mais utilise toujours le même jeu d'instructions 8 bits que le Z80. Bizarre!J,
1614 octetsCoutumes:
Explication:
J évalue de droite à gauche.
(_=_)
estinf equals inf
ce qui est vrai, a une valeur de1
, donc l'expression devient1+]...[+1
. ((8=8)
ça marcherait aussi mais ça a l'air plus cool. :))[
et]
retourner leurs arguments gauche et droit respectivement s'ils ont 2 arguments. S'ils n'en obtiennent qu'un, ils le retournent.+
ajoute les 2 arguments. S'il n'en obtient qu'un, il le renvoie.Maintenant, évaluons une expression de niveau 3 (allant de droite à gauche):
Comme nous le voyons, la moitié droite du
1
's est ajoutée et le côté gauche du1
' s est omis, ce qui donne le nombre entier souhaitéN
, le niveau miroir.Essayez-le en ligne ici.
la source
Haskell, 42 octets
Heureusement, un commentaire de ligne dans Haskell (->
--
) peut être mis en miroir et la moitié (->-
) est une fonction valide. Le reste est un peu de mathématiques pour obtenir les chiffres0
et1
. Fondamentalement, nous avons(0)-(-1)
un commentaireN=0
et un préfixe(0)-(-1)-
à chaque étape.Si des nombres à virgule flottante sont autorisés pour la sortie, nous pouvons construire à
1
partir8/8
de 26 octets et nous en tirer:Haskell, 26 octets
Sorties
1.0
,2.0
etc.la source
program.hs
, puis exécuter à$ runhaskell program.hs
partir de la ligne de commande et voir la sortie. Je ne connais pas Haskell, donc je ne peux pas dire exactement ce qui doit changer.runhaskell
est un script shell qui configure un environnement et appelle finalementghc
le compilateur Haskell. Vous pouvez exécuter mon code directement avecghc
:ghc -e "(8-8)-(-8/8)--(8\8-)-(8-8)"
. Cela démarreghc
qui évalue le code fourni en argument, affiche le résultat et quitte. Pas de REPL, pas d'interaction. Bien sûr, cela ajouterait +1 au nombre d'octets pour-e
.-e
ne contribue pas au score dans ce cas. Nous ne comptons pas les octets pourperl -E
ougcc -std=c99
non.CJam, 14 octets
Essayez-le en ligne dans l'interpréteur CJam: N = 0 , N = 1 , N = 2 , N = 3 , N = 41
Notez que ce code se termine par un message d'erreur. À l'aide de l'interpréteur Java, ce message d'erreur peut être supprimé en fermant ou en redirigeant STDERR. 1
Comment ça marche
Dans les moitiés gauches, les événements suivants se produisent:
]
enveloppe la pile entière dans un tableau.X
ajoute1
à ce tableau.:+
calcule la somme de tous les éléments du tableau.Oo
affiche le contenu d'un tableau vide (c.-à-d. rien).Dans la première moitié droite, les événements suivants se produisent:
o
imprime l'entier sur la pile, qui est la sortie souhaitée.O+
tente d'ajouter un tableau vide à l'élément le plus haut de la pile.Cependant, la pile était vide avant de pousser
O
. Cela échoue et met fin à l'exécution du programme.Le code restant est simplement ignoré.
1 Selon le méta-sondage Les soumissions devraient-elles être autorisées à se terminer avec une erreur? , cela est autorisé.
la source