Interprete di lingua completo di Turing


42

Una sfida che ho pensato che sarebbe molto interessante è quella di creare un interprete per una lingua completa di Turing di tua scelta.

Le regole sono semplici:

  1. È possibile utilizzare qualsiasi linguaggio per creare questo interprete anche se è più recente di questa sfida.
  2. Puoi usare qualsiasi linguaggio completo di Turing purché non sia uguale a quello con cui lo stai scrivendo.
  3. Non è possibile semplicemente valutare il codice, ad esempio, utilizzare le funzioni eval.
  4. Una spiegazione di come ti sei avvicinato a questo sarà piacevole ma non richiesta.
  5. Questo sarà segnato in byte.
  6. Ogni invio deve essere pienamente funzionante, il che significa che deve essere presente ogni caratteristica della lingua scelta.

Per dirla semplicemente:

Il tuo compito è creare un interprete di lavoro per qualsiasi lingua completa di Turing con qualsiasi lingua di tua scelta.

In bocca al lupo!


3
Vorrei anche raccomandare una regola secondo cui il linguaggio implementato deve essere diverso dal linguaggio che usi per implementarlo, per evitare evalsoluzioni banali .
ETHproductions

1
In realtà, potresti voler semplicemente vietare evalcomandi / funzioni, poiché alcune lingue hanno incorporati per valutare il codice in un'altra lingua.
ETHproductions

2
@arodebaugh Per le sfide future, puoi pubblicare la tua idea nella sandbox in cui è possibile ottenere feedback e appianare dettagli del genere prima che le sfide si realizzino e ricevano risposta.
Martin Ender,

1
OK, probabilmente dovresti essere un po 'più specifico e dire qualcosa come "Non puoi semplicemente eseguire il codice, tramite qualsiasi metodo" per evitare altre risposte banali come quella di Bash + perl.
ETHproductions

Risposte:


16

Brachylog (2) → Problema post-corrispondenza , 9 byte

~h=∋ᵐ\cᵐ=

Provalo online!

L'input è un elenco di elenchi di stringhe. (Nel problema di corrispondenza Post come definito su Wikipedia, gli elenchi interni hanno due elementi ciascuno, anche se questo programma può effettivamente gestire una generalizzazione a qualsiasi numero di elementi.) Questo programma forza bruta soluzioni al problema, in ordine di lunghezza, fino a è stata trovata una soluzione. Il problema della corrispondenza post è noto per essere in grado di simulare una macchina di Turing, e quindi le soluzioni di forzatura bruta ad essa sono Turing complete. Se eseguito come una funzione, piuttosto che un programma, in realtà produce anche un output significativo.

Il programma nel link TIO sopra è [["a","baa"],["ab","aa"],["bba","bb"]], che ho copiato da Wikipedia. La soluzione (che il programma trova abbastanza rapidamente) è ["bbaabbbaa","bbaabbbaa"].

Spiegazione

Questa è praticamente solo una traduzione diretta del problema di corrispondenza Post in Brachylog.

~h=∋ᵐ\cᵐ=
~h         Find {the shortest possible} list which starts with {the input}
  =        and for which all elements are equal
   ∋ᵐ      such that taking an element of each element,
     \cᵐ   and concatenating elements in corresponding positions,
        =  produces a list all of whose elements are equal.

Fondamentalmente, creiamo un elenco di copie ripetute dell'input (il minor numero possibile, il che significa che non perdiamo alcuna possibilità durante la forzatura bruta), prendiamo un elemento da ogni copia, quindi concateniamo gli elementi corrispondenti (come nella corrispondenza Post problema).


1
E la solita "carrellata di cose significative e che salverebbero i byte ma l'interprete di Brachylog non può gestirlo": i primi cinque byte potrebbero essere espressi come ~dp(il che non significa esattamente la stessa cosa ma è abbastanza vicino da essere ancora Turing-complete), tranne per il fatto che l'interprete Brachylog non sa ancora come invertire d.

12

Gelatina → "Aggiungi minimo per trasporre", 5 4 byte

+"Ṃẞ

Provalo online! (esegue solo una iterazione, per evitare timeout)

Una costruzione di Turing molto semplice: prendiamo una matrice quadrata come programma e eseguiamo il loop per sempre, identificando la riga lessicograficamente più piccola, quindi aumentando ogni elemento della prima riga dal primo elemento del lessicograficamente più piccolo, ogni elemento della seconda fila dal secondo elemento del lessicograficamente più piccolo, e così via. (Il programma Jelly è " +"aggiungi gli elementi corrispondenti {dell'input e} il minimo {dell'originale}, loop"; questo è un byte più corto del mio programma precedente Z+ṂZß, che ha fatto esattamente la stessa cosa. Chiaramente avrei dovuto concentrarmi sul golf Jelly, non solo giocare a golf con il linguaggio implementato.)

La lingua risultante è Turing-complete per lo stesso motivo del canguro. Il primo elemento di ogni riga si comporta come un conteggio dei salti (anche se invece del conteggio dei salti di ciascun comando che si riduce quando viene saltato, aumentiamo invece il conteggio dei salti di ciascun comando quando viene eseguito e cerchiamo invece il comando con il conteggio dei salti più basso di comandi con zero salti conteggi; questo arriva alla stessa cosa). Assicuriamo che questo primo elemento sia più alto degli altri elementi (che rappresentano il numero di volte in cui ciascun comando appare nel multiset di ciascun comando), assicurando così che la prima riga non sia mai il minimo; il resto della prima riga può essere immondizia. L'unico problema rimanente è la modellazione del modo in cui i comandi con uguale numero di salti vengono eseguiti ciclicamente in sequenza, ma possiamo farlo moltiplicando tutti i conteggi di salti per una costante grande, quindi aggiungendo piccoli "iniziali" saltare conta fino alla prima colonna per fungere da tiebreak. Questo ci dà un pareggio di "prime esecuzioni di comandi non bloccati", non di "comandi non bloccati eseguiti ciclicamente in sequenza", ma la costruzione della completezza di Turing per Canguro non tiene conto di questa differenza.


10

Mathematica interpretando Conway's Game of Life, 64 byte

CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&

Il gioco della vita di Conway è noto per essere Turing completo; e gli automi cellulari sono la vera ossessione di Stephen Wolfram. CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}è una regola che trasforma un array bidimensionale di 0 e 1 secondo un passaggio di Conway's Game of Life. (Penso che il comportamento predefinito sia che questo array si avvolga attorno ai suoi bordi, quindi è davvero un toro discreto.) ~Nest~##&Trasforma questa regola in una funzione che, quando viene dato uno stato iniziale della scheda (di qualsiasi dimensione) e un intero ncome argomento, genera risultato delle niterazioni della regola del Gioco della vita.

Per il tuo divertimento, potresti usare la versione incartata

