Interpreta TwoMega


9

In questa sfida, si scriverà un interprete per 2 Ω (trascritto come TwoMega ), un linguaggio basato vagamente su Brainfuck con uno spazio di archiviazione infinito-dimensionale.

La lingua

2 Ω contiene tre parti di stato:

  • Il nastro , che è un elenco infinito di bit, tutti inizializzati su 0. Ha un elemento all'estrema sinistra, ma nessun elemento all'estrema destra.

  • Il puntatore di memoria , che è un numero intero non negativo che è un indice di un elemento nel nastro. Un puntatore di memoria superiore si riferisce a una cella a nastro più a destra; un puntatore di memoria pari a 0 fa riferimento all'elemento più a sinistra. Il puntatore di memoria è inizializzato su 0.

  • L' ipercubo , che è una "scatola" di celle concettualmente ∞- dimensionale, ognuna delle quali contiene un bit inizializzato su 0. La larghezza dell'ipercubo è legata in ogni dimensione a solo 2 celle, ma l'infinito delle dimensioni indica il numero di le cellule non sono numerabili .

Un indice nell'ipercubo è un elenco infinito di bit che fa riferimento a una cella nell'ipercubo (allo stesso modo in cui un elenco finito di bit potrebbe essere utilizzato per fare riferimento a un ipercubo di dimensione finita). Poiché il nastro è un elenco infinito di bit, l'intero nastro fa sempre riferimento a un elemento di Hypercube; questo elemento è chiamato referente .

2 Ω dà significato a 7 caratteri diversi:

  • < decrementa il puntatore della memoria di 1. Decrementarlo al di sotto di 0 è un comportamento indefinito, quindi non è necessario gestirlo.
  • > incrementa il puntatore della memoria di 1.
  • ! lancia il bit al referente.
  • . emette il bit al referente.
  • ^sostituisce il bit nella cella a cui punta il puntatore di memoria sul nastro con l' inverso del bit sul referente.
  • [x]esegue il codice xpurché il bit al referente sia 1.

La sfida

Il tuo compito è scrivere un programma che accetta una stringa come input ed esegue quell'input come un programma 2 Ω .

Questo è , quindi vince la risposta valida più breve (misurata in byte).

Appunti

  • Puoi presumere che il programma sarà composto esclusivamente da caratteri <>!.^[]e che []sarà nidificato correttamente.
  • L'interprete dovrebbe essere limitato solo dalla memoria disponibile sul sistema. Dovrebbe essere in grado di eseguire i programmi di esempio in un ragionevole lasso di tempo.

Programmi di esempio

Stampa 1:

!.

Stampa 010:

.!.!.

Stampa 0 per sempre:

![!.!]

Stampa 0 per sempre o 1 per sempre se !è anteposto:

[.]![!.!]

2
Una piccola nota: il numero di celle di archiviazione non è effettivamente numerabile, poiché il numero di 1s sul nastro è sempre finito. In effetti, esiste una biiezione abbastanza semplice tra i numeri naturali e gli stati del nastro (interpretare il contenuto del nastro come un numero binario all'indietro), il che dimostra che Hypercube è fondamentalmente un array 1D infinito, a cui si accede lanciando i bit in un valore di puntatore intero , invece di in / decrementare come in brainfuck.
Lynn,

Inoltre, re: il tuo invito a scrivere un catprogramma: non sembra esserci un'istruzione per ricevere input.
Lynn,

2
Penso che dovrebbero esserci programmi di esempio che usano più del set di istruzioni. Due semplici: .- stampa un singolo zero e poi esiste; !^!.- ne stampa una sola, quindi esce. Più sarebbe buono però. Al momento è necessario comprendere i contributi per verificarli (e quindi migliorarli!)
Jonathan Allan,

@Lynn L'input verrebbe dato avendo un 1 o uno 0 sulla cella [0,0,0,0,0,0,0...](cioè la presenza di !a all'inizio del programma).
Esolanging Fruit,

Quindi potresti fare [.]![!.!]per stampare il valore di quella cella per sempre
Leo

Risposte:


2

Python 2 , 167 byte

t=h=I=0
m=1
E=''
for c in input():i='[<>!.^]'.find(c);E+=' '*I+'while+2**t&h: m/=2 m*=2 h^=2**t print+(2**t&h>0) t=t&~m|m*(2**t&h<1) #'.split()[i]+'\n';I-=~-i/5
exec E

Provalo online!

t è il nastro. t = 6 indica che il nastro è [0 1 1 0 0 0…]

m è 2 alla potenza del puntatore di memoria. Quindi m = 8 significa che stiamo puntando al bit 3 del nastro.

h è l'ipercubo. h = 80 (set di bit 4 e 6) indica che i bit in [0 0 1 0…] e [0 1 1 0…] sono impostati.

Per leggere il bit al referente, controlliamo 2 t & h . Per capovolgere, eseguiamo h ^ = 2 t .

