Hacer un contador Geiger

29

Un contador Geiger es un dispositivo que se usa para detectar radiación.

Haremos un programa de contador Geiger.

Como todos sabemos, cuando la radiación golpea un programa de computadora, elimina exactamente 1 byte al azar. Entonces, un programa contador de Geiger es un programa que en sí mismo no hace nada, pero cuando se elimina cualquier byte, el programa modificado se imprime beeppara indicar la presencia de radiación.

Las respuestas se puntuarán en bytes, siendo menos bytes mejores. Las respuestas deben ser de al menos 1 byte.

Su programa puede imprimir beepcon una nueva línea al final o imprimir una nueva nueva línea para la salida vacía, siempre que lo haga de manera consistente. Su programa también puede utilizar un caso diferente de beepcomo BEEP, bEEPo Beeptanto tiempo como lo hace constantemente.

Asistente de trigo
fuente
Relacionado , relacionado .
Wheat Wizard
77
¿Podemos usar el carácter de control BEL para emitir un pitido real?
Jo King
2
@JoKing Jugué con la idea, es divertido, pero tengo que decir que no. Es muy sustancialmente diferente.
Wheat Wizard
2
Quiero ver una solución en Retina.
mbomb007
3
Estoy tratando de descubrir cómo hacer esto en SMBF ... pero la única forma de comparar dos celdas consiste en cambiarlas. Y en SMBF, las celdas que necesita verificar son las celdas en las que el programa se está ejecutando actualmente. Entonces es como el Principio de incertidumbre de Heisenberg. Por lo tanto, debe determinar si algo cambió utilizando solo el flujo de control.
mbomb007

Respuestas:

24

Perdido , 303 293 263 253 238 228 bytes

