Interpreta TwoMega


9

En este desafío, escribirás un intérprete para 2 Ω (transcrito como TwoMega ), un lenguaje basado libremente en el cerebro con un espacio de almacenamiento de dimensiones infinitas.

El idioma

2 Ω contiene tres partes de estado:

  • La cinta , que es una lista infinita de bits, todos inicializados a 0. Tiene un elemento situado más a la izquierda, pero ningún elemento situado a la derecha.

  • El puntero de memoria , que es un entero no negativo que es un índice de un elemento en la cinta. Un puntero de memoria más alto se refiere a una celda de cinta más a la derecha; un puntero de memoria de 0 se refiere al elemento más a la izquierda. El puntero de memoria se inicializa a 0.

  • El Hypercube , que es una "caja" de celdas conceptualmente -dimensional, cada una de las cuales contiene un bit inicializado a 0. El ancho del Hypercube está limitado en cada dimensión a solo 2 celdas, pero el infinito de dimensiones significa el número de Las células son incontables .

Un índice en el hipercubo es una lista infinita de bits que se refiere a una celda en el hipercubo (de la misma manera que una lista finita de bits podría usarse para referirse a un hipercubo de dimensión finita). Debido a que la cinta es una lista infinita de bits, toda la cinta siempre se refiere a un elemento del hipercubo; Este elemento se llama el referente .

2 Ω da significado a 7 caracteres diferentes:

  • < disminuye el puntero de memoria en 1. Disminuirlo por debajo de 0 es un comportamiento indefinido, por lo que no necesita manejarlo.
  • > incrementa el puntero de memoria en 1.
  • ! le da la vuelta al referente.
  • . saca el bit en el referente.
  • ^reemplaza el bit en la celda señalada por el puntero de memoria en la cinta con el inverso del bit en el referente.
  • [x]ejecuta el código xsiempre que el bit en el referente sea 1.

El reto

Su tarea es escribir un programa que tome una cadena como entrada y la ejecute como un programa de 2 Ω .

Este es el , por lo que gana la respuesta válida más corta (medida en bytes).

Notas

  • Puede suponer que el programa consistirá únicamente en los personajes <>!.^[]y que []estará anidado correctamente.
  • Su intérprete solo debe estar limitado por la memoria disponible en el sistema. Debería poder ejecutar los programas de muestra en un período de tiempo razonable.

Programas de muestra

Imprimir 1:

!.

Imprimir 010:

.!.!.

Imprimir 0 para siempre:

![!.!]

Imprima 0 para siempre o 1 para siempre si !se antepone:

[.]![!.!]

2
Una pequeña nota: el número de celdas de almacenamiento no es realmente incontable, ya que el número de 1s en la cinta siempre es finito. De hecho, existe una biyección bastante simple entre los números naturales y los estados de la cinta (interpretar el contenido de la cinta como un número binario hacia atrás), lo que muestra que el Hypercube es básicamente una matriz 1D infinita, a la que se accede volteando bits en un valor de puntero entero , en lugar de disminuir / disminuir como en brainfuck.
Lynn

Además, re: su invitación a escribir un catprograma: no parece haber una instrucción para recibir aportes.
Lynn

2
Creo que debería haber programas de muestra que usen más del conjunto de instrucciones. Dos simples: .imprime un solo cero y luego existe; !^!.- imprime uno y luego sale. Sin embargo, más sería bueno. Por el momento, uno debe comprender los envíos para verificarlos (¡y por lo tanto votarlos!)
Jonathan Allan

@Lynn La entrada se daría al tener un 1 o un 0 en la celda [0,0,0,0,0,0,0...](es decir, la presencia de un !al inicio del programa).
Esolanging Fruit

Entonces podría hacer [.]![!.!]para imprimir el valor de esa celda para siempre
Leo

Respuestas:


2

Python 2 , 167 bytes

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

Pruébalo en línea!

t es la cinta. t = 6 significa que la cinta es [0 1 1 0 0 0…]

m es 2 a la potencia del puntero de memoria. Entonces m = 8 significa que estamos apuntando al bit de cinta 3.

h es el hipercubo. h = 80 (conjunto de bits 4 y 6) significa que los bits en [0 0 1 0…] y [0 1 1 0…] están configurados.

Para leer el bit en el referente, verificamos 2 t & h . Para voltearlo, realizamos h ^ = 2 t .

Traducimos las instrucciones al código Python y ejecutamos el resultado. Me almacena el nivel de sangría de los ciclos while.


Ya sea que su programa o el segundo caso de prueba
estén