Traduciamo le istruzioni in codice Python ed eseguiamo il risultato. Ho memorizza il livello di rientro dei loop mentre.


Il tuo programma o il secondo caso di test sono sbagliati
wastl

@wastl Il secondo caso di test era sbagliato. ;)
DLosc


2

JavaScript (Node.js) , 148 byte

x=>eval(x.replace(e=/./g,c=>({'<':'u/=2','>':'u*=2','!':'e[v]^=1','.':'alert(+!!e[v])','^':'v=(v|u)^u*e[v]','[':'while(e[v]){'}[c]||'}')+';',v=u=1))

Provalo online!

È completo

BoolFuck TwoMega
< >^>^>[!]^<<<<[!]^>>[!]!^>[!]!^>[!]!^<<<<(>^>^>1<<<<1>>0>0>0<<<<)
> ^<^<[!]^>>>>[!]^<<[!]!^<[!]!^<[!]!^>>>(^<^<1>>>>1<<0<0<0>>>)

È necessario init come spostarsi di pochi posti e inizializzare un bit dell'indirizzo corrente e destro come 1 ( >>>>>>>>^>^<)

Provalo online!

Place nin BoolFuck è scritto come (0, 0, ..., 0(n*0), [1], 1, 0, 0, ...).

Per >, fa n=>n+1

     0 0 0 0 0[1]1 0 0 0 0
^    0 0 0 0 0[x]1 0 0 0 0
<    0 0 0 0[0]x 1 0 0 0 0
^    0 0 0 0[y]x 1 0 0 0 0, yx != 01
<    0 0 0[0]y x 1 0 0 0 0
[!]^ 0 0 0[1]y x 1 0 0 0 0, (0yx10) = 0
>>>> 0 0 0 1 y x 1[0]0 0 0
[!]^ 0 0 0 1 y x 1[1]0 0 0, (1yx10) = 0
<<   0 0 0 1 y[x]1 1 0 0 0
[!]! 0 0 0 1 y[x]1 1 0 0 0, (1yx11) = 1
^    0 0 0 1 y[0]1 1 0 0 0
<    0 0 0 1[y]0 1 1 0 0 0
[!]! 0 0 0 1[y]0 1 1 0 0 0, (1y011) = 1
^    0 0 0 1[0]0 1 1 0 0 0
<    0 0 0[1]0 0 1 1 0 0 0
[!]! 0 0 0[1]0 0 1 1 0 0 0, (10011) = 1
^    0 0 0[0]0 0 1 1 0 0 0
>>>  0 0 0 0 0 0[1]1 0 0 0

Lo stesso di come <funziona


Sei sicuro che questa traduzione sia valida? !>.stampa 1in boolfuck ma si traduce in !>^.quale stampa 1 in TwoMega ( >non influenza il nastro; ^non influenza il nastro poiché il referente è 1)
Esolanging Fruit

@EsolangingFruit +>;do [1]00... 1[0]0...(output 0), !>^.do (0,0,...)=1, ptr=([0],0,...) (0,0,...)=1, ptr=(0,[0],...) (0,0,...)=1, ptr=(0,[1],...)(output 0), cosa c'è che non va?
l4m2

@EsolangingFruit for !>., only >è un comando valido in boolfuck ...
ASCII

1
@ l4m2 In TwoMega, !inverte il referente, non la cella a nastro.
Esolanging Fruit,

@EsolangingFruit quindi cosa c'è che non va qui?
l4m2

1

Brain-Flak Classic , 816 byte

<>(((<(())>)))<>{(([][][])(((({}){}[])({}))({})[]([][](({})(({}())(({}){}{}({}(<()>))<{<>({}<>)}{}>))))))(([]{()(<{}>)}{}){<((<{}>))<>(()(){[](<{}>)}{}<{({}[]<({}<>)<>>)}{}{}>)<>({()<({}<>)<>>}<<>{<>(({}){}<>({}<>)[])<>}{}<>({()<({}[]<<>({}<>)>)>}{})<>(({})<<>{({}[]<({}<>)<>>)}({}<>)<>{({}<>)<>}>)<>>)<>({}<>)<>>}{}([]{()(<{}>)}{}){{}<>({})(<>)}{}([]{()(<{}>)}{}){(<{}<>({}<{((<({}[])>))}{}{((<(())>))}{}>)<>>)}{}([]{()(<{}>)}{}){(<{}<>({}<({}())>)<>>)}{}([]{()(<{}>)}{}){(<{}<>[({})]<>>)}{}([]{()(<{}>)}{})<{((<{}>))<>{}({}<{<>(({}){}<>({}<>)[])<>}{}<>({()<({}[]<<>({}<>)>)>}{})<>(((){[](<{}>)}{})<<>{({}[]<({}<>)<>>)}{}(<>)<>{({}<>)<>}>)<>>)<>({}<>)<>}{}(<>)<>{({}<>)<>}{}>()){((({}[]<>){(<{}({}<>)>)}{}())<{({}<({}<>)<>((((((([][][]){}){}){}()){}){}({})())[][])>{[](<{}>)}{}{()(<{}>)}{})}{}({}<>)>[]){{}(<>)}}{}}

