Schreiben Sie ein Programm, das seinen Spiegelpegel ausgibt

31

Es gibt 95 druckbare ASCII- Zeichen:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

In der Consolas-Schriftart (der Standardeinstellung für den Stack Exchange-Codeblock) haben einige der Zeichen Spiegel um eine vertikale Symmetrieachse:

  • Diese Zeichenpaare sind Spiegelbilder voneinander: () [] {} <> /\
  • Diese Zeichen sind Spiegel ihrer selbst: ! "'*+-.8:=AHIMOTUVWXY^_ovwx|(Beachten Sie, dass das Leerzeichen eins ist.)
  • Diese haben keine Spiegel: #$%&,012345679;?@BCDEFGJKLNPQRSZ`abcdefghijklmnpqrstuyz~

( i, l, 0, #, Und wahrscheinlich auch andere Zeichen sind , ihr eigener Spiegel in einigen Schriften , sondern wir werden die Consolas Formen bleiben.)

Eine Zeichenfolge wird als Spiegel ihrer selbst bezeichnet, wenn sie nur aus 39 Spiegelzeichen besteht , die so angeordnet sind, dass die Zeichenfolge eine vertikale Symmetrie-Mittellinie aufweist. So ](A--A)[ist ein Spiegel von sich selbst aber ](A--A(]nicht.

Schreiben Sie ein einzeiliges Programm mit gerader Länge, das ein Spiegelbild seiner selbst ist. Wenn ihm N Kopien seiner linken Hälfte vorangestellt und N Kopien seiner rechten Hälfte angehängt wurden, sollte er N + 1 ausgeben. N ist eine nicht negative ganze Zahl.

Wenn zum Beispiel das Programm ](A--A)[(linke Hälfte:, ](A-rechte Hälfte:) war -A)[, dann:

  • Laufen ](A--A)[sollte ausgeben 1. (N = 0)
  • Laufen ](A-](A--A)[-A)[sollte ausgeben 2. (N = 1)
  • Laufen ](A-](A-](A--A)[-A)[-A)[sollte ausgeben 3. (N = 2)
  • Laufen ](A-](A-](A-](A--A)[-A)[-A)[-A)[sollte ausgeben 4. (N = 3)
  • . . .
  • Laufen ](A-](A-](A-](A-](A-](A-](A-](A-](A-](A--A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[sollte ausgeben 10. (N = 9)
  • etc.

Regeln

  • Ausgabe auf stdout oder die nächstgelegene Alternative Ihrer Sprache. Es kann eine optionale nachgestellte Newline geben. Es sollten keine Eingaben gemacht werden.
  • Der Prozess sollte theoretisch für N bis zu 2 15 -1 oder mehr funktionieren , vorausgesetzt, dass genügend Speicher und Rechenleistung vorhanden sind.
  • Ein vollständiges Programm ist erforderlich, nicht nur ein REPL- Befehl.

Das kürzeste Anfangsprogramm (Fall N = 0) in Bytes gewinnt.

Calvins Hobbys
quelle
In einigen Schriftarten #ist dies auch eine eigene Relektion, aber Sie haben Recht, nicht in Konsolen.
SuperJedi224
1
Die Verwendung von Antworten ist zulässig? Mit anderen Worten: Sollen wir ein vollständig gültiges Programm schreiben oder reicht ein Ausdruck aus? Ich denke über den Haskell-Eintrag nach, der funktionieren würde, wenn er in ghci ausgeführt wird, aber kein gültiges vollständiges Programm ist.
Bakuriu
@ Bakuriu Ein vollständiges Programm ist erforderlich. Die Haskell-Antwort ist ungültig.
Calvins Hobbys
4
Warum sind 'b' und 'd' keine Spiegel voneinander? Das macht meinen Plan unmöglich: P
Thijs ter Haar
1
@ThijsterHaar Ich hielt eigentlich nicht so , aber es sieht aus wie ihre Consolas Formen sind nur etwas anders, sorry: P
Calvins Hobbys

Antworten:

20

Pip, 12 8 4 Bytes

Jetzt mit 66% weniger Bytes!

x++x
  • xist eine Variable, vorinitialisiert für "". Im numerischen Kontext wird dies 0.
  • Die erste Halbzeit ohne Finale +ist Ausdruck der Form x+x+...+x. Dies ist eine gültige Aussage, die nichts bewirkt.
  • Die zweite Hälfte, einschließlich des Finales +aus der ersten Hälfte, ist Ausdruck der Form ++x+x+...+x. ++xerhöht sich xauf 1, und der Rest addiert sich N-mal. Da Ausdrücke in Pip von links nach rechts ausgewertet werden, wird das Inkrement garantiert zuerst ausgeführt und das Ergebnis entspricht der Anzahl der Spiegelebenen.
  • Am Ende wird der Wert dieses Ausdrucks automatisch gedruckt.

Leider kann Pip große Ausdrücke nicht gut verarbeiten: Diese Lösung verursacht einen maximum recursion depth exceededFehler für N über 500 oder so. Hier ist eine frühere Lösung, die dies für 8 Bytes nicht tut :

x++oo++x

Mehr zu Pip

DLosc
quelle
OK, es sei denn, jemand sendet eine 2-Byte-Antwort. Sieht so aus, als hätten Sie diese in der Tasche. Ich weiß übrigens nicht, ob Sie es mit N = 32767 ausgeführt haben , aber die tatsächliche Ausgabe ist Fatal error: maximum recursion depth exceeded while calling a Python object.
Dennis
@Dennis Ja, ich bin tatsächlich darauf gestoßen - es beginnt ziemlich früh, ungefähr 600, wenn nicht vorher. Der Grund dafür ist, dass Ausdrücke ausgewertet werden, indem zuerst alle Unterausdrücke rekursiv ausgewertet werden, wodurch die x+x+...+xRekursionstiefe O (N) generiert wird. Vielleicht macht das diese Antwort ungültig. Ich werde eine Notiz hinzufügen.
DLosc
Das Rekursionslimit ist in Python leicht einstellbar, nicht wahr?
Dennis
@Dennis Ja, obwohl es ernsthafte Warnungen darüber gibt, was mit Ihrem System geschehen wird, wenn Sie es zu hoch einstellen. Deshalb habe ich es nie ausprobiert. ;) Außerdem ist die Konfiguration in Pip nicht möglich , daher kommt es mir irgendwie wie Betrug vor. Wenn Sie es dennoch versuchen möchten, wären Sie an den Ergebnissen interessiert.
DLosc
Ich habe es versucht. Auf meinem Computer schlägt die Erhöhung des Rekursionslimits auf 20000 bereits fehl. Aber da die Antwort nur bei genügend Arbeitsspeicher und Rechenleistung funktionieren muss, sollte das kein Problem sein.
Dennis
34

GolfScript, 10 Bytes

!:{)::(}:!

Probieren Sie es online mit Web Golfscript aus: N = 0 , N = 1 , N = 2 , N = 3 , N = 41

Web GolfScript ist auf 1024 Zeichen beschränkt, der Ruby-Interpreter verarbeitet N = 32767 jedoch perfekt:

$ curl -Ss http://www.golfscript.com/golfscript/golfscript.rb > golfscript.rb
$ echo '"!:{):"32768*":(}:!"32768*' | ruby golfscript.rb > mirror-level-32767.gs
$ ruby golfscript.rb mirror-level-32767.gs
32768

Wie es funktioniert

Ohne Eingabe hat GolfScript zunächst eine leere Zeichenfolge auf dem Stapel.

In der ersten linken Hälfte passiert folgendes:

  • !Wendet logisches NICHT auf die leere Zeichenfolge an. Das drängt 1.

  • :{speichert die ganze Zahl auf dem Stapel in der Variablen {.

    Ja, das ist eine gültige ID, obwohl der gespeicherte Wert nicht abgerufen werden kann.

  • ) erhöht die Ganzzahl auf dem Stapel.

  • : ist eine unvollständige Anweisung.

In den folgenden linken Hälften passiert Folgendes:

  • :!(wo :ist ein Rest von vorher) speichert die ganze Zahl auf dem Stapel in der Variablen !.

    Ja, das ist auch eine gültige Kennung. Dadurch wird der !Befehl abgebrochen, aber wir verwenden ihn nicht mehr.

  • :{, )Und :arbeiten wie zuvor.

In der ersten rechten Hälfte passiert folgendes:

  • ::(wo :ist ein Rest von vorher) speichert die ganze Zahl auf dem Stapel in der Variablen :.

    Ja, auch das ist eine gültige Kennung. Wie bei {gibt es keine Möglichkeit, den gespeicherten Wert abzurufen.

  • ( dekrementiert die Ganzzahl auf dem Stapel und ergibt die Anzahl der linken Hälften.

  • }, da es nicht übereinstimmt und die Ausführung sofort beendet.

    Dies ist eine undokumentierte Funktion. Ich nenne sie Superkommentare .

Der verbleibende Code wird einfach ignoriert.

Dennis
quelle
Es scheint wirklich seltsam, }in einem Spiegelwettbewerb einen in der zweiten Hälfte Ihres Codes unerreichten Code zu haben .
ballesta25
Dies ist ein häufiger Trick bei Palindrom-Varianten. In "\""/"würden die vierten doppelten Anführungszeichen als auch unübertroffen, da die zweiten entgangen war.
Dennis
27

Z80 Maschinencode, 8 6 Bytes *

<8ww8> * Unter bestimmten Bedingungen von Amstrad BASIC eingeben

<   INC A         // A=A+1
8w  JR C, #77     ## C is unset unless A has overflowed, does nothing

w   LD (HL), A    // Saves A to memory location in HL (randomly initialised)
8>  JR C, #3E     ## C is still unset, does nothing

Aist anfangs 0, wenn von BASIC eingegeben. Es wird A n- mal inkrementiert und dann n- mal an denselben Speicherort geschrieben (der von BASIC auf einen leicht zufälligen Speicherort festgelegt wurde)! Die JROperation "Relativ springen" führt zu keinem Ergebnis, da das CFlag immer nicht gesetzt ist. Daher wird das folgende Byte "auskommentiert". Diese Version schummelt leicht, wenn bestimmte Einreisebedingungen vorausgesetzt werden, nämlich, dass die Einreise aus den BASIC-Garantien Aimmer 0 (HL)ist. Der folgende Code ist viel robuster, weshalb er viel länger ist.

Z80-Maschinencode, 30 Byte

Als ASCII: o!.ww.!>A=o>{))((}<o=A<!.ww.!o

Grundsätzlich garantiert die erste Hälfte die Erzeugung eines Nullwerts und die zweite Hälfte erhöht ihn und schreibt ihn in den Speicher. In der erweiterten Version ##bezeichnet unten Code, der in seiner Hälfte des Spiegels keinen Zweck erfüllt.

o   LD L, A       ## 
!.w LD HL, #772E  // Load specific address to not corrupt random memory!
w   LD (HL), A    ## Save random contents of A to memory
.!  LD L, #21     ## 
>A  LD A, #41     // A=#41
=   DEC A         // A=#40
o   LD L, A       // L=#40
>{  LD A, #7B     ## 
)   ADD HL, HL    // HL=#EE80
)   ADD HL, HL    // HL=#DD00. L=#00 at this point

((  JR Z, #28     ## 
}   LD A, L       // A=L
<   INC A         // A=L+1
o   LD L, A       // L=L+1
=   DEC A         // A=L
A   LD B, C       ## 
<   INC A         // A=L+1
!.w LD HL, #772E  // Load address back into HL
w   LD (HL), A    // Save contents of A to memory
.!  LD L, #21     ## 
o   LD L, A       // L=A

Aufschlüsselung der erlaubten Anweisungen:

n   op    description
--  ----  -----------
28  LD    LoaD 8-bit or 16-bit register
3   DEC   DECrement 8-bit or 16-bit register
1   INC   INCrement 8-bit or 16-bit register
1   ADD   ADD 8-bit or 16-bit register

Available but useless instructions:
3   JR    Jump Relative to signed 8-bit offset
1   DAA   Decimal Adjust Accumulator (treats the A register as two decimal digits
          instead of two hexadecimal digits and adjusts it if necessary)
1   CPL   1s ComPLement A
1   HALT  HALT the CPU until an interrupt is received

Von den 39 zulässigen Befehlen sind 28 Ladeoperationen (die Blöcke von 0x40 bis 0x7F sind alle Einzelbyte- LDBefehle), von denen die meisten hier keine Hilfe sind! Die einzige Anweisung LD (HL), Azum Laden in den Speicher, die noch zulässig ist , bedeutet, dass ich den Wert in speichern muss A. Da dies Adas einzige Register ist, in dem eine INCAnweisung zulässig ist , ist dies praktisch.

Ich kann nicht Amit 0x00 beginnen, da ASCII 0x00 kein zulässiges Zeichen ist! Alle verfügbaren Werte sind weit von 0 entfernt und alle mathematischen und logischen Anweisungen wurden nicht zugelassen! Außer ... ich kann immer ADD HL, HLnoch 16-Bit HLzu sich selbst hinzufügen ! Abgesehen vom direkten Laden von Werten (hier keine Verwendung!), Dem Inkrementieren Aund Dekrementieren A, Loder HLnur so kann ich den Wert eines Registers ändern! Es gibt tatsächlich eine spezielle Anweisung, die in der ersten Hälfte hilfreich sein könnte, aber in der zweiten Hälfte ein Problem, das umgangen werden muss, und eine ergänzende Anweisung, die hier fast nutzlos ist und nur Platz beansprucht.

Also fand ich den nächsten Wert zu 0, den ich finden konnte: 0x41. Wie ist das nahe bei 0? In der Binärdatei ist es 0x01000001. Also dekrementiere ich es, lade es hinein Lund mache es ADD HL, HLzweimal! List jetzt null, in die ich wieder lade A! Leider für den ASCII - Code ADD HL, HList )so ich jetzt verwenden müssen (zweimal. Zum Glück (ist JR Z, e, wo eist das nächste Byte. Also verschlingt es das zweite Byte und ich muss nur sicherstellen, dass es nichts tut, indem ich vorsichtig mit der ZFlagge bin ! Die letzte Anweisung, die das ZFlag beeinflusste, war DEC A( ADD HL, HLnicht intuitiv zu ändern) und da ich weiß, dass Aes zu diesem Zeitpunkt 0x40 war, ist garantiert, dass Zes nicht gesetzt ist.

Die erste Anweisung in der zweiten Hälfte JR Z, #28wird die ersten 255-mal nichts tun, da das Z-Flag nur gesetzt werden kann, wenn A von 255 auf 0 übergelaufen ist. Danach ist die Ausgabe jedoch falsch, da ohnehin nur 8-Bit-Werte gespeichert werden sollte keine Rolle spielen. Der Code sollte nicht mehr als 255 Mal erweitert werden.

Der Code muss als Snippet ausgeführt werden, da alle verfügbaren Methoden zur sauberen Rückgabe nicht zugelassen wurden. Alle RETurn-Befehle liegen über 0x80 und die wenigen erlaubten Sprungoperationen können nur zu einem positiven Offset springen, da auch alle negativen 8-Bit-Werte nicht erlaubt wurden!

CJ Dennis
quelle
6
WAS. WAS IST DAS.
Cloudfeet
4
Jetzt habe ich diese Antwort mit GolfScript / J / etc gesehen. scheint nur zu schummeln. : p
cloudfeet
Gibt es Z80-kompatible Prozessoren mit einem 16-Bit-A-Register? Ich frage , da die Frage erfordert, dass der Code für N = 32767 funktionieren muss .
Dennis
1
@Dennis Damit ein Programm für N = 32767 funktioniert , muss es mindestens 2 x 32767 oder 65534 Byte lang sein. Der Z80 kann nur 65536 Bytes Speicher adressieren, was dies zu einer unmöglichen Aufgabe macht, da ich nicht glaube, dass ich das Programm kleiner als 6 Bytes machen kann! Das ARegister ist immer 8 Bit, sonst wäre der Prozessor nicht mit dem Z80 kompatibel. Ich würde sagen, dass bei genügend Arbeitsspeicher und Rechenleistung hier abgedeckt wurde!
CJ Dennis
1
@Dennis Verstehst du, warum kein Z80-kompatibler Prozessor ein ARegister mit etwas anderem als 8 Bits hat? Das Ändern in 16-Bit würde zum Beispiel einen Code unterbrechen, der sich auf 255 + 1 = 0 stützt . Sie müssten eine CPU erfinden, nennen wir sie die Z160, die ein Standard-16-Bit-Register verwendet, aber immer noch denselben 8-Bit-Befehlssatz wie die Z80 verwendet. Seltsam!
CJ Dennis
19

J, 16 14 Bytes

(_=_)]++[(_=_)

Verwendungen:

   (_=_)]++[(_=_)
1
   (_=_)]+(_=_)]++[(_=_)+[(_=_)
2
   (_=_)]+(_=_)]+(_=_)]++[(_=_)+[(_=_)+[(_=_)
3

Erläuterung:

  • J wertet von rechts nach links aus.

  • (_=_)Ist inf equals infdas, was wahr ist, hat einen Wert von 1, so wird der Ausdruck 1+]...[+1. ( (8=8)würde auch funktionieren aber das sieht cooler aus. :))

  • [und ]geben die Argumente left und right zurück, wenn sie 2 Argumente haben. Wenn sie nur 1 bekommen, geben sie das zurück.

  • +fügt die 2 Argumente hinzu. Wenn es nur 1 bekommt, gibt es das zurück.

Bewerten wir nun einen Ausdruck der Ebene 3 (von rechts nach links):

(_=_)]+(_=_)]++[(_=_)+[(_=_)  NB. (_=_) is 1

1]+1]+1]++[1+[1+[1  NB. unary [, binary +

1]+1]+1]++[1+[2  NB. unary [, binary +

1]+1]+1]++[3  NB. unary [, unary +

1]+1]+1]+3  NB. unary +, binary ]