@wastl El segundo caso de prueba estaba mal. ;)
DLosc


2

JavaScript (Node.js) , 148 bytes

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))

Pruébalo en línea!

Está completando

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

Necesita init moviéndose a la derecha unos pocos lugares e inicie el bit actual y correcto de la dirección como 1 ( >>>>>>>>^>^<)

Pruébalo en línea!

Place nin BoolFuck se escribe como (0, 0, ..., 0(n*0), [1], 1, 0, 0, ...).

Para >, lo hace 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

Igual a como <funciona


¿Estás seguro de que esta traducción es válida? !>.imprime 1en boolfuck, pero traduce a las !>^.cuales imprime 1 en TwoMega ( >no afecta la cinta; ^no afecta la cinta ya que el referente es 1)
Esolanging Fruit

@EsolangingFruit +>;do [1]00... 1[0]0...(salida 0), !>^.do (0,0,...)=1, ptr=([0],0,...) (0,0,...)=1, ptr=(0,[0],...) (0,0,...)=1, ptr=(0,[1],...)(salida 0), ¿qué pasa?
l4m2

@EsolangingFruit for !>., only >es un comando válido en boolfuck ...
Solo para ASCII

1
@ l4m2 En TwoMega, !invierte el referente, no la celda de la cinta.
Esolanging Fruit

@EsolangingFruit, ¿qué pasa aquí?
l4m2

1

Brain-Flak Classic , 816 bytes

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

Pruébalo en línea!

Este código fue escrito solo para tener un lugar para escribir una prueba de integridad de Turing.

Prueba de integridad de Turing

Mostramos una reducción de Boolfuck a TwoMega:

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

Esta traducción almacena el estado de Boolfuck en las celdas de cinta pares en TwoMega. Todos los comandos traducidos preservarán los siguientes invariantes:

  • El puntero de memoria está en una celda de número par.
  • Todas las celdas de cinta con números impares son cero.
  • Para cualquier cinta posible con todas las celdas impares cero, el valor correspondiente en el hipercubo es cero.

El fragmento !^!se mantendrá [0]0constante e intercambiará entre 0[0]y [1]1(donde la atención se limita a la línea en el hipercubo accesible sin mover el puntero de memoria). Como tal, se utiliza para poner temporalmente el valor de la cinta actual en el referente de los comandos de Boolfuck que se preocupan por él.

Si TwoMega recibiera un comando de entrada ,con la semántica esperada, el comando Boolfuck ,se traduciría a >^<,!^>[!]!^<. Como ,no es necesario demostrar que Boolfuck está completo en Turing, la falta de un comando de entrada no afecta esta prueba.


¿Almacena principalmente información en la posición en el hipercubo en lugar del cubo en sí?
l4m2

@ l4m2 Mi reducción de BoolFuck no almacena ningún dato en el cubo en sí. Cualquier 1 que haga en el hipercubo solo está allí para establecer las celdas de cinta en 0.
Nitrodon

0

Python 3 , 297 284 274 bytes

-10 bytes gracias a ovs y 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)

Pruébalo en línea!


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

@shooqie Eso no funciona a menos que lo tsea global.
fergusq

@fergusq Aunque estoy bastante seguro de que funciona si declaras fcomof(C,p,t=set())
shooqie

0

Pip , 75 71 bytes

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

Pruébalo en línea!

Traduce el código de 2 Ω en código Pip equivalente y lo evalúa.

Utilizamos ipara representar la cinta, vpara el puntero de cinta * y lpara el hipercubo. Los dos primeros vienen preinicializados a valores útiles; lcomienza como [], a lo que presionamos a 0( lPU0) para evitar problemas de indexación-lista-vacía.

* En realidad, es la negación bit a bit del puntero de la cinta, porque estamos almacenando la cinta hacia atrás para facilitar la conversión a decimal.

El resto del código es:

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 tabla de traducción:

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

l@FBies el referente: elemento de hipercubo len el índice (convertir ide binario). Aparece a menudo, por lo que lo llamamos _y lo reemplazamos _con el código real al final.

  • !:_ lógicamente niega el referente en su lugar.

  • --viPU0decrementos v(mover el puntero de la cinta hacia la derecha); luego empuja a otro 0hacia el lado izquierdo ipara asegurarse de que el puntero de la cinta permanezca dentro de los límites.

  • ++vincrementos v(sin necesidad de verificación de límites, por OP).

  • W_{ejecuta un bucle mientras el referente es verdadero (es decir, distinto de cero, es decir 1).

  • } cierra el ciclo

  • O_ da salida al referente sin nueva línea.

Finalmente para ^:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.