L'obiettivo di questa sfida è (eventualmente) produrre ogni possibile programma di arresto in una lingua a scelta. All'inizio può sembrare impossibile, ma puoi farlo con una scelta molto attenta dell'ordine di esecuzione.
Di seguito è riportato un diagramma ASCII per illustrare questo. Lascia che le colonne rappresentino una numerazione di ogni possibile programma (ogni programma è un numero finito di simboli da un alfabeto finito). Lascia che ogni riga rappresenti un passo singolare nell'esecuzione di quel programma. Un X
rappresenta l'esecuzione eseguita da quel programma in quel passaggio temporale.
step# p1 p2 p3 p4 p5 p6
1 X X X X X X
2 X X X X X
3 X X X X
4 X X X X
5 X X X
6 X X
7 X X
8 X X
9 X X
∞ X X
Come puoi dire, i programmi 2 e 4 non si fermano. Se dovessi eseguirli uno alla volta, il tuo controller si bloccherebbe nel ciclo infinito che è il programma 2 e non emetterebbe mai programmi 3 e oltre.
Invece, usi un approccio a coda di rondine . Le lettere rappresentano un possibile ordine di esecuzione per i primi 26 passaggi. I *
punti sono i luoghi in cui quel programma si è interrotto e viene emesso. Gli .
s sono passaggi che non sono stati ancora eseguiti.
step# p1 p2 p3 p4 p5 p6
1 A C F J N R V
2 B E I M Q * Z
3 D H * P U
4 G L T Y
5 K O X
6 * S .
7 W .
8 . .
9 . .
∞ . .
Requisiti per la lingua di destinazione
La lingua di destinazione (quella interpretata in parallelo) deve essere Turing-complete. A parte questo, può essere qualsiasi lingua completa di Turing, inclusi sottoinsiemi completi di Turing di lingue molto più grandi. Sei anche libero di interpretare cose come le regole di sistema dei tag ciclici. Puoi anche creare una lingua da testare, purché tu possa mostrare perché è Turing completo.
Ad esempio, se si sceglie di testare Brainfuck, è consigliabile testare solo il []-+<>
sottoinsieme, poiché l'input non è supportato e l'output viene semplicemente eliminato (vedere di seguito).
Quando si tratta del programma "controller" (che stai giocando a golf), non ci sono requisiti speciali. Si applicano le normali restrizioni linguistiche.
Come creare un elenco infinito di programmi
La maggior parte dei linguaggi di programmazione può essere rappresentata come una serie di simboli da un alfabeto finito. In questo caso, è relativamente facile elencare un elenco di tutti i programmi possibili in ordine crescente. L'alfabeto che usi dovrebbe essere rappresentativo dei requisiti della lingua di destinazione. Nella maggior parte dei casi, questo è ASCII stampabile. Se la tua lingua supporta Unicode come funzionalità aggiuntiva, non dovresti testare tutte le possibili combinazioni di caratteri Unicode, ma solo ASCII. Se la tua lingua utilizza solo []-+<>
, non testare le varie combinazioni di caratteri ASCII "comment". Lingue come APL avrebbero i loro alfabeti speciali.
Se la tua lingua è meglio descritta in un modo non alfabetico, come Fractran o Turing Machines, allora ci sono altri metodi ugualmente validi per generare un elenco di tutti i possibili programmi validi.
Interpretazione di un elenco sempre crescente di programmi
La parte fondamentale di questa sfida è quella di scrivere un interprete parallelo per un elenco crescente di programmi. Ci sono alcuni passaggi di base per questo:
- Aggiungi un numero finito di programmi all'elenco
- Interpretare ciascun programma nell'elenco individualmente per un periodo di tempo finito. Ciò può essere realizzato eseguendo un passo di istruzione per ciascuno. Salva tutti gli stati.
- Rimuovere dall'elenco tutti i programmi che terminano / generano errori
- Emette i programmi * fermamente arrestati
- Aggiungi altri programmi all'elenco
- Simula ogni programma a turno, riprendendo l'esecuzione dei programmi più vecchi da dove era stato interrotto
- Rimuovere dall'elenco tutti i programmi che terminano / generano errori
- Emette i programmi * fermamente arrestati
- ripetere
* Dovresti solo emettere programmi che si fermano in modo pulito. Ciò significa che non sono stati generati errori di sintassi o eccezioni non rilevate durante l'esecuzione. Anche i programmi che richiedono input devono essere chiusi senza emetterli. Se un programma produce output, non dovresti terminarlo, basta buttare l'output.
Più regole
- Non devi generare nuovi thread per contenere i programmi testati, poiché questo scarica il lavoro di parallelizzazione sul sistema operativo host / altro software.
- Modifica: per chiudere potenziali scappatoie future, non è consentito
eval
(o alcuna funzione correlata) una parte del codice del programma testato . È possibileeval
un codeblock dal codice dell'interprete. (La risposta BF-in-Python è ancora valida in base a queste regole.) - Questo è code-golf
- La lingua in cui scrivi l'invio non deve necessariamente essere la stessa lingua che stai testando / producendo.
- Si dovrebbe supporre che la memoria disponibile sia illimitata.
- Quando si dimostra la completezza di Turing, è possibile supporre che l'input sia codificato nel programma e che l'output possa essere letto dallo stato interno del programma.
- Se il tuo programma esce da solo, probabilmente è sbagliato o un poliglotta.
"If your program outputs itself, it is probably wrong or a polyglot."