Scrivi un programma che emette il suo livello di mirroring


31

Esistono 95 caratteri ASCII stampabili :

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

Nel carattere Consolas (il blocco di codice Stack Exchange predefinito), alcuni dei caratteri hanno specchi attorno ad un asse verticale di simmetria:

  • Queste coppie di personaggi si specchiano: () [] {} <> /\
  • Questi personaggi sono specchi di se stessi: ! "'*+-.8:=AHIMOTUVWXY^_ovwx|(Nota che lo spazio è uno.)
  • Questi non hanno mirror: #$%&,012345679;?@BCDEFGJKLNPQRSZ`abcdefghijklmnpqrstuyz~

( i, l, 0, #, E probabilmente altri personaggi sono i propri specchi in alcuni tipi di carattere, ma ti attaccano alle forme Consolas.)

Si dice che una stringa è uno specchio di se stessa se è fatta solo con i 39 caratteri speculari , disposti in modo tale che la stringa abbia una linea verticale centrale di simmetria. Quindi ](A--A)[è uno specchio di se stesso ma ](A--A(]non lo è.

Scrivi un programma di lunghezza pari di una riga che è uno specchio di se stesso. Quando N copie della sua metà sinistra le sono state anteposte e N copie della sua metà destra le sono state aggiunte, dovrebbe produrre N + 1. N è un numero intero non negativo.

Ad esempio, se il programma era ](A--A)[(metà sinistra:, ](A-metà destra:) -A)[, quindi:

  • L'esecuzione ](A--A)[dovrebbe essere in uscita 1. (N = 0)
  • L'esecuzione ](A-](A--A)[-A)[dovrebbe essere in uscita 2. (N = 1)
  • L'esecuzione ](A-](A-](A--A)[-A)[-A)[dovrebbe essere in uscita 3. (N = 2)
  • L'esecuzione ](A-](A-](A-](A--A)[-A)[-A)[-A)[dovrebbe essere in uscita 4. (N = 3)
  • . . .
  • L'esecuzione ](A-](A-](A-](A-](A-](A-](A-](A-](A-](A--A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[-A)[dovrebbe essere in uscita 10. (N = 9)
  • eccetera.

Regole

  • Invia a stdout o l'alternativa più vicina alla tua lingua. Potrebbe esserci una nuova riga finale opzionale. Nessun input dovrebbe essere preso.
  • Il processo dovrebbe teoricamente funzionare per N fino a 2 15 -1 o oltre, con memoria e potenza di calcolo sufficienti.
  • È richiesto un programma completo, non solo un comando REPL .

Vince il programma iniziale più breve (caso N = 0) in byte.


In alcuni tipi di carattere, #è presente anche il suo riferimento, ma, hai ragione, non nelle console.
SuperJedi224,

1
È consentito l'utilizzo di sostituti? In altre parole: dovremmo scrivere un programma completo valido o un'espressione è sufficiente? Sto pensando alla voce di Haskell che funzionerebbe durante l'esecuzione in ghci ma non è un programma completo valido.
Bakuriu,

@Bakuriu È richiesto un programma completo. La risposta di Haskell non è valida.
Hobby di Calvin

4
Perché non sono specchi "b" e "d" l'uno dell'altro? Rende impossibile il mio piano: P
Thijs ter Haar,

1
@ThijsterHaar In realtà non l'ho preso in considerazione, ma sembra che le loro forme di Consolas siano leggermente diverse, mi dispiace: P
Calvin's Hobbies

Risposte:


20

Pip, 12 8 4 byte

Ora con il 66% di byte in meno!

x++x
  • xè una variabile, preinizializzata in "". In un contesto numerico, questo diventa 0.
  • La prima metà, senza il finale +, esprime la forma x+x+...+x. Questa è un'affermazione valida che non fa nulla.
  • La seconda metà, compreso il finale +della prima metà, esprime la forma ++x+x+...+x. ++xaumenta xa 1, e il resto lo aggiunge a se stesso N volte. Poiché le espressioni vengono valutate da sinistra a destra in Pip, l'incremento è garantito per primo e il risultato è uguale al numero di livelli mirror.
  • Alla fine, il valore di questa espressione viene stampato automaticamente.

Sfortunatamente, Pip non fa bene l'elaborazione di espressioni enormi: questa soluzione provoca un maximum recursion depth exceedederrore per N superiore a circa 500. Ecco una soluzione precedente che non funziona, per 8 byte :

x++oo++x

Altro su Pip


OK, a meno che qualcuno non pubblichi una risposta a 2 byte, sembra che tu abbia questo nella borsa. A proposito, non so se l'hai eseguito con N = 32767 , ma l'output effettivo è Fatal error: maximum recursion depth exceeded while calling a Python object.
Dennis,

@Dennis Sì, in realtà mi sono imbattuto in quello - inizia abbastanza presto, circa 600 se non prima. Il motivo è che le espressioni vengono valutate valutando ricorsivamente prima tutte le sottoespressioni, quindi x+x+...+xgenera la profondità O (N) della ricorsione. Forse questo invalida questa risposta. Aggiungerò una nota.
DLosc,

Il limite di ricorsione è facilmente regolabile in Python, non è vero?
Dennis,

@Dennis Sì, anche se ci sono avvertimenti terribili su cosa farà al tuo sistema se lo imposti troppo in alto, quindi non l'ho mai provato. ;) Inoltre, configurarlo non è possibile all'interno di Pip , quindi mi sembra un po 'come imbrogliare. Se vuoi provarlo, comunque, sarei interessato a sentire i risultati.
DLosc,

Ho provato. Sulla mia macchina, aumentando il limite di ricorsione a 20000 già segfault. Ma poiché la risposta deve funzionare solo con memoria e potenza di elaborazione sufficienti , questo non dovrebbe essere un problema.
Dennis,

34

GolfScript, 10 byte

!:{)::(}:!

Provalo online con Web Golfscript: N = 0 , N = 1 , N = 2 , N = 3 , N = 41

Web GolfScript ha un limite di 1024 caratteri, ma l'interprete Ruby gestisce perfettamente N = 32767 :

$ 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

Come funziona

Senza alcun input, GolfScript inizialmente ha una stringa vuota nello stack.

Nella prima metà sinistra, succede quanto segue:

  • !applica il NOT logico alla stringa vuota. Questo spinge 1.

  • :{salva il numero intero nello stack nella variabile {.

    Sì, questo è un identificatore valido, sebbene non sia possibile recuperare il valore memorizzato.

  • ) incrementa il numero intero nello stack.

  • : è un'istruzione incompleta.

Le successive metà sinistra, succede quanto segue:

  • :!(dove :è un avanzi di prima) salva il numero intero nello stack nella variabile !.

    Sì, anche questo è un identificatore valido. Questo interrompe il !comando, ma non lo usiamo più.

  • :{, )E :il lavoro come prima.

Nella prima metà destra, succede quanto segue:

  • ::(dove :è un avanzi di prima) salva il numero intero nello stack nella variabile :.

    Sì, anche quello è un identificatore valido. Come con {, non c'è modo di recuperare il valore memorizzato.

  • ( decrementa il numero intero nello stack, producendo il numero di metà sinistra.

  • }, poiché non ha eguali e termina immediatamente l'esecuzione.

    Questa è una funzionalità non documentata. Li chiamo supercommenti .

Il codice rimanente viene semplicemente ignorato.


Sembra davvero strano avere un impareggiabile }nella seconda metà del codice in una competizione speculare.
ballesta25,

È un trucco comune nelle varianti di palindromo. In "\""/", la quarta doppia virgoletta non avrebbe eguali poiché la seconda è stata salvata.
Dennis,

27

Codice macchina Z80, 8 6 byte *

<8ww8> * Presuppone determinate condizioni entrando da Amstrad BASIC

<   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

Aè inizialmente 0 quando inserito da BASIC. Aumenta A n volte, quindi la scrive n volte nella stessa posizione di memoria (che è impostata su una posizione leggermente casuale da BASIC)! L' JRoperazione Jump Relative non fa mai nulla poiché il Cflag è sempre non impostato, quindi viene utilizzato per "commentare" il seguente byte! Questa versione è leggermente ingannevole assumendo determinate condizioni di accesso, vale a dire entrare da garanzie BASIC che Asono sempre 0. La posizione di (HL)non è garantita per essere sicura, e in effetti, è probabilmente una posizione pericolosa. Il codice seguente è molto più robusto ed è per questo che è molto più lungo.

Codice macchina Z80, 30 byte

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

Fondamentalmente, la prima metà garantisce la creazione di un valore zero e la seconda metà lo incrementa e lo scrive in memoria. Nella versione estesa di seguito ##indica il codice che non serve a nulla nella sua metà del mirror.

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

Ripartizione delle istruzioni consentite:

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

Delle 39 istruzioni consentite, 28 sono operazioni di caricamento (il blocco da 0x40 a 0x7F sono tutte LDistruzioni a byte singolo ), la maggior parte delle quali non sono di aiuto qui! L'unico caricamento ancora consentito nella memoria è il LD (HL), Ache significa che devo memorizzare il valore A. Poiché Aè l'unico registro rimasto con un'istruzione consentita INC, questo è in realtà abbastanza utile!

Non posso caricare Acon 0x00 per cominciare perché ASCII 0x00 non è un carattere consentito! Tutti i valori disponibili sono lontani da 0 e tutte le istruzioni matematiche e logiche sono state vietate! Tranne ... posso ancora fare ADD HL, HL, aggiungere 16 bit HLa se stesso! Oltre a caricare direttamente i valori (non usare qui!), INCrementare Ae DECrementare A, Lo HLquesto è l'unico modo che ho di cambiare il valore di un registro! Esiste in realtà un'istruzione specializzata che potrebbe essere utile nella prima metà, ma una seccatura da risolvere nella seconda metà, e un'istruzione a complemento a uno che è quasi inutile qui e occuperebbe solo spazio.

Quindi, ho trovato il valore più vicino a 0 che potevo: 0x41. Quanto è vicino a 0? In binario è 0x01000001. Quindi lo decremento, lo carico Le lo faccio ADD HL, HLdue volte! Lè ora zero, che carico nuovamente A! Sfortunatamente, il codice ASCII per ADD HL, HLè )quindi ora devo usare (due volte. Fortunatamente, (è JR Z, e, dov'è eil byte successivo. Quindi divora il secondo byte e devo solo assicurarmi che non faccia nulla facendo attenzione con la Zbandiera! L'ultima istruzione per influenzare la Zbandiera è stata DEC A(controintuitivamente, ADD HL, HLnon la modifica) e poiché so che Aera 0x40 a quel punto è garantito che Znon è impostato.

La prima istruzione nella seconda metà JR Z, #28non farà nulla le prime 255 volte perché il flag Z può essere impostato solo se A ha traboccato da 255 a 0. Successivamente, l'output sarà errato, tuttavia dal momento che sta salvando comunque solo valori a 8 bit che non dovrebbe importare. Il codice non deve essere espanso più di 255 volte.

Il codice deve essere eseguito come frammento poiché tutti i modi disponibili per restituire in modo pulito sono stati vietati. Tutte le istruzioni RETurn sono superiori a 0x80 e le poche operazioni Jump consentite possono saltare solo a un offset positivo, poiché anche tutti i valori negativi a 8 bit sono stati vietati!


6
CHE COSA. COS'È QUESTO.
cloudfeet,

4
Ora ho visto questa risposta, usando GolfScript / J / etc. sembra solo barare. : p
cloudfeet,

Esistono processori compatibili Z80 con un registro A a 16 bit? Sto chiedendo poiché la domanda richiede che il codice funzioni per N = 32767 .
Dennis,

1
@Dennis Affinché un programma funzioni con N = 32767 , deve essere lungo almeno 2 x 32767 o 65534 byte. Lo Z80 può indirizzare solo 65536 byte di memoria, rendendo questo un compito impossibile poiché non credo di poter rendere il programma più piccolo di 6 byte! Il Aregistro ha sempre 8 bit, altrimenti il ​​processore non sarebbe compatibile con lo Z80. Direi che a causa della memoria e della potenza di calcolo sufficienti è stata coperta qui!
CJ Dennis,

1
@Dennis Capisci perché nessun processore compatibile con Z80 avrà un Aregistro di qualcosa di diverso da 8 bit? Modificandolo in 16 bit, si spezzerebbe il codice basandosi, ad esempio, su 255 + 1 = 0. Dovresti inventare una CPU, chiamiamola Z160, che utilizza un registro predefinito a 16 bit ma utilizza ancora lo stesso set di istruzioni a 8 bit dello Z80. Strano!
CJ Dennis,

19

J, 16 14 byte

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

usi:

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

Spiegazione:

  • J valuta da destra a sinistra.

  • (_=_)è ciò inf equals infche è vero, ha un valore di 1, quindi l'espressione diventa 1+]...[+1. ( (8=8)Funzionerebbe anche ma questo sembra più bello. :))

  • [e ]restituiscono rispettivamente i loro argomenti left e right se hanno 2 argomenti. Se ottengono solo 1, lo restituiscono.

  • +aggiunge i 2 argomenti. Se ottiene solo 1, lo restituisce.

Ora valutiamo un'espressione di livello 3 (che va da destra a sinistra):

(_=_)]+(_=_)]++[(_=_)+[(_=_)  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

Come vediamo la metà destra di quella 1viene aggiunta e la parte sinistra di quella 1viene omessa risultando nel numero intero desiderato N, il livello mirror.

Provalo online qui.


12

Haskell, 42 byte

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

Fortunatamente un commento di riga in Haskell (-> --) è speculare e metà (-> -) è una funzione valida. Il resto è un po 'di matematica per ottenere i numeri 0e 1. Fondamentalmente abbiamo (0)-(-1)un commento N=0e anteporre (0)-(-1)-ad ogni passaggio.

Se i numeri in virgola mobile sono permessi per l'output, possiamo costruire 1da 8/8e cavarsela con 26 byte:

Haskell, 26 byte

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

Le uscite 1.0, 2.0ecc


2
Questo non è tecnicamente valido poiché deve essere un programma completo.
Calvin's Hobbies,

@ Calvin'sHobbies: Capisco. Abbiamo consenso sui requisiti minimi per un programma completo? Ho cercato meta, ma ho trovato solo una discussione sulle funzioni, non sui programmi. A seconda della definizione di un programma completo, potrei essere in grado di risolvere la mia soluzione.
nimi,

Lo chiamerei un programma completo se potessi salvarlo in un file program.hse quindi eseguirlo $ runhaskell program.hsdalla riga di comando e vedere l'output. Non conosco Haskell, quindi non posso dire esattamente cosa debba cambiare.
Calvin's Hobbies,

2
@ Calvin'sHobbies: runhaskellè uno script di shell che imposta un ambiente e infine chiama ghc, il compilatore di Haskell. È possibile eseguire il mio codice direttamente con ghc: ghc -e "(8-8)-(-8/8)--(8\8-)-(8-8)". Questo avvia ghcche valuta il codice fornito come argomento, stampa il risultato ed esce. Nessuna REPL, nessuna interazione. Naturalmente questo aggiungerebbe +1 al conteggio dei byte per -e.
nimi,

@nimi: -ein questo caso non contribuisce al punteggio. Non contiamo byte perl -Ené per gcc -std=c99nessuno dei due.
Dennis,

11

CJam, 14 byte

]X+:+OooO+:+X[

Provalo online nell'interprete CJam: N = 0 , N = 1 , N = 2 , N = 3 , N = 41

Si noti che questo codice termina con un messaggio di errore. Usando l'interprete Java, quel messaggio di errore può essere soppresso chiudendo o reindirizzando STDERR. 1

Come funziona

A metà sinistra, accade quanto segue:

  • ] avvolge l'intero stack in un array.

  • Xaggiunge 1a quell'array.

  • :+ calcola la somma di tutti gli elementi dell'array.

  • Oo stampa il contenuto dell'array vuoto (ovvero nulla).

Nella prima metà destra, succede quanto segue:

  • o stampa l'intero sulla pila, che è l'output desiderato.

  • O+ tenta di aggiungere un array vuoto all'elemento più in alto dello stack.

    Tuttavia, lo stack era vuoto prima di spingere O. Questo non riesce e termina l'esecuzione del programma.

Il codice rimanente viene semplicemente ignorato.

1 Secondo il meta sondaggio Le presentazioni devono essere autorizzate a uscire con un errore? , questo è permesso.


Sarei scettico nell'accettare questo a causa dell'errore, ma dal momento che non sta vincendo non sono troppo preoccupato.
Calvin's Hobbies,

Compiti come questo sono sorprendentemente difficili in CJam, considerando che è un linguaggio da golf. Anche un errore di sintassi (ad es. Un operatore non definito) in un blocco non eseguito impedirà l'esecuzione dell'intero programma. Sto ancora cercando di eliminare l'errore.
Dennis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.