b = RandomInteger[1,{50,50}];
Manipulate[ArrayPlot[
  CellularAutomaton@{224,{2,{t={2,2,2},{2,1,2},t}},{1,1}}~Nest~##&
    [b, n] ]
, {{n,0}, 0, 100, 1}]

e scorri per 100 generazioni su una tavola 50x50.


Se ho capito bene, questo ha una dimensione della scheda fissa? In quel caso, penso che non possa essere Turing completo, vero?
DLosc

Ogni chiamata particolare alla funzione ha una dimensione della scheda fissa, ma quella dimensione della scheda può essere arbitrariamente grande. (Nota che la seconda metà del post descrive un esempio di osservazione del codice in azione, non il codice stesso).
Greg Martin,

Quello che sto dicendo è che affinché GoL sia Turing-Complete, deve essere capace di uno schema che cresce all'infinito. (Come una pistola ad aliante.) Se questa implementazione non può far crescere l'array da un passo all'altro, ma invece lo avvolge toroidalmente, allora fallisce il test di crescita infinita.
DLosc,

Questa è una prospettiva ragionevole, per essere sicuri. Ma le implementazioni dei linguaggi di programmazione sui computer fisici non soddisfano nemmeno questo test! Si potrebbe accontentarsi di una (ipotetica) sequenza di computer fisici con sempre più memoria, ognuno in grado di calcolare un valore in più di quella funzione calcolabile; a quel punto, tuttavia, si dovrebbe essere ugualmente contenti di una (ipotetica) sequenza di input per un tale programma GoL.
Greg Martin,

9

Turtlèd interpretando CT , 49 byte

Potrei essere in grado di giocare a golf

Inoltre, questo non produce nulla di utile. si ferma solo se e solo se il programma CT specificato si arresta.

questo è quello che ho fatto qualche tempo fa in realtà (poi ho giocato a golf ora)

!-l[*+.r_]' !l[ l]r[ u.(;d' u)d(1[ r].[ l])( r)+]

Come funziona:

Turtlèd utilizza celle a griglia. Quando dico "scrivi qualcosa sulla griglia" intendo che un gruppo contiguo di personaggi viene posizionato sulla griglia. esempio

[ ][ ][ ][ ][ ][ ][ ]
[ ][H][E][L][L][O][ ]
[ ][ ][ ][ ][ ][ ][ ]
[ ][ ][ ][ ][ ][ ][ ]

sul programma

i dati vengono immessi per primi:

!-l[*+.r_]' 

questo è essenzialmente un programma per gatti. scrive l'input sulla griglia.

quindi vengono immessi i comandi:

!

cosa fa con questi comandi:

questi comandi sono "produzioni". se il bit di dati più a sinistra è 1, copia la produzione alla fine della stringa di dati. altrimenti non succede nulla. quindi il bit di dati più a sinistra viene rimosso e utilizza la produzione successiva con il bit di dati più a sinistra successivo. il programma si arresta quando non ci sono bit nella stringa di dati. Un modo per fare queste produzioni è quello di affrontare i pezzi e la fine delle produzioni separatamente. questo è ciò che fa il nostro programma. copia separatamente i bit dalla stringa di comando alla fine della stringa di dati e cancella separatamente i bit dal datastring

su come funziona questo programma. dopo aver inserito i comandi, il puntatore tartaruga / griglia ritorna al bit più a sinistra del datastring. quindi va in loop

