Non male per un tarpit di Turing abbastanza prolisso ...
N
Count i while _%128-9 {
Count x while _/128%2 {
Write 40
_+128
}
Write _%128
_+128-_%128+N
}
Count j while _/256-j {
Write 41
}
(Sì, tutto quello spazio bianco è obbligatorio.)
Nota: a causa delle limitazioni di input di Acc !! , è impossibile leggere una stringa arbitraria di caratteri senza delimitatore finale. Pertanto, questo programma prevede input (su stdin) come una stringa seguita da un carattere di tabulazione.
Acc !! ?
È una lingua che ho creato che sembra essere inutilizzabile . L'unico tipo di dati è numeri interi, l'unico costrutto del flusso di controllo è il Count x while y
ciclo e l'unico modo per archiviare i dati è un singolo accumulatore _
. L'input e l'output vengono eseguiti un carattere alla volta, utilizzando il valore speciale N
e l' Write
istruzione. Nonostante questi limiti, sono abbastanza sicuro che Acc !! è Turing completo.
Spiegazione
La strategia di base in Acc !! la programmazione consiste nell'utilizzare la %
divisione mod e integer /
per partizionare concettualmente l'accumulatore, consentendogli di memorizzare più valori contemporaneamente. In questo programma, utilizziamo tre di queste sezioni: i sette bit di ordine più basso ( _%128
) memorizzano un codice ASCII dall'input; il bit successivo ( _/128%2
) memorizza un valore flag; e i bit rimanenti ( _/256
) contano il numero di parentesi chiuse di cui avremo bisogno.
Ingresso in Acc !! deriva dal valore speciale N
, che legge un singolo carattere e restituisce il suo codice ASCII. Qualsiasi affermazione che consiste esclusivamente in un'espressione assegna il risultato di quell'espressione all'accumulatore. Quindi iniziamo memorizzando il codice del primo personaggio nell'accumulatore.
_%128
memorizzerà l'ultimo carattere letto. Quindi il primo ciclo viene eseguito mentre _%128-9
è diverso da zero, ovvero fino a quando il carattere corrente non è una scheda.
All'interno del ciclo, vogliamo stampare a (
meno che non siamo alla prima iterazione. Dal momento che Acc !! non ha un'istruzione if, dobbiamo usare i loop per i condizionali. Usiamo il bit 128 dell'accumulatore _/128%2
, come valore flag. Al primo passaggio, l'unica cosa nell'accumulatore è un valore ASCII <128, quindi il flag è 0 e il ciclo viene saltato. Ad ogni passaggio successivo, ci assicureremo che la bandiera sia 1.
All'interno del Count x
loop (ogni volta che il flag è 1), scriviamo un open paren (ASCII 40
) e aggiungiamo 128 all'accumulatore, impostando così il flag su 0 ed uscendo dal loop. Questo succede anche per aumentare il valore di _/256
, che useremo come nostro conteggio di parentesi ravvicinate da produrre.
Indipendentemente dal valore della bandiera, scriviamo il carattere di input più recente, che è semplicemente _%128
.
Il prossimo incarico ( _+128-_%128+N
) fa due cose. Innanzitutto, aggiungendo 128, imposta la bandiera per la prossima volta attraverso il ciclo. In secondo luogo, azzera lo _%128
slot, legge un altro personaggio e lo memorizza lì. Quindi andiamo in loop.
Quando il Count i
ciclo termina, abbiamo appena letto un carattere di tabulazione e il valore dell'accumulatore si scompone in questo modo:
_%128
: 9
(il carattere di tabulazione)
_/128%2
: 1
(la bandiera)
_/256
: numero di caratteri letti, meno 1
(Il meno 1 è perché aggiungiamo 128 all'accumulatore solo una volta durante il primo passaggio attraverso il circuito principale.) Tutto ciò di cui abbiamo bisogno ora sono i parentesi strette. Count j while _/256-j
Cicli _/256
volte, scrivendo un paren vicino (ASCII 41
) ogni volta. Ecco!