Este desafío se basa en la pregunta de Helka Homba Programación de un mundo prístino . A partir de esa pregunta, la definición de un programa original es:
Definamos un programa prístino como un programa que no tiene ningún error en sí mismo, pero lo hará si lo modifica quitando cualquier subcadena contigua de N caracteres, donde
1 <= N < program length
.Por ejemplo, el programa Python 2 de tres caracteres
`8`
es un programa impecable ( gracias, Sp ) porque todos los programas resultantes de la eliminación de subcadenas de longitud 1 causan errores (errores de sintaxis, de hecho, pero cualquier tipo de error funcionará):
8` `` `8
y también todos los programas resultantes de eliminar subcadenas de longitud 2 causan errores:
` `
Si, por ejemplo,
`8
hubiera sido un programa sin errores, entonces`8`
no sería perfecto porque todos los resultados de la eliminación de la subcadena deben ser erróneos.Notas:
- Las advertencias del compilador no cuentan como errores.
- Los subprogramas de error pueden tomar entrada o dar salida o hacer cualquier otra cosa, siempre y cuando se produzca un error sin importar lo que pase.
Su tarea es crear un programa de longitud distinta de cero que imprima su propio código fuente exactamente, siga las reglas para una quine adecuada y sea impecable.
La respuesta más corta en bytes para cada idioma gana.
Respuestas:
Haskell , 132 bytes
Pruébalo en línea!
Esta es una extensión de la quine
que funciona concatenando la cadena de datos con una versión citada (usando
show
) de sí misma e imprimiendo el resultado. Sin embargo, esto no es perfecto, ya que cualquier carácter en la cadena de datos puede eliminarse sin fallar y también la parte$(++)<*>show$
o(++)<*>
podría eliminarse sin que se rompa el programa.Para solucionar esto, una función de impresión personalizada
q
se define que verifica la longitud de la cadena dada y llamafail
si es más corta que 132. Esto detecta la eliminación de cualquier secuencia de la cadena de datos y también la eliminación de$(++)<*>show$
o(++)<*>
, como en ambos casos el resultado la cadena pasada aq
es más corta.En
q
el número132
podría acortarse a1
,13
,32
o2
, pero en cada caso de nuevofail
que se llama.Por lo que puedo decir, la eliminación de cualquier otra subcadena causa un error de sintaxis o de tipo, por lo que el programa ni siquiera se compila en primer lugar. (El estricto sistema de tipos de Haskell es útil aquí).
Editar: Gracias a Ørjan Johansen y Shelvacu por señalar fallas!
fuente
fail[]|length x/=122
se puede eliminar.fail[]:[putStr x|length x==122]
Podría funcionar mejor.|length x==122
podría ser eliminado.if length x==122 then putStr x else fail[]
¿quizás?if then else
antes pero pensé que podría acortarlo.putStr x
puede llegar a serp x
, lo que cuando probé en mi sistema funcionó durante mucho tiempo antes de matarlo, sospecho que la recursión de la cola se optimizó, por lo que es un bucle infinito. No conozco suficiente haskell para dar sugerencias sobre cómo solucionarlo.p
aq
debería solucionar eso.Python 3 , 113 bytes
Pruébalo en línea!
Cómo funciona
No podemos usar fácilmente varias declaraciones ya que la segunda podría eliminarse, por lo que comenzamos con un quine de expresión única:
Para protegerlo contra las eliminaciones de subcadenas, utilizamos en
open(1,"w").write
lugar deprint
. En Python 3,write
devuelve el número de caracteres escritos, lo que verificaremos es113
asegurarnos de que no se eliminó ninguna parte de la cadena. Hacemos esto al buscar el valor de retorno en el diccionario{113:[]}
y recorrer el resultado confor[]in…:a
, que fallará si no obtuvimos un iterable vacío o si lafor
declaración se elimina.fuente
Ruby, 78 bytes
Escribí esto cuando pensé en el desafío para asegurarme de que fuera posible. Utiliza el mismo "contenedor" de una de mis respuestas al desafío original.
Explicación:
eval(*[
expr])
Esto evalúa cualquier código devuelto como un programa ruby. Esto efectivamente prueba que la cadena que código devuelve el es un programa ruby válido. Convenientemente, los programas ruby pueden estar en blanco o solo consisten en espacios en blanco.
El operador "splat" le
*
permite usar una matriz como argumentos para una función. Esto también significa que sieval
se elimina, el programa resultante es(*[
expr])
, que no es válido ruby.($>.write(
str)-78).chr
$>
es una variable corta para STDOUT.$>.write(foo)
escribe foo en STDOUT y, lo que es importante para este código, devuelve el número de bytes escritos.$>.write(foo)-78
: Aquí78
está la duración del programa, y si el programa no está maltratado, también será el número de bytes escritos. Por lo tanto, en el caso no mutilado, esto devolverá cero.num.chr
devuelve num como un carácter, por ejemplo0.chr
, devolverá una cadena que contiene un solo byte nulo. En el programa no desencadenado, esto dará una cadena con un solo byte nuloeval
, que es un programa ruby válido que no funciona.Además, el programa puede eliminar una subcadena de modo que sea justo
eval(*[(78).chr])
oeval(*[(8).chr])
, lo que significa que la constante numérica no puede terminar con ninguno de los números (0, 4, 9, 10, 11, 12, 13, 26, 32, 35, 48 , 49, 50, 51, 52, 53, 54, 55, 56, 57, 59, 64, 95) porque son códigos ASCII para programas válidos de rubí de un solo carácter.%{
str}
Esta es una sintaxis menos conocida para los literales de cadena en ruby. La razón por la que se usa aquí es que
{}
se pueden usar pares balanceados dentro de la cadena, lo que significa que esta sintaxis puede contenerse. Por ejemplo,%{foo{bar}}
es lo mismo que"foo{bar}"
.(s=%{
datos})%s
Esto define la variable
s
que son los datos de esta línea, como una cadena printf.Las asignaciones en ruby devuelven lo asignado, por lo que es lo mismo que la primera asignación
s
y luego ejecutars%s
%
en una cuerda hay azúcar sintético para el equivalente de ruby de sprintf. los%s
significa en donde dentro de los datos de los propios datos deben ser embebidos.Este bit de código define la porción de datos del quine y lo integra dentro de sí mismo para crear el código completo.
fuente
ML estándar (MLton) ,
204182189 bytesPruébalo en línea!
Para MLton, los programas SML completos son expresiones delimitadas y terminadas por
;
( por ejemploprint"Hello";print"World";
) o declaraciones con las palabras clavevar
yfun
(por ejemplovar _=print"Hello"var _=print"World"
) donde_
hay un comodín que también podría reemplazarse por cualquier nombre de variable.La primera opción es inútil para la programación inmaculada porque
;
por sí sola es un programa válido (que no hace nada, pero tampoco falla). El problema con el segundo enfoque es que las declaraciones comovar _=print"Hello"
se pueden acortar a solovar _="Hello"
(o inclusovar _=print
) porque la declaración convar
funciona siempre que el lado derecho sea una expresión o valor SML válido (SML es un lenguaje funcional, por lo que las funciones pueden ser usado como valores también).En este punto, estaba listo para declarar imposible la programación prístina en SML, cuando por casualidad me topé con la coincidencia de patrones en las
val
declaraciones. Resulta que la sintaxis para las declaraciones no esval <variable_name> = <expression>
sinoval <pattern> = <expression>
, donde un patrón puede consistir en nombres de variables, constantes y constructores. A medida que laprint
función tiene el tipostring -> unit
, podemos usar una comparación de patrones en elunit
valor P()
para hacer cumplir la función de impresión que se aplica realmente a la cadena:val()=print"Hey"
. Con este enfoque, eliminar cualquiera de los dosprint
o"Hey"
resulta en unPattern and expression disagree
error.Con esta forma de impresión impecable a mano, el siguiente paso es escribir un quine, antes de que finalmente se necesite agregar más protección de salvamento. Anteriormente utilicé una técnica de quine SML fácil (consulte el historial de revisiones ), pero Anders Kaseorg señaló un enfoque diferente que puede ahorrar algunos bytes en su caso. Utiliza la
String.toString
función incorporada para manejar el escape de cadenas y es de forma general<code>"<data>"
, donde"<data>"
es una cadena escapada decode
antes:Esta es una quine de trabajo pero aún no está impecable. En primer lugar, Anders Kaseorg descubrió que MLton acepta una sola cita
"
como código sin generar errores, lo que significa que no podemos tener un código que termine en una cita como se indicó anteriormente. La forma más corta de evitar esto sería envolver todo despuésval()=
en un paréntesis, sin embargo, el código podría reducirse aval()=()
. La segunda forma más corta que encontré es usarval()=hd[ ... ]
, es decir, envolvemos todo en una lista y devolvemos su primer elemento para hacer feliz el verificador de tipos.Para asegurarse de que no se pueda eliminar ninguna parte de la cadena de datos sin que se note, la coincidencia de
val
patrones en las declaraciones vuelve a ser útil: la longitud de la cadena final a imprimir (y, por lo tanto, la longitud del programa) debe ser igual a 195, por lo que podemos escribirlet val t=... val 195=size t in print t end
en el cuerpo de lafn
abstracción en lugar deprint(...)
. La eliminación de una parte de la cadena da como resultado una longitud inferior a 189, lo que provoca unaBind
excepción.Todavía queda un problema: toda la
val 195=size t
verificación simplemente podría descartarse. Podemos evitar esto expandiendo la verificación para que coincida con una tupla: deval t=... val(216,u)=(n+size t,t)in print u end
modo que al eliminar la verificación se obtiene una variable independienteu
.En total, esto produce la siguiente solución de 195 bytes:
La aplicación del truco de golf de usar nombres de variables de operador como
!
,$
y en%
lugar den
,t
yu
para ahorrar algo de espacio en blanco (ver este consejo ) conduce a la versión final de 182 bytes.Todas las demás eliminaciones de subcadenas que no se indiquen explícitamente en la explicación deberían dar lugar a un error de tipo o sintaxis.
Edición 1:
length(explode t)
es justosize t
.Edición 2: Gracias a Anders Kaseorg por un enfoque de quine diferente y señalando una "vulnerabilidad".
fuente
"\""
directamente y usandoString.toString
para escapar."
, produciendo una salida vacía ( TIO ).let ... in ... end
."
como programa, y parece que se corrigió el error en esta confirmación , por lo que tal vez su 182 o mi 180 esté bien siempre que especifique la versión Git inédita de MLton.