v^"peeb"<\>"beepvv"((>@@>>%%>>(((((([[[[[[\
>>>>>>>>>//>>>>>>>>>>>>>>/>>/>>>>>>>>>>>>>\\
>>>>>>>>//>>>>\>>>>>>>>>>/>>>>>>>>>>>>>>>>>\\
>/>>>>>>>/>>>>>>>>>>>>\>>>>>>>>>>>>>>>>>>>>>\\
>>>>>>>>>>>>>>>>>>>>>>\\>>>>\>>>>>>>>>>>>>>>>\

Pruébalo en línea!

Script de verificación (tomado de la respuesta del usuario 202729 ). Desafortunadamente, esto solo puede probar la mitad del código a la vez, pero puede estar seguro de que he probado todo el programa.

Ouch, esta fue una pregunta difícil. Citaré la respuesta eliminada de WW:

Lost es quizás el lenguaje más interesante para este desafío. En Lost, la ubicación y la dirección de inicio del puntero son completamente aleatorias, por lo tanto, para hacer programas deterministas, debe tener en cuenta cada posible ubicación y dirección de inicio. Al mismo tiempo, por la naturaleza de este desafío, también debe tener en cuenta cualquier byte que se elimine.

Desafortunadamente, su respuesta no tuvo en cuenta la eliminación de nuevas líneas, lo que arruinó todo.

Explicación:

(tenga en cuenta que algunos bytes pueden estar apagados aquí y allá)

Primero hablemos de la estructura general del código:

v^^"peeb"<<\/"beepvv"((>>>@@>>%%>>(((((([[[[[[[\       Processing line
>>>>>>>>>>>//>>>>>>>>>>>>>>>>>>>/>>>>>>>>>>>>>>\\      Beep line
>>>>>>>>>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\\     Back-up beep line
>//>>>>>>>>>>>>>>>>>>>>\\>>>>>>>>>>>>>>>>>>>>>>>>\\    Back-up return line
>>>>>>>>>>>>>>>>>>>>>>>>\\>>>>>>\>>>>>>>>>>>>>>>>>\    Return line

Todo menos la línea de procesamiento debe estar completamente compuesto por uno >o por uno \/. ¿Por qué? Bueno, como ejemplo, eliminemos una nueva línea:

v^^"peeb"<<\/"beepvv"((>>>@@>>%%>>(((((([[[[[[[\>>>>>>>>>>>//>>>>>>>>>>>>>>>>>>>/>>>>>>>>>>>>>>\\
>>>>>>>>>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\\
>//>>>>>>>>>>>>>>>>>>>>\\>>>>>>>>>>>>>>>>>>>>>>>>\\
>>>>>>>>>>>>>>>>>>>>>>>>\\>>>>>>\>>>>>>>>>>>>>>>>>\

La primera línea ahora es mucho más larga que el resto del bloque. Si un puntero se generara en un no >\/personaje con movimiento vertical, entonces se quedaría atascado en un bucle infinito.


La parte más grande del detector de radiación es la sección al final de cada línea.

 \
 \\
 >\\
 >>\\
 >>>\

Normalmente, una IP que pasa por esto desde la primera línea saldría de la última línea. Sin embargo, si se elimina cualquier carácter en la línea, entonces esa línea se desplaza hacia abajo, por ejemplo:

 \
 \\
 >\\
 >\\
 >>>\

Y, en cambio, la IP sale de la línea a la que le falta un byte (con la excepción de la última línea, donde sale de la penúltima).

A partir de ahí, cada una de las primeras cuatro líneas redirigirá a la segunda línea:

v
>>>>>>>>>>
>>>>>>>>//
>/

Lo que luego conducirá a cualquiera de las dos beeperas.

v^"peeb"<<\/"beepvv"((>
>>>>>>>>>>//

Si alguno de los bytes en el primer beeper ha sido eliminado, entonces pasa al segundo:

v^^"peb"<<\/"beepvv"((>
>>>>>>>>>>>//

Ambas beepers vuelven a la primera línea y a la terminación @.

Algunas otras partes misceláneas:

Se (((((([[[[[[[usa para borrar la pila cuando el puntero comienza dentro de un par de comillas y termina empujando toda la primera línea para apilar. Desafortunadamente, debe ser tan largo porque la primera línea nueva se puede quitar para hacer que la primera línea doble el tamaño. Experimentar generando el beepuso de aritmética en lugar de comillas terminó por más tiempo.

Los \sys /dispersos a través de las líneas están ahí para los bytes de golf en la línea superior del código al redirigir el puntero a las líneas correctas. Como la mayoría de las líneas de fondo son solo de relleno, solo la línea superior puede jugar al golf. Si alguien tiene alguna idea para una pila más corta a prueba de radiación más clara que la que tengo ahora, siéntase libre de comentar.

Jo King
fuente
Solo por curiosidad, ¿qué tan útil fue la respuesta parcial que publiqué en el chat? Vi algunas similitudes en las versiones anteriores, y me gustaría saber si estaba en el camino correcto.
Wheat Wizard
@WW Ya había estado trabajando en eso para entonces, pero el hecho \/de separar los beepempujes y el hecho de que solo una de las citas necesitaba una cláusula de salida ayudó
Jo King
20

Hexagonía , 38 bytes.

.....;p;<>b;e;/<b;e;;p...@@.......;@..

Pruébalo en línea!

Programa de verificación.


Explicación

Hacemos uso de la autodetección de Hexagony de hexágono de longitud lateral aquí.

Si no se eliminan bytes, el programa tiene una longitud lateral 4 y se ve así:

Programa sin bytes eliminados

Sin embargo, si se elimina un byte. Hay 2 casos.

  1. El byte eliminado es después del segundo < .

    El flujo de ejecución sería:

    Programa con el último byte eliminado

    Hay 2 consecutivos @en la quinta línea, por lo que incluso si se elimina uno de ellos, la IP golpeará con seguridad a @.

  2. El byte eliminado es igual o anterior al segundo <.

    Luego, la segunda mitad permanecerá intacta y la IP ya no se redirigirá hacia arriba <. Imagen del flujo de ejecución:

    Programa con el segundo <code> <</code> eliminado

usuario202729
fuente
19

Hexagonía , 34 29 bytes

//..>;e;<b@;p;/|/;e;;\.b@;p<@

Pruébalo en línea! ¡Verificación!

Explicación:

Aquí está el código normal formateado en un hexágono apropiado usando HexagonyColorer :

No Cancer ...

El doble //al principio asegura que este camino siempre se tome. Si se elimina algún personaje, @se elimina de la ruta, ya sea desplazándose uno hacia atrás o eliminándose a sí mismo:

¡Cáncer!

En este caso, hemos eliminado un carácter después del |, lo que hace que siga este camino, imprimiendo beep:

Primer pitido

Si, en cambio, eliminamos un carácter anterior a |(o al |propio), seguimos la otra impresora de pitidos:

Segundo pitido

Luego consideramos todas las posibilidades y solo beepusamos las partes no irradiadas del programa.

Jo King
fuente
13

Brainfuck auto modificable , 73 63 bytes

<<[[[[<<]]>[[.>>..>>.[,>]]]]   bbeepp+[<<<]>>[[>]>>>.>>..>>.,+]

Pruébalo en línea! ¡Verificación!

Los espacios en el medio del código en realidad representan bytes NUL.

Explicación:

El código se divide en dos secciones por 3 bytes NUL en el medio. Ambos básicamente imprimenbeep si la otra sección está irradiada (con un par de excepciones).

Primero, el <<[[principio es asegurar que todos los ]s coincidan en cualquier momento. [s no intentará buscar una coincidencia ]si la celda es positiva, mientras que ]s . Si alguno ]salta de nuevo a uno de estos soportes, generalmente salta hacia atrás de inmediato porque la celda está0 .

La siguiente parte, [[<<]]>luego verifica si la longitud de la sección 2 es par. Si es así, ejecuta la otra mitad de la sección 1, que imprime beeputilizando el bbeeppal comienzo de la sección 2.

[[.>>..>>.[,>]]]]

Luego borra toda la sección 2 para que no se ejecute.

En la sección 2, verificamos si la longitud de la sección 1 y los bytes NUL es divisible por 3con +[<<<]>>.

[[>]>>>.>>..>>.,+]

Del mismo modo, imprimimos beep.

Jo King
fuente
10

Z80Golf , 53 36 34 bytes

-16 bytes gracias a @Lynn
-2 bytes gracias a @Neil

Dado que este es solo el código de máquina Z80, hay muchos no imprimibles en este, así que tenga un xxd -rhexdump reversible:

00000000: ddb6 2120 10dd b615 280c 003e 62ff 3e65  ..! ....(..>b.>e
00000010: ffff 3e70 ff76 003e 62ff 3e65 ffff 3e70  ..>p.v.>b.>e..>p
00000020: ff76                                     .v

Pruébalo en línea! (probador exhaustivo en Python)

Explicación

z80golf es la máquina Z80 hipotética de Anarchy Golf, donde call $8000es un putchar, call $8003es un getchar, halthace que el intérprete salga, su programa se coloca en $0000, y toda la otra memoria está llena de ceros. Hacer que los programas sean a prueba de radiación en el ensamblaje es bastante difícil, pero una técnica genéricamente útil es usar instrucciones idempotentes de un byte. Por ejemplo,

or c        ; b1    ; a = a | c

es solo un byte y a | c | c == a | c, por lo tanto, puede hacerse a prueba de radiación simplemente repitiendo las instrucciones. En el Z80, una carga inmediata de 8 bits es de dos bytes (donde el inmediato está en el segundo byte), por lo que también puede cargar algunos valores en registros de manera confiable. Esto es lo que hice originalmente al comienzo del programa, para que pueda analizar las variantes más largas que archivé al final de la respuesta, pero luego me di cuenta de que hay una manera más simple.

El programa consta de dos cargas útiles independientes, donde una de ellas podría haber sido dañada por la radiación. Compruebo si se eliminó un byte y si el byte eliminado se encontraba antes de la segunda copia de la carga útil, verificando los valores de algunas direcciones de memoria absolutas.

Primero, debemos salir si no se observó radiación:

    or a, (ix+endbyte) ; dd b6 21 ; a |= memory[ix+0x0021]
    jr nz, midbyte     ; 20 10    ; jump to a halt instruction if not zero

Si se eliminó algún byte, todos los bytes se desplazarán y $0020contendrán el último 76, por $0021lo que será un cero. Podemos permitirnos irradiar el comienzo del programa, a pesar de que prácticamente no hay redundancia:

  • Si $10se elimina el desplazamiento del salto , se detectará correctamente la radiación, no se tomará el salto y el desplazamiento no importará. El primer byte de la próxima instrucción se consumirá, pero dado que está diseñado para ser resistente a la eliminación de bytes, esto no importa.
  • Si $20se elimina el código de operación de salto , el desplazamiento de salto $10se descodificará como djnz $ffe4(consumiendo el siguiente byte de instrucción como el desplazamiento, ver arriba), que es una instrucción de bucle, decremento B, y saltará si el resultado no es cero. Debido a que ffe4-ffffestá lleno de ceros nop, y el contador del programa se ajusta, esto ejecutará el comienzo del programa 256 veces, y finalmente continuará. Estoy sorprendido de que esto funcione.
  • Al eliminarlo $dd, el resto del fragmento se decodificará como or (hl) / ld ($1020), hl, y luego se deslizará a la siguiente parte del programa. El orno va a cambiar cualquier registros importantes, y debido HL es cero en este punto, la escritura también se suprimirá.
  • Si quita el $b6resto, el resto se decodificará como ld ($1020), ixy proceda como se indicó anteriormente.
  • Quitarlo $21hará que el decodificador se coma el $20, desencadenando el djnzcomportamiento.

Tenga en cuenta que el uso or a, (ix+*)ahorra dos bytes ld a, (**) / and a / and agracias a la verificación integrada de cero.

Ahora debemos decidir cuál de las dos copias de la carga útil ejecutar:

    or (ix+midbyte)  ; dd b6 15
    jr z, otherimpl  ; 28 0c
    nop              ; 00
    ; first payload
    ld a, 'b'        ; 3e 62
    rst $0038        ; ff
    ld a, 'e'        ; 3e 65
    rst $0038        ; ff
    rst $0038        ; ff
    ld a, 'p'        ; 3e 70
    rst $0038        ; ff
midbyte:
    halt             ; 76
otherimpl:
    nop              ; 00
    ld a, 'b'        ; 3e 62
    ; ...            ; ...
    rst $0038        ; ff
endbyte:
    halt             ; 76

Las dos copias están separadas por un nop, ya que se usa un salto relativo para elegir entre ellas, y la radiación podría haber cambiado el programa de una manera que haría que el salto saltara el primer byte después del destino. Además, el nop está codificado como cero, lo que facilita la detección de bytes desplazados. Tenga en cuenta que no importa qué carga útil se elija si el interruptor en sí está dañado, porque ambas copias son seguras. Sin embargo, asegurémonos de que no salte a la memoria no inicializada:

  • La eliminación $ddhará que los siguientes dos bytes se decodifiquen como or (hl) / dec d. Clobbers D. No es gran cosa.
  • La eliminación $b6creará una codificación más larga no documentada para dec d. Lo mismo que arriba.
  • La eliminación $15leerá en su $28lugar como el desplazamiento, y la ejecución continuará en el $0c, como a continuación.
  • Cuando $28desaparece, $0cse decodifica como inc c. La carga útil no le importa c.
  • Eliminar $0c: para eso está el nop. De lo contrario, el primer byte de la carga útil se habría leído como el desplazamiento de salto, y el programa saltaría a la memoria no inicializada.

La carga útil en sí es bastante simple. Creo que el tamaño pequeño de la cadena hace que este enfoque sea más pequeño que un bucle, y es más fácil hacer que la posición sea independiente de esta manera. El ede beeprepeticiones, por lo que se pueden reducir la uno ld a. Además, debido a toda la memoria entre $0038y $8000se pone a cero, puedo caer a través de él y utilizar un corto rstvariante de la callinstrucción, que sólo funciona para $0, $8, $10y así sucesivamente, hasta $38.

Enfoques más antiguos

64 bytes

00000000: 2e3f 3f2e 3f3f 7e7e a7a7 201f 1e2b 2b1e  .??.??~~.. ..++.
00000010: 2b2b 6b00 7ea7 2814 003e 62cd 0080 3e65  ++k.~.(..>b...>e
00000020: cd00 80cd 0080 3e70 cd00 8076 003e 62cd  ......>p...v.>b.
00000030: 0080 3e65 cd00 80cd 0080 3e70 cd00 8076  ..>e......>p...v

58 bytes

00000000: 2e39 392e 3939 7e7e a7a7 2019 3a25 00a7  .99.99~~.. .:%..
00000010: 2814 003e 62cd 0080 3e65 cd00 80cd 0080  (..>b...>e......
00000020: 3e70 cd00 8076 003e 62cd 0080 3e65 cd00  >p...v.>b...>e..
00000030: 80cd 0080 3e70 cd00 8076                 ....>p...v

53 bytes

Este tiene una explicación en el historial de edición, pero no es muy diferente.

00000000: 3a34 00a7 a720 193a 2000 a728 1400 3e62  :4... .: ..(..>b
00000010: cd00 803e 65cd 0080 cd00 803e 70cd 0080  ...>e......>p...
00000020: 7600 3e62 cd00 803e 65cd 0080 cd00 803e  v.>b...>e......>
00000030: 70cd 0080 76                             p...v

Qué pasa si: cualquier salida no vacía estaba bien en lugar de pitido

1 byte

v

halts el programa normalmente, pero si la radiación lo elimina, entonces la memoria estará llena de ceros, haciendo $8000ejecutar un número infinito de veces, imprimiendo muchos bytes nulos.

NieDzejkob
fuente
Como acomienza en cero, ¿no puedes usarlo en or a, (N);lugar de ld a, (N); and a;? Parece que puede guardar un par de bytes de esa manera.
Neil
@Neil Buena pregunta! Desafortunadamente, en el Z80, solo las instrucciones de carga pueden tomar direcciones como esta.
NieDzejkob
Ugh, ha pasado demasiado tiempo desde que hice cualquier programación Z80 ... ¿tal vez estaba pensando or a, (ix + N)?
Neil
@Neil en realidad, eso existe, y IX también comienza en cero ... desafortunadamente, guardar un byte en esa área hace que los bytes cambien de tal manera que 20 19al principio se convierta 20 18, y al eliminar el 20crea un salto incondicional hacia atrás, por lo que un nop tiene que agregarse después del primer salto en el programa, invirtiendo el guardado de bytes.
NieDzejkob
Ah, eso es una pena. ¡Gracias por consultar!
Neil
4

Klein , una de cada topología, totalizando 291 bytes

Después de ver la respuesta de WW usando la 001topología, decidí ver qué difícil sería hacer un contador Geiger para cada topología. (Spoiler: muy difícil. Es difícil saber adónde irá el puntero sin gestos con las manos que me hagan ver que estoy descubriendo qué mano es mi izquierda)

¡Verificación!

(También pensé en escribir un programa que sea un contador Geiger válido en todas las topologías, pero que tenga que esperar. Sin embargo, si alguien más quiere intentarlo, estoy ofreciendo una recompensa de 500 repeticiones)

000 y 010, 21 bytes

<<@"peeb"/
.@"peeb"<\

¡Prueba 000 en línea! y prueba 010 en línea!

Esto es portado desde mi ><>solución . Obviamente, esto funciona 000, ya que esa es la topología predeterminada para la mayoría de los lenguajes 2D, pero me sorprendió que también funcione 010.

001 y 011, 26 bytes

!.<<@"peeb"/
.@"peeb"..<..

¡Prueba 001 en línea! y prueba 011 en línea!

Este se copia directamente de la respuesta de WW . ¡Gracias!

100, 21 bytes

//@"peeb"\
@"peeb".</

Pruébalo en línea!

101, 21 bytes

//@"peeb"/
@"peeb".<!

Pruébalo en línea!

110, 26 bytes

<.<@"peeb"\\
.\@."peeb".\<

Pruébalo en línea!

111, 24 bytes

<<@"peeb"<\
...@"peeb"//

Pruébalo en línea!

200, 21 bytes

<<@"peeb"\
@"peeb".!/

Pruébalo en línea!

201, 31 bytes

\\.\.@"peeb"</./
./...@"peeb"<\

Pruébalo en línea!

De lejos, el más molesto.

210, 26 bytes

/\\@"peeb"</\
/@.."peeb"<\

Pruébalo en línea!

211, 27 bytes

\\."peeb"((</
!/@@<"peeb"<\

Pruébalo en línea!

El único en el que tuve que manejar entrar en el busca por el lado derecho.

Jo King
fuente
Felizmente apoyaré esa recompensa.
Wheat Wizard
3

Brainfuck auto modificable , 144 102 bytes

Los no imprimibles se muestran como secuencia de escape (por ejemplo \x01).

\xa8<<[[<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<[[[.<-]>[>-]\x01qffb\x00\x00beep\x00]]]<[>]<<[>[-<+>]+<<]>[[>]>>[.>]]\x01

¡Verificación!

usuario202729
fuente
2

Encantamientos rúnicos , 29 bytes

>>yyLL@"peeb"/
     @"peeb"L\

Pruébalo en línea!

Esencialmente lo mismo que la respuesta Klein 000 o> <> (comencé con la respuesta Klein). El único cambio realmente necesario era convertir la <entrada Ly la .entrada  (traducción de símbolos de comando), insertar los puntos de entrada de IP (necesidad 2, de lo contrario, una eliminación daría como resultado un programa que no se compila) y la inserción del ycomando dela para obtener el dos IP para fusionar (imprimiendo solo una beep), nuevamente, necesitando dos También se requiere insertar NOP adicionales para mantener las longitudes de línea iguales. Klein también utiliza convenientemente @para "imprimir y terminar".

No hay capacidad para utilizar el espacio en blanco en la parte inferior izquierda, ya que cualquier reflector para cambiar de dirección inhibe la capacidad de detectar radiación. por ejemplo (26 bytes, irradiado y):

/yLL@"peeb"/
\<<  @"peeb"L\

No imprime ninguna salida, debido a que el segmento de entrada doblado causa un reflejo de regreso al terminador de la línea inferior.

Draco18s
fuente
1

Wumpus , 37 34 32 31 bytes

777*7..@ $o&4"beep"|"@peeb"4&o@

Pruébalo en línea! ¡Verificación!

Esta solución utiliza el hecho de que . salta a un módulo de posición a lo largo del programa.

Alternativamente para la misma cantidad de bytes


" @o&4"beep"}@
@o&4"beep"}$}  

Pruébalo en línea! ¡Verificación!

Éste utiliza la diferencia en la dirección del puntero para longitudes de línea pares e impares. (Realmente no sé cómo funciona el primero "cuando se elimina la nueva línea)

Jo King
fuente
1

Klein (001), 26 bytes

!.<<@"peeb"/
.@"peeb"..<..

Pruébalo en línea!

¡Verificar!

Explicación

Este programa aprovecha la topología única de Klein, en particular el 001 topología , que es una botella de Klein.

Sin editar, el programa sigue la ruta de ejecución:

Camino naranja

Eliminar un byte del programa puede afectar el programa de 4 maneras (cada una en un color diferente):

Secciones del programa

Lo primero que debe tener en cuenta es que <<siempre desviará la ip a la izquierda del origen al comienzo. Si uno de los< se elimina s, el otro toma su lugar. Entonces, si se elimina algún byte de la sección roja, se seguirá la siguiente ruta de ejecución:

Camino rojo

Si se elimina el byte azul, obtenemos la ruta muy simple:

ingrese la descripción de la imagen aquí

Si se elimina la nueva línea, obtenemos la ruta:

Camino verde

El camino amarillo es un poco más complejo. Como la línea inferior es una más larga que la línea superior, cuando el programa se cuadra al comienzo de la ejecución, se agrega un carácter virtual al final de la primera línea para que tengan el mismo tamaño. Si se elimina algún byte en la segunda línea, la línea se acorta y ese carácter virtual no se agrega. Esto es importante porque !normalmente salta sobre el personaje virtual, pero en su defecto, salta sobre él /.

Camino amarillo

Asistente de trigo
fuente
1
Podría transferir mi ><>solución 000por 21 bytes
Jo King
@JoKing Creo que eso sería mejor como respuesta propia.
Wheat Wizard
1

Revés , 25 21 bytes

vv""ppeeeebb""jjHH@

Pruébalo en línea! ¡Verificación!

Esto utiliza la capacidad de Backhand para cambiar el valor del paso del puntero para omitir una instrucción en cada paso y resolver el problema de redundancia. Luego utiliza el jcomando para verificar si el código se irradia saltando al último carácter ( @, detener) si no, y saltando al segundo último ( H, detener y apilar salida) si es así.

Jo King
fuente