1]+1]+3  NB. unary +, binary ]

1]+3  NB. unary +, binary ]

3

Wie wir sehen, wird die rechte Hälfte der 1's addiert und die linke Seite der 1' s weggelassen, was die gewünschte Ganzzahl ergibt N, die Spiegelebene.

Probieren Sie es hier online aus.

randomra
quelle
12

Haskell, 42 Bytes

(8-8)-(-(8-8)^(8-8))--((8-8)^(8-8)-)-(8-8)

Glücklicherweise --ist ein Zeilenkommentar in Haskell (-> ) spiegelbar und die Hälfte davon (-> -) ist eine gültige Funktion. Der Rest ist ein bisschen Mathe, um die Zahlen 0und zu bekommen 1. Grundsätzlich müssen wir bei jedem Schritt (0)-(-1)einen Kommentar für N=0und voranstellen (0)-(-1)-.

Wenn Gleitkommazahlen für die Ausgabe erlaubt sind, können wir bauen 1aus 8/8und kommen mit 26 Bytes:

Haskell, 26 Bytes

(8-8)-(-8/8)--(8\8-)-(8-8)

Ausgänge 1.0, 2.0usw.

nimi
quelle
2
Dies ist technisch ungültig, da es sich um ein vollständiges Programm handeln muss.
Calvins Hobbys
@ Calvin'sHobbies: Ich verstehe. Haben wir einen Konsens über die Mindestanforderungen für ein vollständiges Programm? Ich habe nach Meta gesucht, aber nur eine Diskussion über Funktionen gefunden, nicht über Programme. Abhängig von der Definition eines vollständigen Programms kann ich möglicherweise meine Lösung reparieren.
nimi
Ich würde es als vollständiges Programm bezeichnen, wenn Sie es in einer Datei speichern program.hsund dann $ runhaskell program.hsüber die Befehlszeile ausführen und die Ausgabe sehen können. Ich kenne Haskell nicht und kann daher nicht genau sagen, was sich ändern muss.
Calvins Hobbys
2
@ Calvin'sHobbies: runhaskellist ein Shell-Skript, das eine Umgebung einrichtet und schließlich ghcden Haskell-Compiler aufruft . Sie können meinen Code direkt mit ausführen ghc: ghc -e "(8-8)-(-8/8)--(8\8-)-(8-8)". Dadurch wird gestartet ghc, der als Argument bereitgestellte Code ausgewertet, das Ergebnis gedruckt und beendet. Keine REPL, keine Interaktion. Dies würde natürlich +1 zur Byteanzahl für hinzufügen -e.
nimi
@nimi: Trägt -ein diesem Fall nicht zur Bewertung bei. Wir zählen keine Bytes für perl -Eoder gcc -std=c99.
Dennis
11