Provalo online!

Questo codice è stato scritto solo per avere un posto dove scrivere una prova della completezza di Turing.

Prova della completezza di Turing

Mostriamo una riduzione da Boolfuck a TwoMega:

Boolfuck   TwoMega
>          >>
<          <<
.          !^!.!^!
[          !^![!^!
]          !^!]!^!
+          !^[!]^[>!^<[!]!^>[!]!^<]

Questa traduzione memorizza lo stato Boolfuck nelle celle a nastro pari in TwoMega. Tutti i comandi tradotti conserveranno i seguenti invarianti:

  • Il puntatore di memoria si trova su una cella pari.
  • Tutte le celle a nastro dispari sono zero.
  • Per ogni possibile nastro con tutte le celle dispari zero, il valore corrispondente sull'ipercubo è zero.

Lo snippet !^!manterrà [0]0costante e scambia tra 0[0]e [1]1(dove l'attenzione è limitata alla linea sull'ipercubo raggiungibile senza spostare il puntatore di memoria). Come tale, viene utilizzato per inserire temporaneamente il valore corrente del nastro nel referente per i comandi Boolfuck che si occupano di esso.

Se a TwoMega fosse assegnato un comando di input ,con la semantica prevista, il comando Boolfuck ,si tradurrebbe in >^<,!^>[!]!^<. Poiché ,non è necessario dimostrare che Boolfuck è Turing completo, la mancanza di un comando di input non influisce su questa prova.


Memorizza principalmente le informazioni nella posizione nell'ipercubo piuttosto che nel cubo stesso?
l4m2

@ l4m2 La mia riduzione da BoolFuck non memorizza alcun dato nel cubo stesso. Qualsiasi 1 che faccio sull'ipercubo è lì solo per impostare celle a nastro su 0.
Nitrodon

0

Python 3 , 297 284 274 byte

-10 byte grazie a ovs e Jonathan Allan

C=input()
h={}
t=set()
def f(C,p):
 c=C[0];r=hash(frozenset(t));v=h.get(r,0)
 p={"<":p-1,">":p+1}.get(c,p)
 if'"'>c:h[r]=not v
 if"."==c:print(int(v))
 if"]"<c:t.discard(p)if v else t.add(p)
 if"["==c:
  while f(C[1:],p):1
 else:return c=="]"and v or C and f(C[1:],p)
f(C,0)

Provalo online!


t.discard(p)->t-={p}
shooqie

@shooqie Non funziona se non lo tè global.
Fergusq,

@fergusq Anche se sono abbastanza sicuro che funzioni se dichiari fcomef(C,p,t=set())
shooqie

0

Pip , 75 71 byte

lPB0aR:^"!><[].^_""!:_
--viPU0
++v
W_{
}
O_
i@v:!_LFBilPB0
l@FBi"^n;Vau

Provalo online!

Traduce il codice 2 Ω in un codice Pip equivalente e lo valuta.

Usiamo iper rappresentare il nastro, vper il puntatore del nastro * e lper l'ipercubo. I primi due vengono preinizializzati su valori utili; linizia come [], a cui si preme a 0( lPU0) per evitare problemi di indicizzazione-elenco vuoto.

* In realtà, è la negazione bit a bit del puntatore a nastro, perché stiamo memorizzando il nastro all'indietro per una più facile conversione in decimale.

Il resto del codice è:

aR:...;     Do a bunch of replacements in a, translating it into Pip code
       Va   Evaluate a
         u  Suppress output of the final expression that was evaluated

La tabella di traduzione:

!  !:_
>  --viPU0
<  ++v
[  W_{
]  }
.  O_
^  i@v:!_LFBilPB0
_  l@FBi

l@FBiè il referente: elemento dell'ipercubo lall'indice (converti ida binario). Appare spesso, quindi lo chiamiamo _e lo sostituiamo _con il codice reale alla fine.

  • !:_ nega logicamente il referente in atto.

  • --viPU0decrementi v(spostando il puntatore del nastro verso destra); spinge quindi un altro 0sul lato sinistro di i, per assicurarsi che il puntatore del nastro rimanga nei limiti.

  • ++vincrementi v(non è necessario il controllo dei limiti, per OP).

  • W_{esegue un ciclo mentre il referente è veritiero (ovvero diverso da zero, ovvero 1).

  • } chiude il ciclo.

  • O_ genera il referente senza newline.

Infine, per ^:

i@v:            Set the current tape cell to
    !_          The logical negation of the referent
                Now, make sure the list representing the hypercube is long enough:
      LFBi      Loop frombinary(i) times:
          lPB0  Push another 0 to the end of l
                This ensures that FBi will always be a valid index into l
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.