[ u.(;d' u)d(1[ r].[ l])( r)+]

quello che fa in questo loop, è che si sposta in alto dal datastring più a sinistra e annota il carattere di comando corrente (u.). in caso affermativo, la fine di una produzione, si sposta verso il basso ed elimina il bit di dati più a sinistra al di sotto di esso e torna indietro ( (;d' u)). quindi, in entrambi i casi, si sposta in basso di uno ( d). se il bit non è stato eliminato, significa che alla fine deve verificare se copiare un bit dai comandi. quindi, se questo carattere che è o era il database più a sinistra è un 1, si sposterà alla fine dell'estremità destra della stringa di dati, copierà il bit dalla stringa di comando e tornerà allo spazio a sinistra dei dati all'estrema sinistra bit ( (1[ r].[ l])). ora si trova sul databit più a sinistra, che era uno zero, oppure a sinistra del databit più a sinistra. quindi, ci spostiamo a destra se su uno spazio (( r)). quindi, il puntatore al comando viene incrementato in modo da annotare il comando successivo nella successiva iterazione del ciclo. Se non ci sono più datastring, questo significa che saremo su uno spazio e il ciclo finirà. altrimenti eseguiamo nuovamente il ciclo.


Prova a giocare ancora a golf!
arodebaugh,

9

Perl → Variante del programmatore a tre stelle , 26 + 1 = 27 byte

++$a[$a[$a[$_]]]for@F;redo

Provalo online! (Questo collegamento contiene un'intestazione che esce dal programma dopo un determinato numero di iterazioni (in modo che TIO non scada) e per stampare lo stato interno ogni iterazione (in modo che faccia qualcosa di osservabile).)

Esegui con -a(penalità di 1 byte, poiché puoi inserirla prima della -M5.010produzione -aM5.010).

In particolare, questo implementa il programmatore a tre stelle in cui i comandi sono separati da spazi e non sono consentiti commenti nel file, senza estensioni I / O. (Queste modifiche non fanno alcuna differenza per la completezza del linguaggio di Turing, ovviamente.) Non c'è una prova della completezza di Turing per il programmatore a tre stelle online, ma è Turing completa (ho condiviso una prova di schizzo del suo Turing -completità con altri esoprogrammatori, ma ho smesso di lavorare sulla lingua quando ho scoperto che in realtà era abbastanza facile programmare una volta superato lo shock originale).

Il programma non ha davvero bisogno di molte spiegazioni; Il programmatore a tre stelle ha una specifica molto semplice, e questa è una traduzione diretta di essa. Gli unici punti sottili: @Fè l'input al programma in forma di array (questa è una conseguenza di -a); e redoripeterà l'intero programma in quanto è in un ciclo implicito (anche una conseguenza di -a).


1
Penso che abbia più senso che la freccia significhi "è ridotto a" che "interpreta".
Quintopia,

9

assembly x86 (sintassi Intel / MASM) -Brainfuck 2127 byte.

Ancora in grado di giocare a golf

.386
.model flat,stdcall
.stack 4096
include \masm32\include\masm32.inc
includelib \masm32\lib\masm32.lib
ExitProcess proto,dwExitCode:dword
.data
bfsrc BYTE 200 dup(0) 
bfcells BYTE 100 dup(0) 
loopStack DD 5 dup(0) 
charBuf BYTE 5 dup(0) 
newline BYTE 10,0 
prompt BYTE "$",0 
hr BYTE 50 dup('-'),0 
space BYTE ' ',0
.code
EvalBf proc
    start:
    invoke StdOut, addr prompt
    invoke StdIn, addr bfsrc,200
    cmp bfsrc,0
    je exit
    mov eax,0 
    mov ebx,0 
    mov ecx,0 
    processInstruction:
    cmp BYTE PTR bfsrc[ebx], '+'
    je plus
    cmp BYTE PTR bfsrc[ebx], '-'
    je minus
    cmp BYTE PTR bfsrc[ebx], '>'
    je fwd
    cmp BYTE PTR bfsrc[ebx], '<'
    je back
    cmp BYTE PTR bfsrc[ebx], '['
    je open
    cmp BYTE PTR bfsrc[ebx], ']'
    je close
    cmp BYTE PTR bfsrc[ebx], '.'
    je dot
    jmp processNextInstruction
    plus:
    inc BYTE PTR bfcells[eax]
    jmp processNextInstruction
    minus:
    dec BYTE PTR bfcells[eax]
    jmp processNextInstruction
    fwd:
    inc eax
    jmp processNextInstruction
    back:
    dec eax
    jmp processNextInstruction
    open:
    mov loopStack[ecx*4],ebx
    inc ecx
    jmp processNextInstruction
    close:
    dec ecx
    cmp BYTE PTR bfcells[eax], 0
    je processNextInstruction
    mov ebx,loopStack[ecx*4]
    inc ecx
    jmp processNextInstruction
    dot:
    mov dl, BYTE PTR bfcells[eax]
    mov BYTE PTR charBuf[0], dl
    mov BYTE PTR charBuf[1],0anything
    push eax
    push ecx
    invoke StdOut, addr charBuf
    pop ecx
    pop eax
    jmp processNextInstruction
    processNextInstruction:
    inc ebx
    cmp BYTE PTR bfsrc[ebx], 0
    je done
    jmp processInstruction
    done:
    invoke StdOut, addr newline
    mov eax, 0
    printNext:
    cmp eax, 100
    jge reset
    push eax
    invoke dwtoa, BYTE PTR bfcells[eax], addr charBuf
    invoke StdOut, addr charBuf
    invoke StdOut, addr space
    pop eax
    inc eax
    jmp printNext
    reset:
    invoke StdOut, addr newline
    invoke StdOut, addr hr
    invoke StdOut, addr newline
    jmp start

    exit:
    invoke ExitProcess,0
EvalBf endp
end EvalBf

3
Di solito le risposte all'assemblaggio vengono contate nella dimensione del codice macchina risultante, quindi non è necessario golfare l'assemblaggio, basta minimizzare il numero / dimensione delle istruzioni.
Robert Fraser,

@RobertFraser uhh non so come contarlo: P
Christopher,

3
In realtà, all'inizio ho in qualche modo letto il titolo come "x86 asm implementato in Brainfuck" e sono rimasto un po 'colpito :)
quetzalcoatl,

@Quetzalcoatl Sarebbe impressionante
Christopher,

1
pls golf nomi variabili / etichette ty
solo ASCII

8

Pip interpreta i sistemi di tag ciclici , 16 byte

YqWyyPBg@++vXPOy

Prende le produzioni del sistema di tag come argomenti della riga di comando e la stringa di dati iniziale da stdin.

Il codice sopra è difficile da verificare perché non produce alcun output (quindi l'unico comportamento osservabile è "termina" vs. "non termina"). Pertanto, ecco una versione non golfata che emette la stringa di dati dopo ogni passaggio e termina anche dopo 20 passaggi, quindi TIO non deve gestire tonnellate di output da loop infiniti: provalo online!

Sistemi di tag ciclici

I sistemi di tag ciclici sono un modello computazionale estremamente semplice ma completo di Turing . Sono costituiti da un elenco di produzioni che definiscono le operazioni su una stringa di dati . Le produzioni e la stringa di dati sono costituite da 1 e 0.

Ad ogni passaggio, il carattere più a sinistra della stringa di dati viene rimosso.

  • Se il carattere è 1, la produzione corrente viene aggiunta sul lato destro della stringa di dati.
  • Se il personaggio è 0, non viene aggiunto nulla.

In entrambi i casi, l'attuale produzione passa ciclicamente alla produzione successiva nella lista: se fossimo all'ultima produzione, passiamo al primo. L'esecuzione continua fino a quando la stringa di dati è vuota.

Spiegazione

                  g is list of cmdline args; v is -1 (implicit)
 q                Read a line of stdin for the data string
Y                 and yank it into the y variable
  Wy              While data string is nonempty:
       g@++v       Retrieve the next production from g (using cyclic indexing)
             POy   Pop the first character of y
            X      String-multiply: result is the production if the first character of y
                   was 1, or empty string if it was 0
    yPB            Push that string to the back end of y

ehi, ho appena ricordato che non è necessario inserire la stringa di dati; può essere solo 1fonte: esolangs si collega a questo arxiv.org/abs/1312.6700 . Modificherò presto la mia risposta, e se questo aiuta la tua risposta dovresti (tbh il tuo contributo sembra effettivamente abbastanza da golf in realtà)
Destructible Lemon

8

Funzioni di collatz generalizzate iterate -> Python 2, 46 byte

a,b,x,m=input()
while-~x%m:x=x/m*a[x%m]+b[x%m]

Chiamare questa funzione con un elenco di m-1 a e b, il valore iniziale x e il divisore m, che costituiscono collettivamente un "programma" per IGCF. Invece di prendere un terzo array per indicare su quali moduli fermarsi, questo si ferma semplicemente ogni volta che il modulo è m-1. Questa semplificazione significa che potrebbe essere necessario uno sforzo supplementare per convertire un determinato programma Fractran in questa variante, ma salva un paio di byte nell'interprete.

Provalo online! Questo TIO dimostra come aggiungere 5 + 5 con questa lingua. Il programma a = [3], b = [0], m = 2 fa l'addizione, e iniziando con 7776 = 2 ^ 5 * 3 ^ 5 alla fine produce 59049 = 3 ^ 10.


Dang bel lavoro. Speravo di vincere la grazia ma un buon lavoro
Christopher,

7

Variante ResPlicate -> Python 2, 47 byte

l=input()
while l:l=l[2+l[0]:]+l[2:2+l[0]]*l[1]

Questa funzione interpreta una variante di ResPlicate

  • per cui un programma è un elenco pitone di lunghezza pari con elementi pari a indici pari.
  • senza I / O.
  • per cui il tentativo di copiare più valori di quelli esistenti nel resto della coda copia semplicemente il resto della coda (ovvero, il bit copiato non viene riempito con zero alla lunghezza richiesta).

L'ultima modifica indica che alcuni programmi ResPlicate (che soddisfano la prima condizione) non si comporteranno allo stesso modo in questa variante, ma fortunatamente gli interpreti BCT non richiedono la funzionalità rimossa, e quindi il linguaggio rimane TC.

Provalo online! Questo TIO ha una stampa incastrata in esso per mostrare che funziona e un'intestazione che uccide il programma dopo 1 secondo e un esempio che riesce a generare più output di quanto TIO possa gestire in quel secondo.


2
Perché no l=input()? Sarebbe un byte più breve.
feersum

7

Perl -amacchina I / D , 24 byte

$p=$a[$p]+=$_ for@F;redo

Provalo online! (contiene un'intestazione che stampa lo stato interno e si interrompe dopo 10 iterazioni, in modo che il comportamento sia osservabile)

A proposito della lingua

Ho passato gli ultimi due giorni a lavorare sulla macchina I / D , una delle mie ultime idee per linguaggi di programmazione molto semplici. Funziona come segue: l'archiviazione dei dati è costituita da una RAM illimitata, inizialmente tutti zeri. Ogni elemento può memorizzare un numero intero senza limiti (anche se in pratica, la maggior parte dei programmi di macchine I / D memorizzerà solo piccoli numeri interi nella maggior parte di essi e utilizzerà gli interi senza limiti solo come un modo per indirizzare le celle con indirizzi di grandi dimensioni). C'è anche un puntatore di dati, che punta a una cella (ovvero contiene l'indirizzo come cella); inizialmente è anche zero.

Ci sono solo due comandi:

  • I: Aumenta la cella a cui punta il puntatore dati. (Il puntatore ai dati stesso rimane invariato.)
  • D: Dereferenziare il puntatore dati, ovvero leggere il valore della cella a cui punta il puntatore dati. Quindi archiviare il valore risultante che si rilegge nel puntatore di dati.

L'esecuzione esegue semplicemente il programma in un ciclo ripetutamente, per sempre.

È abbastanza sorprendente che un linguaggio così semplice sia completo di Turing, quindi ho lavorato per dimostrarlo. Ecco la prova . È abbastanza simile (ma più semplice) della dimostrazione per il programmatore a tre stelle, un linguaggio molto simile (e in effetti, questa presentazione utilizza la stessa "shell" OISC di base attorno al programma, differendo solo per l'istruzione effettiva implementata).

A proposito del programma

uso

L'input deve essere fornito su input standard ed è un programma I / D della macchina senza commenti e utilizzando la sintassi RLE / OISC. (La macchina I / D ha due diverse sintassi equivalenti, ma per golfismo questo programma ne supporta solo una.) In questa sintassi, un programma è una sequenza di numeri in decimale, che rappresenta la lunghezza delle serie di Icomandi tra Dcomandi. (È possibile specificare due o più Dcomandi consecutivi posizionando una " sequenza di 0 Icomandi" tra loro, quindi la sintassi è completamente generale.)

Spiegazione

Come si può vedere dal programma, questo non implementa i comandi Ie Dsingolarmente. In realtà, è un interprete (molto leggermente) ottimizzante (puramente perché è più breve scrivere in questo modo). La chiave è vedere che una serie di n comandi di incremento incrementa n volte la destinazione del puntatore dati , ovvero aggiunge n ad esso; e l'esecuzione di 0 comandi di incremento può anche essere implementata in questo modo, poiché l'aggiunta di 0 alla memoria non ha alcun effetto. Quindi l'operazione che effettivamente implementiamo è quella di alternare l'implementazione di un run-of- Is e a D. O in altre parole "aggiungi nal valore puntato dal puntatore dati (memorizzandolo nuovamente nel valore puntato dal puntatore dati), quindi leggi il valore puntato dal puntatore dati e memorizzalo nel puntatore dati ". È chiaramente più dettagliato di quello di cui ha bisogno essere, e possiamo semplificare ulteriormente questo "aggiungere n al valore indicato dal puntatore dati, quindi memorizzare quel valore sia nella destinazione del puntatore dati che nel puntatore dati stesso".

Ciò costituisce il nucleo del nostro programma. Stiamo utilizzando un array $aper memorizzare la RAM e $pcome puntatore ai dati (indicizzazione nell'array):

$p=$a[$p]+=$_
         + $_  add {the run length}
   $a[$p]      to the element of $a pointed to by $p
   $a[$p] =    storing the result back into that element
$p=            and also in the pointer itself

Convenientemente, Perl interpreta gli elementi dell'array non inizializzati come 0 quando vengono trattati come numeri, quindi l'array verrà inizializzato pigramente a zero per noi senza alcun codice esplicito per ciò che è necessario. (Un potenziale problema è l'accuratezza numerica quando i numeri diventano grandi; tuttavia, ciò accadrà solo se la quantità dell'array utilizzata supera lo spazio degli indirizzi della macchina (gli interi Perl sono abbastanza grandi da contenere puntatori), qualcosa che non può accadere su una macchina idealizzata.)

Infine, tutto ciò che dobbiamo fare è inserire questo programma in un paio di loop. Il for@Fciclo, combinato con l' -aopzione della riga di comando, passerà in rassegna i campi dell'input standard (la definizione predefinita di "campo" qui verrà suddivisa in spazi bianchi). Il redociclo inserirà l'intero programma in un ciclo implicito (oltre, in modo conveniente, alla lettura dell'input standard), che farà girare ripetutamente il programma in un ciclo, come richiesto dalla semantica della macchina I / D.


Ben tornato! Non abbiamo più bisogno di segnare i flag per gli interpreti, basta notare che questo è "Perl con -a". codegolf.meta.stackexchange.com/a/14339/9365
Dom Hastings

6

GelatinaSistema a 2 tag , 8 byte

µḢị⁴⁸;Ḋß

Provalo online!

Ho una taglia che favorisce le lingue pratiche, ma ho pensato che avrei potuto anche provare a vincere il compito originale mentre ero lì (dato che non posso esattamente vincere la mia taglia).

Implementa una variante di sistemi di tag senza stato di arresto, poiché non è necessario per la completezza di Turing. Gli stati sono numerati da 1, consecutivamente, e la stringa iniziale precede il programma.

Ad esempio, Wikipedia fornisce un esempio di un sistema di tag { a, b, c}, { abc, ba, caaa} con stringa iniziale aaa; in questo formato di input, che è [1,1,1], [[2,3],[1],[1,1,1]]. (I sistemi di tag non hanno una sintassi fissa e questo sembra un modo ragionevole per farlo.)

Il collegamento TIO ha aggiunto ("scrivi stato interno e una nuova riga su stdout") per mostrare che il programma sta effettivamente funzionando.

Spiegazione

µḢị⁴⁸;Ḋß
           {implicit: initialise internal state from first argument}
µ          Disregard the second command-line argument by default
 Ḣ         Take the first element, removing it from the internal state
  ị⁴       Use the value to index into the second argument
    ⁸;     Prepend (the rest of) the internal state
      Ḋ    Discard the first element of the internal state
       ß   Loop forever

6

BF / P "implementato in una Turing Machine, 842 byte

Tabella delle transizioni (collegata a causa della lunghezza)

Tavolo di transizione, versione meno golfizzata

Simulatore di Turing Machine che ho usato

Questo certamente non vincerà alcun premio per la lunghezza, ma è qualcosa che ho sempre desiderato fare, dal momento che BF è così simile a una macchina di Turing. Ogni cella memorizza un valore da 0x0- 0xF. La larghezza è comunque lontana dal sito Web di Turing Machine senza arresti anomali del browser. Le funzioni ,e .(input e output) non sono definite, quindi è un po 'più simile a P "rispetto al vero BF.

Per eseguirlo, incollare la tabella di transizione nel simulatore di Turing Machine, impostare l'input su un codice BF e premere Esegui.

Il nastro della TM memorizza sia il codice BF che i dati BF, con un singolo spazio nel mezzo. Tiene traccia della sua posizione nel codice modificando il carattere che è attualmente in esecuzione ( [-> (, ecc.) E la sua posizione nei dati con un ^davanti alla cella. Una volta che legge un carattere di comando, si sposta fino a quando non colpisce il cursore, sposta una cella a destra ed esegue la funzione appropriata. Quindi torna indietro, cercando uno dei caratteri di comando "modificati" nel codice BF, e passa a quello successivo, ripetendo l'intero processo. Una volta esaurito il codice, si arresta.

Il modo migliore per capire come funziona è eseguire la versione non controllata, metterla in modalità step e guardare quali linee portano a quali altre e cosa fa ogni stato / blocco di linee.

Le versioni golf e non golf sono esattamente uguali in termini di come funzionano, ma la versione non golf ha nomi più umani e è suddivisa in sezioni.


1
Il limite di lunghezza post è più che sufficiente per adattarsi alla tabella di transizione
solo ASCII il

6

C implementando la (2,3) Turing Machine , 236 205 byte ( 46 31 in meno se non ti importa degli input scomodi)

Grazie a Appleshell per -11 byte, VisualMelon per -12 byte e Johan du Toit per -7 byte.

CeilingCat ha realizzato una versione che utilizza solo 144 byte, vedi qui .

(Ho aggiunto alcune interruzioni di riga qui in modo da non dover scorrere, ma normalmente la maggior parte di queste verrebbero eliminate)

#define c char
j;i;k;c s,d[256];c main(){c*p=d+128;gets(d);
for(;k<256&&d[k];)d[k++]-=48;for(;++j<256;)
{c t=*p;*p=-t*t+(2-s)*t+1+s;p+=(s^t==0)*2-1;s=s?t%2:!t%3;
for(i=0;++i<256;)printf("%d",d[i]);puts("");}}

Provalo online!

Per utilizzare: inserire una stringa di massimo 256, zero e due per inizializzare il nastro. Qualsiasi valore non inizializzato sarà zero. (Valori diversi da 0, 1 e 2 possono causare comportamenti indefiniti.) Il programma eseguirà l'iterazione su 256 passaggi. Il numero di passaggi su cui scorre può essere aumentato modificando il codice, ma ovviamente ciò richiede più caratteri.

È una voce piuttosto lunga, ma questa è la prima volta che faccio una di queste e non ho usato un linguaggio golfistico dedicato. Mi sono divertito molto, anche se è risultato più lungo del previsto.

Molti byte derivano dalla gestione dell'input e dell'output e ho perso un totale di 42 byte facendogli accettare 0, 1 e 2 invece di NUL, SOH, STX. (Per cambiarlo, elimina k;dalla parte anteriore e for(;k<256&&d[k];)d[k++]-=48;dalla seconda riga.)

La tabella di transistor, in particolare la linea *p=-t*t+(2-s)*t+1+s;(che imposta i valori sul nastro) potrebbe probabilmente essere compressa anche di più.


1
Wow, e questo è il tuo primo codice golf qui! Meraviglioso!
Zacharý

Puoi abbreviare le dichiarazioni delle variabili globali in questo modo: k,j;c s,d[256];( intè implicito in C, quindi puoi anche passare ialla dichiarazione globale per risparmiare altri 3 byte)
Appleshell

@Appleshell Grazie, lo farò.
a52,

È possibile spostare il controllo null-terminal della stringa all'interno del ciclo for. L'allineamento k++e la rimozione di {}salva un paio di byte in più: for(;k<256&d[k];)d[k++]-=-48;poiché jè solo un cronometrista (valore mai usato) puoi sostituirlo (e i) kcontando all'indietro: sai k==256dopo il primo ciclo, quindi conta fino a zero nel secondo for(;k>0;), che lascia k==-1, così può diventare l'ultimo ciclo for(;++k<256;). (Dichiarazione di non responsabilità: di solito gioco a golf C#, ma questo sembra compilare).
VisualMelon

1
@VisualMelon Ho determinato il problema. Avevo bisogno di usare k<256&&d[k], non è &, perché d[k]era in corso di valutazione a k==256. Inoltre, poiché knon era più garantito 256che seguissi quel loop, ho dovuto ripristinarlo in seguito per garantire 256 passaggi. (Se tu (cioè VisualMelon) hai altri suggerimenti, dovremmo probabilmente metterli in chat in modo da non ricevere troppi commenti)
a52

5

Röda implementa Fractran , 114 112 106 byte

1 byte salvato grazie a @fergusq riorganizzando i parametri

f&n,a{x=1{x=0;(a/" ")()|[_/`/`]|[parseInteger(_[0],_1[1])]|{|q,w|{n*=q/w;x=1}if[n%w<1,x<1]}_,_}while[x>0]}

Provalo online!

Chiamare la funzione in questo modo: f reference_to_input program. L'output verrà archiviato nella posizione di input.


Il punto e virgola dopo e[1]è ridondante. Inoltre è possibile salvare un byte modificando ordine parametri: f&n,a.
Fergusq,

@fergusq Grazie per il f&n,atrucco, e stavo per rimuovere quel punto e virgola quando hai commentato :)
Kritixi Lithos

5

Clojure, 82 81 byte (Turing Machine)

Aggiornamento: rimosso uno spazio da t{} s.

#(loop[p 0 t{}s 1](if-let[[S M N](%[(or(t p)0)s])](recur(+ p M)(assoc t p S)N)t))

Implementa la Turing Machine come un ciclo, restituisce il nastro quando viene raggiunto lo stato di arresto. Nelle regole di transizione dello stato questo è indicato inserendo lo stato di transizione. Questo settins Na nile la conseguente if-letvolontà interruzione della corrispondente transizione di stato non viene trovato dall'ingresso hash-map %. In realtà qualsiasi valore per questo stato farà, come :abort0 o -1.

Ungolfed con un castoro occupato di 2 simboli di esempio a 3 stati di Wikipedia .

(def f #(loop[pos 0 tape {} state 1]
          (if-let [[sym move next-state](%[(get tape pos 0)state])]
            (do (println [pos tape state])
                (recur(+ pos move)(assoc tape pos sym)next-state))
            tape)))

(f {[0 1] [1  1 2]
    [0 2] [1 -1 1]
    [0 3] [1 -1 2] 
    [1 1] [1 -1 3]
    [1 2] [1  1 2]
    [1 3] [1  1]})

{0 1, 1 1, -1 1, -2 1, -3 1, 2 1}

Provalo online .

Su un singolo core di 6700 K viene eseguito il castoro occupato a 2 simboli a 2 stati (47,1 milioni di passi) in circa 29 secondi, ovvero 1,6 milioni di passi / secondo.


5

MPunta , 4 byte

Ṅ×ịß

Provalo online!

Il collegamento TIO aggiunge un piè di pagina per chiamare la funzione con il programma Tip di esempio mostrato nella pagina Esolang (il "wrapper automatico" di M per chiamare le funzioni come se fossero programmi che non possono gestire numeri razionali o a virgola fissa, o almeno non ho ho capito come dirlo come, quindi ho bisogno di trasformare la funzione in un programma completo a mano per poterlo eseguire.)

Questo in realtà stampa un utile output di debug; il programma non può essere scritto in 3 byte in M ​​perché un programma composto esattamente da tre diadi innesca un caso speciale nel parser, quindi ho dovuto aggiungere un comando aggiuntivo per evitare il caso speciale. Farlo (stampare con newline) almeno gli dà uno scopo utile.

ıi=1

Non implementa l'I / O (diverso da halt / no-halt). L'I / O è un'estensione di Tip (non parte della lingua stessa) e non è necessaria per la completezza di Turing.

Spiegazione / sfondo

Ṅ×ịß
Ṅ     Print {the left argument} and a newline; also resolves a parser ambiguity
  ị   {The left argument}th element of {the right argument}, wrapping on OoB
 ×    Multiply {the left argument} by {the chosen element}
   ß  Recursive call; arguments: {the product} and {the same right argument}

[1,2,3][1,2,3,1,2,3,1,2,3,…]rx+s, che è un polinomio, e la "conversione di base" incorporata in molte lingue del golf è in realtà un valutatore polinomiale per scopi generici sotto mentite spoglie. Quindi tutto ciò che dobbiamo fare è indicizzare in un elenco di elenchi di cifre, convertirli in base e abbiamo finito, giusto?

xx

x(xy)xy. Certo, potremmo sovrascrivere il comportamento di concatenamento praticamente a tutto ciò che vogliamo, ma costerebbe un intero byte e le voci del linguaggio golf a questa domanda stanno diventando così brevi che un byte è molto.

Quindi ho guardato indietro e rivalutato un po '. Ci sono operazioni che potremmo usare al posto della valutazione polinomiale? Idealmente, quelli che sono commutativi, quindi non dobbiamo preoccuparci dell'ordine degli argomenti? Poco dopo, mi sono reso conto che le funzioni di Collatz sono più complesse di quanto debbano essere.

s

E, ovviamente, a differenza della conversione di base ( ), la moltiplicazione ( ×) è commutativa, e quindi non importa in quale ordine sono collocati gli argomenti. Quindi tutto ciò di cui abbiamo bisogno è scrivere ×ị, e quindi posizionare il programma in una ricorsione infinita con ß, e abbiamo un linguaggio completo di Turing. Destra?

(xy)(xy)¹×ịß¹¹ è una buona scelta perché produce un utile output di debug.

Sono possibili tre byte? A meno che non mi manchi qualcosa, non con questa specifica scelta di linguaggio implementativo e implementato, ma a questo punto sembra sicuramente che sarebbe possibile in qualche modo, poiché ci sono così tanti modi per farlo in quattro e così tanti Turing-complete lingue che potresti implementare.


Dopo averci pensato un po 'di più, potremmo ottenere questo fino a tre byte usando e piuttosto che ×e ; la lingua risultante non è esattamente la stessa lingua di Tip, ma è abbastanza simile e quasi certamente Turing completa per lo stesso motivo. Sfortunatamente, non è implementato in M ​​e non riesco a trovare alcun modo per fare in modo che Jelly esegua calcoli di precisione arbitraria quando uno degli input è un numero reale non intero. Se qualcuno conosce altre lingue del golf dove questa costruzione potrebbe funzionare, sentiti libero di provarlo.
ais523,

4

C interpretando Brainfuck, 187 byte

t[999],*p=t,c,i,l;f(char*t){for(i=0;c=t[i];i++){c^62?c^60?c^43?c^45?c^46?c^44?c^91:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;if(c==93&&*p)for(l=1;l>0;)c=t[--i],c==91?l--:c==93?l++:0;}}

Provalo online


3
Welp, c'era sicuramente una risposta usando BF.
Zacharý,

4

Lua interpretando Brainf ***, 467 byte

b,r,a,i,n,s=0,io.read,{0},1,1,"><+-.,[]"c,f=r(),{function()n=n+1;a[n]=a[n]or 0;end,function()n=n-1;a[n]=a[n]or 0;end,function()a[n]=a[n]+1;end,function()a[n]=a[n]-1;end,function()io.write(string.char(a[n]))end,function()a[n]=io.read():byte()end,function()i=a[n]~=0 and i or c:find("]",i)end,function()if a[n]~=0 then b,x=1,""repeat i=i-1 x=c:sub(i,i)b=x=="["and b-1 or x=="]"and b+1 or b until b==0 and x=="["end end}repeat f[s:find(c:sub(i,i),1,1)]()i=i+1 until i>#c

So che c'è ancora qualche dimagrimento che posso fare in seguito, ma ecco dove è finito il mio primo passaggio. Prende il codice Brainf dall'input standard.


2
+1 per il brains, è sempre divertente quando i golfisti assegnano a un elenco di variabili.
Zacharý,

4

CJam → ResPlicate Variant, 15 14 13 byte

-1 byte grazie a @ ais523

l~{(/((*+e_}h

La variante è la stessa di quella in questa risposta , tranne per il fatto che il numero di elementi tolti dalla coda è uno in meno del numero in cima alla coda.

La l~{ ... }hparte accetta solo una matrice come input e si ripete fino a quando la matrice non è vuota.

Spiegazione per il ciclo principale:

    e# Stack:             | [3 2 1 1 2 2 2 1]
(   e# Pop first element: | [2 1 1 2 2 2 1] 3
/   e# Split chunks:      | [[2 1 1] [2 2 2] [1]]
(   e# Pop first:         | [[2 2 2] [1]] [2 1 1]
(   e# Pop first:         | [[2 2 2] [1]] [1 1] 2
*   e# Repeat array:      | [[2 2 2] [1]] [1 1 1 1]
+   e# Concatenate:       | [[2 2 2] [1] 1 1 1 1]
e_  e# Flatten:           | [2 2 2 1 1 1 1 1]

Non hai davvero bisogno dell'incremento qui. Basta specificare che la lunghezza dei blocchi deve essere incrementata di 1 nel programma originale; ciò non pregiudica la completezza di Turing di ResPlicate (ci sono costruzioni TC in cui le lunghezze dei blocchi e i conteggi ripetuti non sono mai mescolati tra loro).

3

Chip , 20 + 3 = 23 byte (Regola 110)

AZZ
>}/a
`)\'E~Zte*f

+3 per la bandiera -z

Provalo online!

Questo invio non è perfetto, poiché Chip non ha (ancora) alcuna capacità di looping, quindi l'output deve essere passato come input per simulare più generazioni, con qualcosa del genere (ovviamente, potresti eseguire quel loop indefinitamente, e Chip può gestire input arbitrariamente lunghi, quindi questa combinazione è Turing Complete).

Questa implementazione accetta input e output in forma di ASCII 0s e 1s. La logica qui è la seguente:

p := value of left neighbor cell    AZZ
q := value of current cell          AZ
r := value of right neighbor cell   A

q' := ((r xor q) and p) or          >}/a
      ((r or q) and ~p)             `)\'

Il resto degli elementi è per le pulizie: e*fcausa l'output numerico ASCII e E~Zttermina l'esecuzione di due byte dopo che l'input è esaurito (poiché la larghezza aumenta di 2 ogni generazione).


3

Clojure, 75 byte (sistema di tag ciclico)

Aggiornamento 1: sostituito some?con nil?.

Aggiornamento 2: risolto un Sramo mancante in else di if s.

#(loop[[p & P](cycle %)[s & S]%2](if(nil? s)S(recur P(if s(concat S p)S))))

Implementa il sistema di tag ciclico , restituisce nilse il programma si interrompe, esegue il loop per sempre altrimenti. Clojure brilla davvero qui con infinite sequenze pigre (come il ciclo ) e destrutturanti . Quelli e zeri sono indicati come valori veri e falsi. Quando la stringa di dati si esaurisce sdiventa nil.

Ungolfed:

(def f #(loop[[p & P] (cycle %) [s & S] %2 i 5]
          (do
            (pprint [p (concat [s] S)])
            (if (and (some? s) (pos? i))
              (recur P (if s (concat S p) S) (dec i))))))

Risultati di esempio:

(f [[false]] [true true])
[[false] (true true)]
[[false] (true false)]
[[false] (false false)]
[[false] (false)]
[[false] (nil)]

(f [[false true true] [true false] [true false true]] [true])
[[false true true] (true)]
[[true false]      (false true true)]
[[true false true] (true true)]
[[false true true] (true true false true)]
[[true false]      (true false true false true true)]
[[true false true] (false true false true true true false)]

2

Interpretazione JavaScript Regola 110 , 131 byte (99 byte ?, 28 byte?)

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}
c=(l,n)=>!n?l:c(b(0+l+0),n-1)

Come si può vedere, il codice definisce 3 funzioni, a, be c. Forse è possibile salvare i byte combinandoli in 1 funzione (non vedo come), ma è positivo che siano separati perché ognuno di essi già soddisfa in qualche modo questa sfida.

La funzione aaccetta 3 numeri come input e ne calcola uno strano polinomio. Quando questi 3 numeri sono 0o 1possono essere visti come Regola 110 celle. La parità dell'output di apuò quindi essere vista come il valore della cella centrale nella generazione successiva. Quindi, in un certo senso, questa semplice funzione è già un 'interprete' della Regola 110 (28 byte):

a=(p,q,r)=>(q+r+q*r+p*q*r)%2

Possiamo quindi creare una nuova funzione bche valuta aogni carattere di una stringa di uno e zeri. Questo bè quindi, in un modo migliore di a, un interprete della Regola 110. Prendendo mod 2 dopo la valutazione di parentesi di salvataggio (99 byte):

a=(p,q,r)=>q+r+q*r+p*q*r
b=l=>{r="";for(i=0;i<l.length-2;i++)r+=a(l[i],+l[i+1],+l[i+2])%2;return r}

Per calcolare effettivamente una funzione con la Regola 110, l'utente deve specificare lo stato iniziale e il numero di generazioni dopo le quali "l'output" apparirà. Possiamo creare una terza funzione cche accetta una stringa di uno e zeri e un numero intero positivo n, che quindi valuta bsulla stringa, i ntempi. In questo modo possiamo davvero vedere la Regola 110 come un linguaggio di programmazione, in cui un programma è uno stato iniziale e un numero ne l'output è lo stato dopo ngenerazioni. La funzione cora è un vero interprete per quel linguaggio di programmazione, quindi il codice finale per questa sfida è quello che ho presentato sopra.


Questo calcola 110 con lo sfondo corretto? Una mia precedente risposta è stata cancellata perché non aveva lo sfondo.
Wheat Wizard

@WheatWizard lo sfondo fa parte dell'input, la tua risposta non dovrebbe essere stata cancellata per questo
Jens Renders

Lo sfondo dovrebbe essere infinito, puoi prendere input infiniti?
Wheat Wizard

@WheatWizard non deve essere infinito, deve poter essere reso arbitrariamente grande, e può
Jens Renders

1
La regola 110 non è completa se decidi in anticipo la generazione e hai bisogno di input infiniti nella costruzione che conosco. Anche se qualcuno ha trovato una costruzione con uno stato iniziale finito, non è possibile conoscere la memoria o il tempo necessario prima dell'esecuzione del programma, perché in questo modo è possibile risolvere il problema di interruzione.
Ørjan Johansen

2

JS -> Newline 854 byte

(function(d){var b=0;var n=!0;var c=[];var h=[];var e=0;var l=[];var m=0;var f=2;var a=0;var g=!1;var k=function(a){if(a===1)return!1;if(a%2===0&&a!==2)return!1;if(a%3===0&&a!==3)return!1;if(a%5===0&&a!==5)return!1;if(a%7===0&&a!==7)return!1;for(var b=7;b<d.round(d.sqrt(a))+1;b++)if(a%b===0)return!1;return f=a,!0;};var j=0;var i=0;var o=function(q){var o=d.__split(q,'\n');d.println(o);for(var n=0;n<o.length;n++)if(n>=f^2&&n<=f+1^2&&k(n)){f=n;for(var p=0;p<o[n].length;p++){if(o[n]==='+'&&(a+=c[b],b++),o[n]==='-')if(g===!0&&a<=0)break;else a-=c[b],b++;if(o[n]==='*'&&(a*=c[b],b++),o[n]==='/'&&(a/=c[b],b++),o[n]==='s'&&(a=d.sqrt(a)),o[n]==='%'&&(a%=c[b],b++),o[n]==='a'&&l.push(a),o[n]==='g'&&(a=c[b],b++),o[n]==='q'&&c.push(a),o[n]==='i'&&a++,o[n]==='d')if(g===!0&&a<=0)break;else a--;o[n]==='r'&&(g=!0),o[n]==='w'&&(g=!1),o[n]==='['&&(j=n),o[n]===']'&&a>0&&(n=j,h[e]--),o[n]==='{'&&(i=n),o[n]==='}'&&h[e]>0&&(n=i,h[e]--),m=a,o[n]==='k'&&e++;}}};});

Super golf grazie a Google.


Penso che tu abbia pubblicato questa risposta alla sfida sbagliata. Intendevi postarlo in questa sfida ?

1
In tal caso, è necessario modificare l'implementazione per mirare alle diverse condizioni di vittoria; questo è code-golf , non concorso di popolarità . Ad esempio, hai molti nomi di variabili che potrebbero essere chiaramente più brevi, il che significa che questa soluzione non è un serio concorrente. Potresti forse cancellarlo per ora e poi ripristinarlo quando hai tempo di giocarlo.

1
Tuttavia, le risposte che non fanno un serio tentativo di ottimizzazione per la condizione di vittoria sono contro le regole . Questo è un motivo sufficiente per eliminarlo fino a quando non puoi renderlo conforme alle regole.

1
Puoi combinare tutte le varaffermazioni:var b=0,n=!0,c=[],h=[],e=0,l=[],m=0,f=2,a=0,g=!1;
Esolanging Fruit,

1
Si prega di rimuovere tutto varty
solo ASCII il

1

Clojure, 87 byte (Regola 110)

Il merito del codice di parità va a Jens Renders! Stavo davvero lottando su come esprimere questo e stavo per andare con la conversione [p q r]da binario a un numero intero e utilizzare una tabella di ricerca.

#(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%)

Qui partitione la distruzione di Clojure rende l'applicazione logica abbastanza semplice. Questa funzione restituisce una sequenza infinita di stati, quindi il chiamante è responsabile di takequanti ne ha bisogno o semplicemente nthper saltare a uno stato specifico. Se i padding con zero fossero due elementi anziché solo uno, il nastro aumenterebbe costantemente, evitando problemi di confine. Ora rimane la larghezza originale.

Esempio:

(def f #(iterate(fn[S](for[[p q r](partition 3 1(concat[0]S[0]))](mod(+ q(* q(+ 1 p)r)r)2)))%))

(pprint (take 5 (f '(0 0 0 0 0 1 1 1 0 0 1 0 0))))
((0 0 0 0 0 1 1 1 0 0 1 0 0)
 (0 0 0 0 1 1 0 1 0 1 1 0 0)
 (0 0 0 1 1 1 1 1 1 1 1 0 0)
 (0 0 1 1 0 0 0 0 0 0 1 0 0)
 (0 1 1 1 0 0 0 0 0 1 1 0 0))

1
Se lavori solo con la larghezza originale, non è possibile che Turing sia completo, perché ha solo memoria finita. (In effetti, tutte le costruzioni note di completezza di Turing dalla Regola 110 richiedono il "padding" che viene utilizzato per espandere la larghezza mentre il programma procede per avere un modello specificato dall'input dell'utente e diverso a sinistra e a destra, piuttosto che usando solo zeri.)

Vedo, questo rende la sua simulazione piuttosto difficile allora. Clojure cyclesarebbe in grado di costruire il modello di imbottitura infinita, ma eseguire il primo passo richiederebbe un infinito lasso di tempo: /
NikoNyrh

Vieni a pensarci bene, non sarebbe troppo difficile prendere quei pattern di riempimento come argomenti aggiuntivi ed espandere il nastro simulato di 1 blocco a sinistra e a destra. La velocità delle informazioni qui è di 1 blocco / iterazione, quindi dobbiamo solo simulare il "cono di luce" attorno al blocco centrale che ha la struttura asimmetrica. (CMIIW)
NikoNyrh

1

APL (Dyalog) → variante di Fractran , 15 byte

(⊃0~⍨××0=1|×)⍣≡

Provalo online!

La funzione accetta le razionali come un elenco di numeri anziché due elenchi contenenti il ​​numeratore e il denominatore e genera il risultato se il programma termina. Questo implementa una variante di Fractran che ha il 1/1 razionale (= 1) alla fine del programma. L'1 non ha alcun effetto sulla completezza di Turing (per quanto ho capito) perché l'input al programma atterra sull'1 solo quando nessuno degli altri razionali funziona, e quando lo fa, l'input non viene modificato. Questo viene utilizzato solo in modo che la funzione sappia quando terminare.

Il collegamento TIO esegue la funzione per 2 iterazioni (in modo che sia possibile vedere l'output poiché il programma non termina) sul primo input ed esegue il secondo input fino al completamento, dopodiché restituisce l'output.

(⊃0~⍨××0=1|×)⍣≡ prende l'elenco dei razionali come argomento di sinistra, da definire come ⊣, e l'input come argomento di destra, da definire come ⊢

(⊃0~⍨××0=1|×) treno di funzioni

  • 1|×ottenere la parte dopo il punto decimale (modulo 1) del prodotto ×di ⊣ e ⊢

  • 0= è uguale a 0?

  • ×× moltiplica questo risultato per ⊣ × ⊢, ovunque il × × razionale non sia un numero intero, viene sostituito con 0

  • 0~⍨ rimuove tutti gli 0

  • ottieni il primo elemento

ciclo fino a quando l' ingresso non cambia, si noti che il risultato di (⊃0~⍨××0=1|×)viene riutilizzato come ingresso, quindi se smette di cambiare (come risultato di 1 alla fine) il programma si arresta


1

JavaScript: Lambda Calculus ( 123 114)

Rappresentato usando Debruijn Indicies in Duples.

V=function b(c,d){if(!isNaN(c)){for(;--c;)d=d[1];return d[0]}return 0==c[0]?e=>b(c[1],[e,d]):b(c[0],d)(b(c[1],d))}

Il combinatore S è [0, [0, [0, [[3, 1], [2, 1]]]]]

K è [0, [0, 2]]

Lo sono [0, 1]

Modifica: rasato 9 byte sostituendo "number"==typeof ccon!isNaN(c)


0

APL (Dyalog Unicode) , SBCS 15 byte

Programma completo che implementa un esecutore generalizzato di automi cellulari unidimensionali. Ciò include la Regola 110 che è Turing completa. Richiede stdin per lo stato iniziale, il numero di iterazioni (o per continuare fino a stabile o {⍵≡⎕←⍺}per visualizzare tutti i valori intermedi fino a stabile) e il set di regole.

⎕∊⍨∘(⊢∘⊂⌺3)⍣⎕⊢⎕

Provalo online! (4 ripetizioni dell'articolo 110)

 richiedere lo stato iniziale e

 cedere che (separa lo stato dal numero di iterazioni)

⍣⎕ richiedere il numero di iterazioni e applicare la seguente funzione più volte:

(... ) applica la seguente funzione tacita:

  ⌺3 ottenere tutti i quartieri di lunghezza 3 (con informazioni sul fatto che siano al limite) e applicare la seguente funzione tacita a ciascuna coppia:

    racchiudere il quartiere

    e

    rendilo (scartando le informazioni sull'essere ai margini)

 poi

∊⍨ controlla se sono membri di

 richiede un elenco di quartieri che portano ad essere attivi nella prossima iterazione

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.