CJam, 14 Bytes

]X+:+OooO+:+X[

Probieren Sie es online im CJam-Interpreter aus: N = 0 , N = 1 , N = 2 , N = 3 , N = 41

Beachten Sie, dass dieser Code mit einer Fehlermeldung endet. Mit dem Java-Interpreter kann diese Fehlermeldung unterdrückt werden, indem STDERR geschlossen oder umgeleitet wird. 1

Wie es funktioniert

In den linken Hälften passiert Folgendes:

  • ] Wickelt den gesamten Stapel in ein Array.

  • Xhängt 1an dieses Array an.

  • :+ berechnet die Summe aller Array-Elemente.

  • Oo druckt den Inhalt eines leeren Arrays (dh nichts).

In der ersten rechten Hälfte passiert folgendes:

  • o druckt die ganze Zahl auf den Stapel, die die gewünschte Ausgabe ist.

  • O+ versucht, ein leeres Array an das oberste Element des Stapels anzuhängen.

    Der Stapel war jedoch vor dem Schieben leer O. Dies schlägt fehl und beendet die Ausführung des Programms.

Der verbleibende Code wird einfach ignoriert.

1 Laut Meta-Umfrage sollten Einsendungen mit einem Fehler beendet werden dürfen? , das ist erlaubt.

Dennis
quelle
Ich würde dies aufgrund des Fehlers skeptisch annehmen, aber da es nicht gewinnt, mache ich mir keine Sorgen.
Calvins Hobbys
Aufgaben wie diese sind in CJam überraschend schwierig, wenn man bedenkt, dass es sich um eine Golfsprache handelt. Selbst ein Syntaxfehler (z. B. ein nicht definierter Operator) in einem nicht ausgeführten Block verhindert, dass das gesamte Programm ausgeführt wird. Ich versuche immer noch, den Fehler loszuwerden.
Dennis