Como debería saber (con suerte), una quina endurecida por radiación es una quine de la que puede eliminar cualquier carácter y aún imprimir su fuente original, previamente modificada. La cuestión es que con la mayoría de estos solo puedes eliminar un personaje; de lo contrario, todo se rompe. Aquí es donde entra esto; su objetivo es construir una quine endurecida por radiación que pueda eliminar la mayor cantidad de caracteres posible. Cualquier lenguaje que cumpla con las reglas está bien.
Reglas
- El programa debe tener al menos un carácter
- El idioma utilizado debe estar completo (por lo que los idiomas como HQ9 + no califican)
- Todas las demás reglas que se aplican a las cuotas normales también se aplican aquí.
- La solución con el mínimo
program_length^(2/n)en el que se puede eliminar cualquier conjunto dencaracteres exactos mientras se sigue imprimiendo el código fuente original gana.

Subleq. ¡Creo que sería ideal para este tipo de desafío!Respuestas:
Perl,
11161124 bytes, n = 3, puntaje = 1124 ^ (2/3) o aproximadamente 108.1Actualización : ahora he verificado que esto funciona con n = 3 a través de la fuerza bruta (que tomó un par de días); con un programa tan complejo, es difícil verificar la resistencia a la radiación a mano (y cometí un error en una versión anterior, por lo que aumentó el recuento de bytes). Fin de actualización
Recomiendo redirigir stderr a algún lugar que no lo vea; Este programa produce un montón de advertencias sobre la sintaxis dudosa, incluso cuando no está eliminando caracteres de la misma.
Es posible que el programa se pueda acortar. Trabajar en esto es bastante doloroso, lo que hace que sea fácil pasar por alto posibles micro optimizaciones. Principalmente tenía el objetivo de obtener el mayor número posible de caracteres eliminables (porque esa es la parte realmente desafiante del programa), y traté el desempate del código de golf como algo que era bueno apuntar pero como algo que no pondría esfuerzo ridículo para optimizar (sobre la base de que es muy fácil romper la resistencia a la radiación por accidente).
El programa
Nota: hay un
_carácter de control literal (ASCII 31) inmediatamente antes de cada una de las cuatro ocurrencias de-+. No creo que se haya copiado y pegado correctamente en StackOverflow, por lo que deberá volver a agregarlo antes de ejecutar el programa.La explicación
Este programa está, claramente, compuesto por cuatro programas idénticos más pequeños concatenados juntos. La idea básica es que cada copia del programa verificará si se ha dañado demasiado o no para ejecutarse; si lo ha sido, no hará nada (aparte de posiblemente arrojar advertencias) y dejará que se ejecute la próxima copia; si no lo ha sido (es decir, sin eliminaciones, o el carácter que se eliminó fue uno que no hace ninguna diferencia en la operación del programa), hará su cosa (imprimiendo el código fuente del programa completo; esta es una quine adecuada, con cada parte que contiene una codificación del código fuente completo) y luego salga (evitando que cualquier otra copia no dañada vuelva a imprimir el código fuente y arruinando la quine al imprimir demasiado texto).
Cada parte está hecha a su vez de dos partes que son efectivamente funcionalmente independientes; un contenedor externo y algo de código interno. Como tal, podemos considerarlos por separado.
Envoltura exterior
El envoltorio exterior es, básicamente,
eval<+eval<+eval< ... >####>####...>###(además de un montón de puntos y comas y líneas nuevas cuyo propósito debería ser bastante obvio; es asegurar que las partes del programa permanezcan separadas independientemente de si algunos de los puntos y comas o las nuevas líneas anteriores se eliminan) ) Esto puede parecer bastante simple, pero es sutil de varias maneras, y la razón por la que elegí a Perl para este desafío.Primero, veamos cómo funciona el contenedor en una copia intacta del programa.
evalanaliza como una función incorporada, que toma un argumento. Debido a que se espera una discusión,+aquí hay un unario+(que será muy familiar para los golfistas de Perl por ahora; son útiles sorprendentemente a menudo). Todavía estamos esperando un argumento (acabamos de ver un operador unario), por lo<que lo que viene a continuación se interpreta como el inicio de la<>operador (que no toma argumentos de prefijo o postfijo, y por lo tanto puede usarse en la posición del operando).<>Es un operador bastante extraño. Su propósito habitual es leer los identificadores de archivo y coloca el nombre del identificador de archivo dentro de los corchetes angulares. Alternativamente, si la expresión no es válida como un nombre de identificador de archivo, se bloquea (básicamente, el mismo proceso que usan los shells de UNIX para traducir el texto ingresado por el usuario a una secuencia de argumentos de línea de comandos; en realidad, se usaban versiones mucho más antiguas de Perl) la cáscara para esto, pero hoy en día Perl maneja el globbing interno). El uso previsto, por lo tanto, está en la línea de<*.c>, que normalmente devolvería una lista como("foo.c", "bar.c"). En un contexto escalar (como el argumento paraeval), solo devuelve la primera entrada que encuentra la primera vez que se ejecuta (el equivalente del primer argumento), y devolvería otras entradas en ejecuciones hipotéticas futuras que nunca suceden.Ahora, los shells a menudo manejan argumentos de línea de comandos; si da algo como
-rsin argumentos, simplemente se pasará al programa textualmente, independientemente de si hay un archivo con ese nombre o no. Perl actúa de la misma manera, por lo tanto, siempre y cuando nos aseguremos de que no haya caracteres que sean especiales para el shell o para Perl, es casi imposible; Parece que hay dos capas de escape con cada<y la coincidencia>, podemos usar esto de manera efectiva como una forma realmente incómoda de literal de cadena. Aún mejor, el analizador de Perl para operadores tipo comillas tiene una tendencia compulsiva a emparejar paréntesis incluso en contextos como este donde no tiene sentido, por lo que podemos anidar de<>forma segura (que es el descubrimiento necesario para que este programa sea posible). El principal inconveniente de todos estos anidados<>es que escapar de los contenidos de la<><>, por lo que para escapar de algo en el interior de las tres, debe ir precedido de 63 barras diagonales inversas. Decidí que, aunque el tamaño del código es solo una consideración secundaria en este problema, casi seguro que no valía la pena pagar este tipo de penalización, así que decidí escribir el resto del programa sin usar los caracteres ofensivos.Entonces, ¿qué sucede si se eliminan partes del contenedor?
evalhacen que se convierta en una palabra desnuda , una cadena sin significado. A Perl no le gustan estos, pero los trata como si estuvieran rodeados de comillas; asíeal<+eval<+...se interpreta como"eal" < +eval<+.... Esto no tiene ningún efecto en la operación del programa, porque básicamente solo toma el resultado de las evaluaciones muy anidadas (que no usamos de todos modos), lo convierte en un número entero y hace algunas comparaciones sin sentido en él. (Este tipo de cosas causa una gran cantidad de spam de advertencia, ya que claramente no es algo útil en circunstancias normales; solo lo estamos usando para absorber eliminaciones). Esto cambia la cantidad de corchetes angulares de cierre que necesitamos (porque el corchete de apertura ahora se está interpretando como un operador de comparación), pero la cadena de comentarios al final asegura que la cadena terminará de manera segura sin importar cuántas veces esté anidada. (Hay más#signos de los estrictamente necesarios aquí; lo escribí como lo hice para hacer que el programa sea más compresible, permitiéndome usar menos datos para almacenar el quine).<se elimina un, el código ahora se analiza comoeval(eval<...>). El secundario, externo,evalno tiene ningún efecto, porque los programas que estamos evaluando no devuelven nada que tenga ningún efecto real como programa (si regresan normalmente, normalmente es una cadena nula o una palabra simple; más comúnmente regresan a través de excepción, que haceevalque se devuelva una cadena nula, o se usaexitpara evitar el retorno).+se elimina un, esto no tiene efecto inmediato si el código adyacente está intacto; Unary+no tiene ningún efecto en el programa. (La razón por la que+están los s originales es para ayudar a reparar el daño; aumentan el número de situaciones en las que<se interpreta como un operador unario en<>lugar de como un operador relacional, lo que significa que necesita más eliminaciones para producir un programa no válido).El contenedor puede dañarse con suficientes eliminaciones, pero debe hacer una serie de eliminaciones para producir algo que no se analice. Con cuatro eliminaciones, puede hacer esto:
y en Perl, el operador relacional
<no es asociativo y, por lo tanto, se obtiene un error de sintaxis (el mismo con el que se obtendría1<2<3). Como tal, el límite para el programa tal como está escrito es n = 3. Agregar más+s unarios parece una forma prometedora de aumentarlo, pero como eso aumentaría la probabilidad de que el interior del contenedor también se rompa, verificando que la nueva versión del programa funcione podría ser muy difícil.La razón por la que el contenedor es tan valioso es que
evalen Perl detecta excepciones, como (por ejemplo) la excepción que se obtiene cuando intenta compilar un error de sintaxis. Como seevaltrata de un literal de cadena, la compilación de la cadena ocurre en tiempo de ejecución, y si el literal no se compila, la excepción resultante queda atrapada. Esto haceevalque devuelva una cadena nula y establezca el indicador de error$@, pero nunca verificamos tampoco (excepto al ejecutar ocasionalmente la cadena nula devuelta en algunas versiones mutadas del programa). Crucialmente, esto significa que si algo le sucede al código dentroel contenedor, causando un error de sintaxis, entonces el contenedor solo hará que el código no haga nada en su lugar (y el programa seguirá ejecutándose en un intento de encontrar una copia no dañada de sí mismo). Por lo tanto, el código interno no tiene que ser tan resistente a la radiación como el envoltorio; todo lo que nos importa es que si está dañado, actuará de forma idéntica a la versión no dañada del programa, o se bloqueará (permitiendoevaldetectar la excepción y continuar) o saldrá normalmente sin imprimir nada.Dentro de la envoltura
El código dentro del contenedor, fundamentalmente, se ve así (de nuevo, hay un Control,
_que Stack Exchange no mostrará inmediatamente antes del-+):Este código está escrito completamente con caracteres seguros para glob, y su propósito es agregar un nuevo alfabeto de signos de puntuación que permitan escribir un programa real, a través de la transcripción y evaluación de un literal de cadena (no podemos usarlo
'o"como nuestra cita marcas, peroq(...)también es una forma válida de formar una cadena en Perl). (La razón del carácter no imprimible es que necesitamos transcribir algo en el carácter de espacio sin un carácter de espacio literal en el programa; por lo tanto, formamos un rango que comienza en ASCII 31 y capturamos el espacio como el segundo elemento del rango). Obviamente, si estamos produciendo algunos caracteres a través de la transliteración, tenemos que sacrificar personajes para transliterarlos de, pero las letras mayúsculas no son muy útiles y es mucho más fácil escribir sin acceso a ellas que sin acceso a signos de puntuación.Aquí está el alfabeto de los signos de puntuación que están disponibles como resultado del globo (la línea superior muestra la codificación, la línea inferior el carácter que codifica):
BCDEFGHIJKLMNOPQRSTUVWXYZ ! "# $% & '() * +; <=>? @ AZz {|} ~Lo más notable es que tenemos un montón de signos de puntuación que no son seguros para los globos, pero son útiles para escribir programas de Perl, junto con el carácter de espacio. También guardé dos letras mayúsculas, la literal
AyZ(que codifican no para sí mismas, sino paraTyU, porqueAse necesitaba como un punto final de rango superior e inferior); Esto nos permite escribir la instrucción de transliteración en sí usando el nuevo conjunto de caracteres codificados (aunque las letras mayúsculas no son tan útiles, son útiles para especificar cambios en las letras mayúsculas). Los caracteres más notables que no tenemos disponibles son[,\y], pero ninguno es necesario (cuando necesitaba una nueva línea en la salida, la produje usando la nueva línea implícita desayen lugar de necesitar escribir\n;chr 10también habría funcionado pero es más detallado).Como de costumbre, debemos preocuparnos por lo que sucede si el interior del contenedor se daña fuera del literal de la cadena. Un corrupto
evalevitará que algo se ejecute; Estamos bien con eso. Si las comillas se dañan, el interior de la cadena no es válido Perl y, por lo tanto, el contenedor lo atrapará (y las numerosas sustracciones en las cadenas significan que incluso si pudieras hacerlo válido Perl, no haría nada, lo que Es un resultado aceptable). El daño a la transliteración, si no se trata de un error de sintaxis, dañará la cadena que se está evaluando, lo que generalmente hace que se convierta en un error de sintaxis; No estoy 100% seguro de que no haya casos en los que esto se rompa, pero lo estoy forzando por el momento para asegurarme, y debería ser lo suficientemente fácil de solucionar si lo hay.El programa codificado
Mirando dentro del literal de cadena, invirtiendo la codificación que utilicé y agregando espacios en blanco para que sea más legible, obtenemos esto (nuevamente, imagine un guión bajo de control antes del
-+, que está codificado comoA):Las personas que están acostumbradas a las quines reconocerán esta estructura general. La parte más crucial es al comienzo, donde verificamos que $ o no está dañado; si se han eliminado los personajes, su longitud no coincide
181, por lo que se correzzzz((()))el cual, si no es un error de sintaxis debido a los soportes sin igual, será un error de ejecución, incluso si elimina cualquiera de los tres personajes, porque ninguno dezzzz,zzz,zz, yzes una función, y no hay forma de evitar que se analice como una función que no sea eliminar(((y causar un error de sintaxis obvio. El cheque en sí también es inmune al daño; la||pueden dañarse a|pero eso hará que lazzzz((()))llamada para funcionar sin condiciones; las variables o constantes dañinas causarán una falta de coincidencia porque estás comparando una de0,180,179,178por igualdad a algún subconjunto de los dígitos de181; y eliminar uno=causará una falla de análisis, y dos=inevitablemente harán que el LHS evalúe el entero 0 o una cadena nula, los cuales son falsey.Actualización : Esta comprobación fue ligeramente incorrecta en una versión anterior del programa, por lo que tuve que editarla para solucionar el problema. La versión anterior se veía así después de la decodificación:
y fue posible eliminar los primeros tres signos de puntuación para obtener esto:
lengtho179, siendo una palabra simple, es verdad y, por lo tanto, rompe el control. Lo arreglé agregando dosBcaracteres adicionales (que codifican caracteres de espacio), lo que significa que la última versión de la quine hace esto:Ahora es imposible ocultar tanto los
=signos como el$signo sin producir un error de sintaxis. (Tuve que agregar dos espacios en lugar de uno porque una longitud180pondría un0carácter literal en la fuente, lo que podría ser abusado en este contexto para comparar cero entero con una palabra desnuda, que tiene éxito). Fin de la actualizaciónUna vez que se pasa la verificación de longitud, sabemos que la copia no está dañada, al menos en términos de eliminaciones de caracteres, por lo que todo es una simple clasificación desde allí (las sustituciones de signos de puntuación debido a una tabla de decodificación corrupta no se detectarán con esta verificación , pero ya he verificado a través de la fuerza bruta que no hay tres eliminaciones de solo la tabla de decodificación que rompen el quine; presumiblemente, la mayoría de ellos causan errores de sintaxis). Ya tenemos
$ouna variable, así que todo lo que tenemos que hacer es codificar los envoltorios externos (con un pequeño grado de compresión; no omití la parte del código de golf de la pregunta por completo ). Un truco es que almacenamos la mayor parte de la tabla de codificación en$r; podemos imprimirlo literalmente para generar la sección de la tabla de codificación del envoltorio interno, o concatenar un código a su alrededorevalpara ejecutar el proceso de decodificación en reversa (lo que nos permite descubrir cuál es la versión codificada de $ o , teniendo solo la versión decodificada disponible en este momento).Finalmente, si fuéramos una copia intacta y pudiéramos generar el programa original completo, llamamos
exitpara evitar que las otras copias también intenten imprimir el programa.Script de verificación
No es muy bonito, pero lo publica porque alguien preguntó. Ejecuté esto varias veces con una variedad de configuraciones (normalmente cambiando
$miny$maxpara verificar varias áreas de interés); No fue un proceso totalmente automatizado. Tiene tendencia a dejar de funcionar debido a la gran carga de CPU en otros lugares; cuando esto sucedió, simplemente cambié$minal primer valor$xque no estaba completamente verificado y continué ejecutando el script (asegurando así que todos los programas en el rango se verificaran eventualmente). Solo verifiqué las eliminaciones de la primera copia del programa, porque es bastante obvio que las eliminaciones de las otras copias no pueden hacer más.fuente
Befunge-98 , 884, n = 14, puntaje ≈ 2.636
Pruébalo en línea!
Esto no solo funciona cuando elimina exactamente 14 caracteres, sino incluso cuando elimina cualquier cantidad de hasta 14 caracteres.
n = 14Puede parecer una elección muy arbitraria, pero la técnica que utilicé en realidad solo puede usarse para órdenes de endurecimiento de la radiación del 1 al 14, pero no más allá de eso (podría ser posible, pero no tengo idea de cómo). El orden-1 quine es simplemente 73 bytes (aunque emplea algunos trucos de golf que no se aplican a los más grandesn):Explicación
Cuando estaba trabajando en esta respuesta , descubrí que es posible establecer el delta del puntero de instrucciones en
(2,0)condiciones de endurecimiento por radiación con el siguiente fragmento:Vea esa respuesta para saber por qué esto funciona. Encontré esto solo con un poco de violín a mano, pero esto planteó la pregunta de si hay patrones similares que sean robustos al eliminar múltiples caracteres. Así que escribí un breve script de Mathematica para buscarlos por fuerza bruta:
Esto reveló muy rápidamente un patrón. Para obtener un fragmento correspondiente que funcione para la eliminación de hasta
ncaracteres, puede usar(m0x){n}m0wheremisn+1yxis omo0. Por lo tanto, todo lo siguiente funcionaría para eliminar hasta dos caracteres:Estoy seguro de que es posible probar esto, pero simplemente lo he verificado
nhasta7. Por supuesto, esto solo funciona siempre que podamos representarn+1como un solo dígito, y el dígito más grande en Befunge 98 es elfque representa 15. Es por eso que mi enfoque se limita an = 14. Si alguien encuentra una manera de establecer de manera confiable el delta en más granden+1, es probable que sea posible aumentar el orden de esta quina endurecida por radiación indefinidamente.Miremos el código real. Básicamente tiene dos partes. Primero configuramos el delta
(15,0)como acabo de mencionar:Y el resto del código tiene cada comando repetido 15 veces e imprime la fuente. Si eliminamos la repetición, se ve así:
Esta
"es una técnica de combinación 2D estándar: inicia el modo de cadena, empuja todos los caracteres (excepto a sí mismo) en la pila y finaliza el modo de cadena nuevamente después de ajustar. Esto nos ayuda a obtener todos los puntos de código de la segunda mitad, pero no conseguirá nada útil de la primera mitad, porque a lo largo delf00f00...f0bit, solo registrará dos caracteres (que pueden serfo0dependiendo de qué caracteres se eliminen). ) Pero como esa parte no está compuesta de caracteres que se repiten 15 veces, de todos modos tendremos que imprimirla por separado.Más convenientemente, en la quine no modificada, la longitud de la cadena antes de la
"es-1 (mod 15). Esto garantiza que no importa cuántos caracteres (hasta 14) eliminemos, que la cantidad de caracteres grabados allí siempre es 3 (unoxy dos defy0). Esto es realmente cierto para cualquier orden de radiación hasta 14.Ahora comenzamos imprimiendo la
f00f00...f0pieza:El siguiente
3k$simplemente descarta eso0, así como los tres caracteres que fueron empujados"desde el comienzo del programa. La pila ahora contiene solo los caracteres después del", así como algo de basura debajo del original,f00f00...f0dependiendo de qué caracteres se eliminaron.Ahora solo necesitamos invertir la parte superior de la pila (que contiene los caracteres restantes) e imprimir cada uno de ellos 15 veces.
Y eso es. :)
fuente
JavaScript (ES6), 927 bytes, n = 1, puntaje = 859329
nota: no use un REPL (como una consola del navegador) para ejecutar esto.
Esto se escribió antes de que la longitud del código fuera un factor, por lo que aún no se juega golf.
Esto fue muy difícil y merece una explicación detallada. ¡Lo escribiré más tarde, después de explorar este desafío un poco más!
nota: hay una nueva línea final
Básicamente, la primera línea se construye cuidadosamente para renombrar todas las 'faltas de ortografía' de
setTimeoutlas funciones válidas, de modo que si se elimina un carácter de una de lassetTimeouts, el código no generará errores y la versión indemne puede ejecutarse. También está escrito de modo que si se elimina cualquier carácter de la primera línea, no habrá ningún error y el resto del código puede ejecutarse sin verse afectado.El segundo y tercer bloque son exactamente equivalentes. Si uno se ejecuta hasta su finalización, establece la
_variable para que el otro sepa que no debe duplicar la quine. Si uno de estos bloques falla, no afecta al otro bloque porque se llamó de forma asincrónicasetTimeout. El error hará que_no se establezca, por lo que el otro bloque se eliminará correctamente. El código principal está en una cadena, que se verifica para determinar la longitud en cada bloque para asegurarse de que no haya eliminaciones.Las cadenas de plantilla en la línea siguiente con algunos comentarios al final de las cadenas de plantilla protegen el código de errores si se elimina uno de los backticks que forman la cadena de plantilla. Si se elimina la marca de retroceso final, la cadena de plantilla finaliza con la marca de retroceso en el comentario. Si se elimina el backtick de inicio, setTimeout se evalúa como una función no asignada (un no-op) y el código se ejecuta normalmente, sin setTimeout. El backtick final es anulado por otro comentario.
¿Qué es lo que dices? ¿Quieres probarlo? ¡No digas más!
Modo de página completa recomendado.
Ignora el cuadro de entrada, este fragmento no tiene entrada.
¡Intenta eliminar cualquier carácter del código!
No lo creo El código normal seguirá funcionando (pero no se ajustará ...) ¡Pruebe algo como
console.log(5)!nota: el fragmento tuvo que modificarse ligeramente para deshabilitar la función REPL, por lo que eliminé varias capacidades de salida solo para esta respuesta.
Una mejor explicación está por llegar. Mientras tanto, ¡siéntase libre de enviarme un correo electrónico al chat @jrich con cualquier comentario / pregunta / crítica!
fuente
thislugar dewindow.