Questo programma è pieno di caratteri non stampabili, quindi ecco un hexdump:
00000000: 2573 dc01 7e13 dcb6 1f %s..~....
Nota: utilizza una routine di input numerico che non è in grado di inserire numeri negativi, quindi questo invio è limitato solo a numeri interi non negativi.
Un problema con le sfide di poliziotti e ladri è che non scrivi spiegazioni sul codice (per rendere più difficile decifrare). D'altra parte, ciò significa che qui non devo andare ai guai.
Ho scelto 7 come lingua perché, specialmente nella sua notazione compressa, è piuttosto difficile da leggere, e non vedo perché dovrei essere solo io a dover affrontare il problema di spostare blocchi di programmi a 8 bit scritti in una codifica a 3 bit. In bocca al lupo!
Spiegazione
Ora che il programma è stato decifrato (dalla forza bruta, sfortunatamente; questo è sempre un pericolo in queste brevi soluzioni), posso anche spiegare a cosa stavo arrivando. Questo era in realtà abbastanza risolvibile leggendo il programma; Avrei potuto renderlo molto più difficile, ma mi è sembrata una cattiva idea quando esistono crepe a forza bruta.
Inizieremo rappresentando il programma in una codifica più naturale. Come al solito, i numeri in grassetto indicano i comandi che vengono eseguiti immediatamente (non tutti sono rappresentabili in un programma, 6
e 7
sono, ma 2
per 5
non), i numeri rappresentano unbolded loro equivalenti sfuggite ( 0
a 5
, che sono tutti rappresentabili nel programma originale; nota che 0
è un escape 6
ed 1
è un escape 7
):
112 7 1 7 34002 77 023 67 13303
L'insieme di comandi disponibili in una sorgente di programma 7 significa che è fondamentalmente solo un valore letterale che rappresenta lo stack originale (non c'è nient'altro che puoi fare con i soli comandi di escape 6
e 7
). Quindi la prima cosa che farà un programma è spingere un sacco di roba nello stack. Ecco come lo stack si occupa dell'esecuzione del programma ( |
separa gli elementi dello stack, come al solito in 7):
772 | 7 | 34662 | 023 | 73.363
L'elemento stack finale viene quindi copiato per diventare il codice da eseguire (rimanendo nello stack). Come succede, questa è l'unica parte del programma che è il codice; tutto il resto sono solo dati. Ecco cosa si traduce in:
73363
7 Spingi un elemento vuoto sullo stack 3 Emetti l'elemento stack
superiore, scarta l'elemento sottostante
73 Effetto combinato di questi: elimina l'elemento stack superiore
3 Emetti l'elemento stack superiore, elimina l'elemento sottostante
6 Esci dall'elemento stack superiore, quindi aggiungilo all'elemento sottostante
3 Emetti l'elemento stack superiore, scarta l'elemento sottostante
In altre parole, questo è principalmente solo un mucchio di istruzioni I / O. Analizziamo questo in dettaglio:
73
scarta 73363
ciò che è ancora in cima alla pila.
3
genera il 023
, e scarta il 34662
. Si può quindi vedere che 34662
è un commento, che è stato usato per memorizzare i byte necessari nell'altra versione del programma. Per quanto riguarda ciò che 023
fa durante l'output, seleziona il formato I / O 0 (numeri interi), quindi 23
è una direttiva che richiede l'implementazione per immettere un numero intero (in 7, si fa input tramite l'output di codici specifici che richiedono input). L'input viene eseguito facendo copie dell'elemento stack di seguito, ad esempio se l'input integer è 10, l'elemento stack successivo (attualmente 7
) diventerà 7777777777
. Pertanto, accettiamo l'input dell'utente in decimale, ma viene memorizzato come unario.
6
sfugge all'elemento stack superiore (modificando ciascuna istanza di 7
in 1
; questo è il modo in cui le stringhe costituite interamente da 7
s vengono evase), quindi lo aggiunge all'elemento stack prima ( 772
). Quindi i nostri dati ora sono qualcosa di simile 7721111111111
.
- Infine,
3
genera l'elemento stack in questione (e apre un elemento stack vuoto che fa parte dello stack iniziale predefinito). Il suo valore è calcolato prendendo il numero di 1
s e 7
s, e sottraendo il numero di 0
s e 6
s. (La 2
parte centrale viene ignorata nella maggior parte dei casi; se si trova alla fine della stringa, diventerà una nuova riga finale invece di essere ignorata, ma le regole PPCG non se ne preoccupano.) Pertanto, l'output è l'originale input più 2.
A questo punto, non c'è nulla di utile nello stack e niente nel programma, quindi il programma termina.
Come possiamo invertire questo? È una semplice questione di cambiare 11
in 00
, in modo che stiamo anteponendo caratteri all'input che lo rendono 2 più basso, anziché 2 più alto. Ci sono 00
otto cifre ottali comodamente nascoste più avanti nel programma (in modo che cifre ottali e byte si allineino l'una con l'altra), quindi possiamo semplicemente scambiarlo con 11
all'inizio.