Programando un mundo prístino

87

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 la eliminación de subcadenas de longitud 2 causan errores:

`
`

Si, por ejemplo, `8hubiera sido un programa sin errores `8`, no sería perfecto porque todos los resultados de la eliminación de la subcadena deben ser erróneos.

Su tarea en este desafío es escribir el programa prístino más corto posible que no requiera ninguna entrada pero que emita cualquiera de las siguientes cinco palabras:

world
earth
globe
planet
sphere

La palabra que elijas depende totalmente de ti. La única palabra más una nueva línea final opcional debe imprimirse en stdout (o la alternativa más cercana a su idioma). El programa más corto en bytes gana.

Notas:

  • Se requiere un programa independiente, no una función.
  • Las palabras distinguen entre mayúsculas y minúsculas; salida Worldo EARTHno está permitido.
  • 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 eventualmente se produzcan errores.

Aquí hay un fragmento de pila que enumerará qué programas necesitan error dado un programa potencialmente prístino:

<script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>function go() { var s = $('#i').val(), e = []; for (var i = 1; i < s.length; i++) { for (var j = 0; j <= s.length - i; j++) { e.push(s.substring(0, j) + s.substring(j + i)); } } $('#o').val(e.join('\n---\n')); }</script>Program:<br><textarea id='i' rows='16' cols='80'>`8`</textarea><br><button onclick='go()' type='button'>Go</button><br><br>Programs that should error: (--- separated)<br><textarea id='o' rows='16' cols='80'></textarea><br>

Pasatiempos de Calvin
fuente
1
@geokavel Sí. Capturar la excepción significa que ya no es un error.
Hobbies de Calvin
33
El doble de respuestas eliminadas que no eliminadas. Eso es un logro!
DLosc
1
¿Puede un programa leer su propio código fuente?
Shelvacu
2
¿Dónde ver el gravegard de respuestas "cercanas pero sin cigarro" y sus comentarios?
Vi.
1
@Vi. Obtenga 2,000 repeticiones para que pueda ver las publicaciones eliminadas .
ThisSuitIsBlackNot

Respuestas:

47

Carril , 24 bytes.

$'main'    #
 -[world]o/

Creo que esto funciona. Y es a la vez corto y legible (en lo que respecta al ferrocarril).

  • Si la subcadena eliminada incluye alguna parte de la $'main'que obtenemos Internal Error: Crash: No 'main' function found.
  • Si la subcadena eliminada incluye #, no hay forma de que el programa salga limpiamente, por lo que siempre terminará con Crash: No valid move. Creo que no es posible eliminar una subcadena de modo que la pista forme un bucle válido (infinito).
  • Si la subcadena eliminada se encuentra frente al #, se desconectará del final de la vía, por lo que el tren se estrellará (con el mismo error que el anterior).
  • Si la subcadena eliminada es posterior a la #, también se desconectará #desde el final de la pista (y potencialmente incluso el comienzo de la pista desde el punto de entrada $). Así que de nuevo el mismo error.

En cuanto al programa real: cada programa ferroviario debe tener una $'main'(o una variante más larga, pero estamos jugando al golf aquí) como punto de entrada a la función y el tren comienza en el $sudeste. Sin embargo, todo en esa primera línea puede ser parte de la pista, por lo que eliminar 'main'la pista es:

$          #
 -[world]o/

Los -y /son simplemente pedazos de rieles que necesitamos para que el tren tome esas vueltas de 45 °.

[world]empuja el hilo worldy lo oimprime. #marca el final de la pista, la única forma de finalizar de forma segura un programa Rail.

Curiosamente, esta solución solo es posible porque Rail permite que las pistas atraviesen la mainlínea; si eso no fuera posible #, sería después de la primera línea nueva y el código siempre se podría acortar a

$'main'
 #

que es un programa válido que no hace nada (Los caracteres sin espacio entre 'y #no afectarían eso).

También bastante interesante: si acabara de jugar golf imprimiendo la tarea world, no habría sido mucho más corto o más simple:

$'main'
 -[world]o#
Martin Ender
fuente
44
¿Qué sucede si elimino cualquier carácter entre [y]?
Martin Lütke
@ MartinLütke se desconectará /de la #.
Martin Ender
2
@ MartinLütke No solo puede quitar los corchetes, ya que no son contiguos.
Hobbies de Calvin
¿Qué pasa si elimino la nueva línea entre las dos líneas?
Vi.
1
@Vi. Eso desconecta el $inicio de la vía, por lo que el tren se estrella inmediatamente (Rail espera que la vía continúe hacia el sudeste de la vía $).
Martin Ender
43

Funciton ( 186 136 bytes en UTF-16)

╔══════════════╗
║19342823075080╟
║88037380718711║
╚══════════════╝

Este programa imprime "mundo".

La mayoría de las subcadenas que elimine de esto evitarán que sea una caja completa, de lo que el analizador se quejará. Las únicas eliminaciones posibles que dejan un cuadro completo son:

 ╔══════════════╗
|║19342823075080╟  (remove this whole line)
|║88037380718711║
 ╚══════════════╝
 ╔══════════════╗
 ║|19342823075080╟   ← substring starts at | here
 ║|88037380718711║   ← substring ends at | here
 ╚══════════════╝
... ↕ or anything in between these that removes a whole line’s worth ↕ ...
 ╔══════════════╗
 ║19342823075080|╟   ← substring starts at | here
 ║88037380718711|║   ← substring ends at | here
 ╚══════════════╝
 ╔══════════════╗
|║19342823075080╟
 ║88037380718711║  (both lines entirely)
|╚══════════════╝
 ╔══════════════╗
 ║19342823075080╟
|║88037380718711║  (remove this whole line)
|╚══════════════╝

La mayoría de estos eliminan el extremo colgante en la parte superior derecha de la caja, que es el conector de salida. Sin este extremo suelto, la caja es solo un comentario:

╔══════════════╗
║88037380718711║
╚══════════════╝

Este ya no es un programa válido porque el analizador espera un programa con exactamente una salida:

Error: los archivos de origen no contienen un programa (el programa debe tener una salida).

La única posibilidad que deja un conector de salida es la última de las anteriores, que deja esto:

╔══════════════╗
║19342823075080╟
╚══════════════╝

Sin embargo, este número no codifica una cadena Unicode válida en el UTF-21 esotérico de Funciton. Intenta ejecutar esto, obtienes:

Excepción no controlada: System.ArgumentOutOfRangeException: un valor UTF32 válido está entre 0x000000 y 0x10ffff, inclusive, y no debe incluir valores de punto de código sustituto (0x00d800 ~ 0x00dfff).

Por lo tanto, este programa es impecable.

Timwi
fuente
3
Siento que tuvo suerte en el último caso (no es que sea tan fácil obtener accidentalmente una secuencia válida de Unicode, pero aún así ...)
Esolanging Fruit
34

Visual C ++ - 96 95 bytes

#include<iostream>
#define I(a,b)a<<b
int main()I({std::cout,I('w',I('o',I('r',I('l','d';)))))}

Propiedades:

  1. No puede eliminar ninguna parte int main()sin un error de compilación.
  2. No se puede quitar el modificar la expansión de macros en absoluto, eliminando aa todos los medios main()nunca se pone {, eliminando ba todos los medios a nuestra línea no termina en una ;, la eliminación de <medios std::cout<'w'provoca un error, y la eliminación de <<las causas std::cout'w', 'w''o'etc.
  3. No puede eliminar parámetros de la definición de macro o invocación, los únicos nombres válidos para la definición serían I(a), I(b)que nunca coinciden y Ique se expande antes (; por otro lado, usa I(,causas <<<<y ,)elimina el punto y coma (salvo cualquier otro error).
  4. No puede eliminar parte de todo std::coutsin encontrarse con un líder <<y, por lo tanto, no puede eliminar ninguno #include<iostream>al principio sin un error de compilación.
  5. No puede eliminar ninguna parte de un solo carácter, ''tiene un error de carácter vacío y 'w,, etc., intenta convertir todo en un solo carácter.
  6. No puede eliminar el lado izquierdo / derecho de una macro sin dejar demasiados )o (del otro lado, por ejemplo, no puede hacer cosas como I('w',I('r'.

Compila en línea usando Visual C ++ .

Una vez más, esto no es una prueba exhaustiva. Si crees que puedes hacerlo funcionar sin una sección, asegúrate de hacérmelo saber.

Las versiones anteriores usaban un enfoque considerablemente diferente y se demostró que no era impecable, así que eliminé esos puntajes.


Verificación:

El siguiente programa ha confirmado que esta versión es inmaculada usando el clcompilador de Visual C ++ 2010. Ojalá me hubiera molestado en escribir esto antes:

#include <fstream>
#include <iostream>
char *S = "#include<iostream>\n#define I(a,b)a<<b\nint main()I({std::cout,I('w',I('o',I('r',I('l','d';)))))}";
//uncomment to print source code before compile
// #define prints
int main(){
   for(int i=0; i<95; i++)
      for(int j=i; j<95; j++){
         std::fstream fs;
         fs.open ("tmptst.cpp",std::fstream::out);
         for(int k=0; k<95; k++)
         if(k<i || k>j){
            fs << S[k];
            #ifdef prints
               std::cout<<S[k];
            #endif
         }
         fs.close();
         #ifdef prints
            std::cout<<'\n';
         #endif
         //Compile and surpress/pipe all output
         //if it doesn't compile we get a nonzero errorlevel (i.e.true) from system.
         if(!system("cl -nologo tmptst.cpp >x"))
            return 0;
      }
      std::cout<<"PRISTINE!";
}
Linus
fuente
1
Notamos que si bien esto es prístino en este compilador, no lo es en todos los compiladores.
Joshua
1
Por favor, da un ejemplo ...
Linus
3
En algunos compiladores, el programa C ++ vacío produce un programa que no hace nada. Dependiendo de la implementación de iostream, #include <iostream> también podría compilarse.
Joshua
55
@Joshua Solo los subprogramas de longitud 1 o superior importan, por lo que es irrelevante lo que hace el programa vacío.
ThisSuitIsBlackNot
2
@Comintern, en realidad no. Si no marca la casilla para ejecutar el ejecutable, la /copción se incluye automáticamente y se compila (como si se creara una biblioteca y no un programa). Si marca la casilla Ejecutar que el sitio no incluye /c, no recibirá un mensaje de éxito, y en su lugar encontrará el "ENLACE: error fatal LNK1561: el punto de entrada debe estar definido".
Linus
32

Pitón 3, 79 33

if 5-open(1,'w').write('world'):a

open(1,'w')abre la salida estándar, luego imprimimos la cadena. writeDevuelve el número de caracteres escritos. Esto se utiliza para reforzar la eliminación de la subcadena: la eliminación de parte de la cadena hace que se devuelva algo distinto de 5, y 5 menos ese valor se evalúa como verdadero. Pero eso hace que el ifcuerpo se ejecute y ano está definido.

Esto se basa en la inteligente quine prístina de Anders Kaseorg aquí .

Como solo se necesita verificar una sola declaración, esta es mucho más corta que la solución anterior, pero también menos general.

Vieja solución:

try:
 q="print('world');r=None"
 if exec('e=q')==eval(q[17:]):exec(e)
finally:r

Para verificar que realmente es un programa impecable:

w=r'''try:
 q="print('world');r=None"
 if exec('e=q')==eval(q[17:]):exec(e)
finally:r'''
exec(w)
for j in range(1,len(w)):
 for i in range(len(w)+1-j):
  e=w[:i]+w[i+j:]
  try:exec(e,{});print('WORKED',e)
  except:pass

Algunos puntos clave:

  • Cada declaración ejecutada podría ser eliminada. Verificar que qse haya ejecutado requiere una declaración fuera de q. Lo tryresuelve muy bien, al requerir al menos dos declaraciones, ninguna de las cuales se puede eliminar por completo.
  • La verificación de que se qha ejecutado ocurre evaluando ral final.
  • La verificación de que qno se modificó se logra mediante eval(q[17:]), que debe evaluarse Nonepara qque se ejecute.
  • La ifcondición es un poco difícil de corregir. Para asegurarse de que se evaluó, tiene el agradable efecto secundario de la configuración e, que se necesita para configurar r. (Esta es la razón por la que usé Python 3, exprya que una función hace maravillas para los efectos secundarios a nivel de expresión).
Philipp
fuente
¿No es el desafío que ninguna eliminación resultaría en un error de sintaxis? Parece que provocas errores de tiempo de ejecución.
Martin Lütke
55
@ MartinLütke Cualquier tipo de error está bien.
Aficiones de Calvin
1
¿No son 79 bytes?
El Matt
@TheMatt ¿Sí? Acabo de contarlos de nuevo y parece que tienes razón. Tal vez el pasado contó nuevas líneas de CRLF ... Qué vergonzoso. ¡Gracias!
Philipp
25

Haskell, 61

x=uncurry(:)
main=putStr$x('w',x('o',x('r',x('l',x('d',[])))))

¿Algún tipo de error está bien? En ese caso:

Haskell, 39

main=putStr$take 5$(++)"world"undefined
Martin Lütke
fuente
¿Funciona esto si eliminas una de las letras?
lirtosiast el
Se bloqueará durante la ejecución. Porque intentará evaluar indefinido.
Martin Lütke
Esto es excelente. Evaluación perezosa FTW, parece!
DLosc
1
Desearía que 'inits' estuviera en el preludio :(. Entonces: main = putStr $ inits "world" !! 5 (27 bytes)
Martin Lütke
16

JavaScript, 74 73 35 bytes

if((alert(a="world")?x:a)[4]!="d")x

Resulta que la respuesta fue mucho más simple de lo que pensaba ...

Explicación

if(
  (
    alert(a="world") // throws a is not defined if '="world"' is removed
        ?x           // throws x is not defined if 'alert' or '(a="world")' is removed
        :a           // throws a is not defined if 'a="world"' or 'a=' is removed
  )
  [4]!="d"           // if "world" is altered fifth character will not be "d"
                     // if 'd' is removed it will compare "world"[4] ("d") with ""
                     // if '[4]' is removed it will compare "world" with "d"
                     // if '(alert(a="world")?x:a)' is removed it will compare [4] with "d"
                     // if '?x:a' is removed [4] on alert result (undefined[4]) will error
                     // if '[4]!="d"' is removed the if will evaluate "world" (true)
                     // if '!', '!="d"' or '(alert...[4]!=' is removed the if will
                     //     evaluate "d" (true)
)x                   // throws x is not defined if reached

// any other combination of removing substrings results in a syntax error
usuario81655
fuente
eliminar todo excepto a="world", no se produce un error
anOKsquirrel
3
@anOKsquirrel Solo se puede eliminar una sola subcadena.
Dennis
44
Pasé por esto como "¿Podría eliminar esto? No, este error ocurriría. ¿Se puede eliminar? Bueno, supongo que causaría este otro error. ¡Ajá! ¡Esos caracteres se pueden eliminar! Oh, espera ..." +1
ETHproductions
if(a="world")["bol"+a[4]]no error
anOKsquirrel
44
Santa vaca, ¡ahora es el doble de impresionante! Ojalá pudiera hacer +1 de nuevo ...
ETHproductions
15

Java 8, 301 bytes

Porque cada pregunta necesita una respuesta Java.

class C{static{System.out.print(((((w='w')))));System.out.print((((o='o'))));System.out.print(((r='r')));System.out.print((l='l'));System.out.print(d='d');e=(char)((f=1)/((g=8)-C.class.getDeclaredFields()[h=0].getModifiers()));}public static void main(String[]a){}static final char w,o,r,l,d,e,f,g,h;}

Expandido

class C {
    static {
        System.out.print(((((w = 'w')))));
        System.out.print((((o = 'o'))));
        System.out.print(((r = 'r')));
        System.out.print((l = 'l'));
        System.out.print(d = 'd');
        e = (char) ((f = 1) / ((g = 8) - C.class.getDeclaredFields()[h = 0].getModifiers()));
    }

    public static void main(String[] a) { }

    static final char w, o, r, l, d, e, f, g, h;
}

Explicación

  • public static main(String[]a){} es requerido.
  • Si se eliminan las declaraciones de campo (o se hacen no estáticas), el primer bloque estático no puede encontrarlas.
  • Si el bloque estático se elimina (o se hace no estático), los campos no se inicializan.

La parte más dificil:

  • Si finalse elimina la palabra clave, la segunda línea se evalúa como 1/(8-8), causando una / by zeroexcepción.
Ypnypn
fuente
¿Por qué no puede eliminar el interior de ninguna de las declaraciones impresas?
Nic Hartley
2
@QPaysTaxes No hay un System.out.print()método vacío . Hay para println(), pero no para print(). Entonces, si lo eliminara d='d', daría The method print(boolean) in the type PrintStream is not applicable for the arguments ()como error (Y si lo eliminara d=, daría The blank final field d may not have been initializedcomo error).
Kevin Cruijssen
15

Funciton , 143 142 136 bytes

La puntuación está en UTF-8 como de costumbre, ya que UTF-16 sería dos bytes más grande (debido a la lista de materiales).

╔══════════╗
║1934282307║╔╗
║5080880373╟╚╝
║80718711  ║
╚══════════╝

Entonces, he estado contemplando una respuesta Funciton por un tiempo y pensé que sería imposible, porque siempre se podía eliminar una línea completa y el código aún formaría un bloque válido. Luego hablé con Timwi al respecto, y se dio cuenta de que puedes poner todo el número en una sola línea, de modo que eliminarlo interrumpiría el programa por falta de un conector de salida.

Pero los literales en una sola línea son notoriamente caros, tanto por el mayor número de caracteres como por el mayor número de caracteres no ASCII. Y su mención de un bloque de "comentario vacío" me hizo pensar ...

Así que se me ocurrió esta solución más eficiente que utiliza un bloque de comentarios vacío adicional que se rompe cuando intenta eliminar cualquier cosa que deje intacto el bloque literal:

  • No podemos eliminar la tercera línea, porque entonces eliminaríamos el conector de salida.
  • Si eliminamos la segunda línea, el bloque de comentarios pierde su borde superior y se rompe.

Eso deja dos opciones (gracias a Steve por señalar eso):

  • Eliminar la cuarta línea. Eso deja ambas cajas intactas. Sin embargo, cuando 19342823075080880373se descodifica el entero resultante , la cadena correspondiente contendría el punto de código 0x18D53Bque no es un carácter Unicode válido, se System.Char.ConvertFromUtf32bloquea con un ArgumentOutOfRangeException.
  • Elimine una línea completa que comienza después de la esquina superior derecha. Nuevamente, ambos cuadros quedan intactos, pero el entero resultante 508088037380718711contendría dos puntos de código no válidos 0x1B0635y 0x140077, lo que llevaría a la misma excepción.

Tenga en cuenta que incluso sin el bloque de comentarios vacío, eliminar la segunda línea conduciría a un punto de código no válido. Pero el bloque de comentarios evita que tomemos una línea desde dentro de la segunda línea, para obtener un número entero como, 193428037380718711por ejemplo, lo que no causaría un error.

Martin Ender
fuente
¿Qué sucede si elimina la subcadena que comienza con el carácter después del conector de salida y termina exactamente 1 línea más tarde? es decir, eliminar la línea media del bloque de comentarios y la línea que contiene "80718711" en el bloque principal, pero dejando intactas las esquinas de ambos cuadros.
Steve
@ Steve, he modificado la respuesta para cubrir ese caso. Después de analizarlo un poco más, esto realmente me permitió guardar dos caracteres / seis bytes.
Martin Ender
10

Rubí, 36

eval(*[(s="planet")[$>.write(s)^6]])

Asignamos s="planet", luego escribimos esa cadena en STDOUT. Esto devuelve el número de caracteres escritos. Xor eso con 6, de modo que si se escribieron otros caracteres que no sean 6, obtendremos un número entero distinto de cero. Luego nos dividimos scon ese índice. Solo el carácter 0 de s"p" es una cadena de código válida (no operativa). Pasamos eso a eval, usando la (*[argument])sintaxis que es equivalente a solo (argument)excepto que no es válida fuera de una llamada al método.

Pristineness verificado programáticamente en Ruby 1.9.3 y 2.2

histocrat
fuente
Santo cielo. Esto es increíble.
aplauso el
¿Qué pasa si quitas el *?
LegionMammal978
Luego, está pasando una matriz a eval en lugar de una cadena, que es un ArgumentError.
histocrat
9

C #, 128 118 101 bytes

Pensamiento en abusar de la regla de subcadena contigua.

El código

class h{static void Main()=>System.Console.Write(new char[1
#if!i
*5]{'w','o','r','l','d'
#endif
});}

Por qué funciona

  1. class hy static void Main()son obligatorios
  2. Eliminar cualquiera de los caracteres en 'w','o','r','l','d'causa un error porque la matriz de caracteres se inicializa con longitud 1*5.
  3. No puede eliminar el contenido dentro de Main () sin violar la regla de caracteres contiguos ya que las partes están separadas por preprocs. (Vea abajo)

Antes del golf y la separación

class h
{
    static void Main() =>
        System.Console.Write(new char[1 * 5]{'w','o','r','l','d'});
}

Verificado con

https://ideone.com/wEdB54

EDITAR:

  • Guardado algunos bytes usando en #if !xlugar de #if x #else.
  • =>Sintaxis func usada . #if!xen lugar de #if !x. Créditos a @JohnBot.
  • Debido a la =>sintaxis de func, se puede eliminar la condición adicional de preproc.
Helix Quar
fuente
Hola helix ¿Crees que podrías explicar cómo y por qué tu respuesta funciona un poco más?
isaacg
@isaacg Editado. Prueba de seguir.
Helix Quar
No puedo hacerlo funcionar sin staticencendido Main.
Johnbot
@Johnbot Sí. Debe haber copiado mal. Fijo.
Helix Quar
Puede guardar un personaje al hacer Mainun miembro de la función Expresión de cuerpo y 2 más por la eliminación de los espacios antes del preprocesador condición: class h{static void Main()=>System.Console.Write(new char[1\n#if!l\n*5]{'w','o','r','l','d'\n#if!o\n});\n#endif\n}\n#endif. Eso es 115 por mi cuenta.
Johnbot
9

MATLAB, 37 36 33 bytes

feval(@disp,reshape('world',1,5))

Como no estoy seguro de si también se nos permite generar ans = , tuve que encontrar una solución alternativa para generar de manera adecuada. Usar fprintf por sí solo no funcionó, porque no importa lo que intenté, simplemente se negó a cometer errores. Usar disp por sí mismo no era una opción, ya que solo tomaría 1 argumento y ese argumento en sí mismo obviamente también se ejecutaría sin errores.

Si no es un problema incluir también ans = en la salida, entonces MATLAB se puede hacer con 20 bytes :

reshape('world',1,5)
slvrbld
fuente
Realmente debo aprender más sobre las funciones integradas (+1) // por cierto, su programa tiene una calificación de 20
Abr001am
2
Eso realmente depende de cuán estrictas sean las reglas. Afirman que solo se debe imprimir 'mundo' (+ nueva línea final opcional), por lo que son 33 bytes.
slvrbld
Sí, contaremos esto como 33. Gracias por entender :)
Calvin's Hobbies
9

> <> , 17 bytes

e"ooooo7-c0pBhtra

Pruébalo en línea!

Imprime "tierra".

La única forma en que un ><>programa sale sin un error es ejecutando el ;carácter, lo cual es un problema, ya que puede eliminar todos los caracteres antes de eso, por lo que ese ;es el primer carácter ejecutado. Puede evitar eso utilizando el pcomando para modificar el programa para incluirlo ;durante la ejecución. La eliminación de cualquier sección del código hace ;que nunca se produzcan errores causando errores a través de las instrucciones no válidas B, hy el tdesbordamiento de la pila y los bucles infinitos que eventualmente se quedan sin memoria. Solo tenía que asegurarme de que todos los bucles infinitos continuaban llenando la pila.

Todas las variantes se probaron con este fragmento de Python:

code = 'e"ooooo7-c0pBhtra'
count = {"invalid":0, "underflow":0, "memory":0}
for l in range(1, len(code)):
    for x in range(0, len(code)-l+1):
        print(code[:x] + code[x+l:], "\t\t", end='')
        try:
            interp = Interpreter(code[:x]+code[x+l:])
            for _ in range(0,1000):
                interp.move()
            print(len(interp._stack), "< ", end='')
            interp2 = Interpreter(code[:x]+code[x+l:])
            for _ in range(0,2000):
                interp2.move()
            print(len(interp2._stack))
            count["memory"] += 1
        except Exception as e:
            print(e)
            if str(e) == "pop from empty list": count["underflow"] += 1
            else: count["invalid"] += 1
print(count) 
#don't judge me

agregado a (una versión ligeramente modificada de) el intérprete oficial fish.py por el creador de> <>. De los 152 subprogramas posibles, 92 se equivocaron debido a instrucciones no válidas, 18 por desbordamiento de pila y 42 por quedarse sin memoria.

Hechos curiosos, la primera versión de esto e"ooooo6-c0pAhtratenía un par de subprogramas extraños que lograron usar el comando put para colocar uno [que despejaría la pila, en lugar de la instrucción no válida A. Además, "tierra" es la única de las frases que funcionará con este método, porque la primera letra ees una instrucción válida en ><>. De lo contrario, el "comando debe colocarse al frente del programa, y ​​un subprograma válido podría ser solo ".

Jo King
fuente
8

Rubí, 34

eval(*[($>.write("world")-1).chr])

Esto tiene algunos componentes:

eval(*[ expr ]) se toma prestado de la respuesta de histocrat , y es prístino, además de verificar que el valor de retorno de expr es un programa ruby ​​válido que no falla. method(*arr)es una sintaxis de ruby ​​que llama methodcon los valores de arrcomo argumentos. La razón de esto es necesario aquí es porque es solamente válida como parámetros para un método, por lo que si evalse quita, (*[expr])es un error de sintaxis. Si se elimina expr , se evalqueja de no tener suficientes argumentos

$>.write("world")-1no se puede destrozar excepto dentro de la cadena y la resta. $>.write("world")escribe "mundo" en STDOUT y devuelve el número de caracteres escritos, luego resta 1. Por lo tanto, si el programa no está destrozado, el valor será exactamente 4 . Si está destrozado (ya sea que -1se elimine o la cadena se acorte), devolverá uno de -1,0,1,2,3 o 5 . Cualquier otra alteración da como resultado un error de sintaxis.

Llamar chra un número devuelve el carácter representado por ese número. Entonces, cuando se invoca el resultado del ejemplo anterior, se produce un error en -1 y, de lo contrario, devuelve una cadena de un solo carácter.

No estoy seguro de por qué es así, pero parece que ruby ​​interpreta \x04como un carácter de espacio en blanco, lo que significa que la expresión es válida (los programas de ruby ​​vacíos no hacen nada). Sin embargo, cualquiera de los otros caracteres ( \x00- \x03y \x05) resultan en Invalid char '\x01' in expression. Encontré esto simplemente iterando sobre las posibles matemáticas que podía hacer con el número devuelto. Anteriormente había usado

$>.write("planet
")*16

donde "planeta" más una nueva línea eran 7 caracteres, 16 veces para obtener 112 p, la única función de una letra en ruby ​​definida por defecto. Cuando no se le dan argumentos, es efectivamente un no-op


Mención de honor: $><<"%c"*5%%w(w o r l d)está muy cerca, pero no está impecable. Eliminar "%c"*5%resultados sin errores. Mini explicación:

$>es stdout y se <<llama a una función en él. "%c"*5genera la cadena de formato "%c%c%c%c%c", que luego intenta ser formateada ( %) por una matriz: %w(w o r l d)que es una versión más corta de ['w','o','r','l','d']. Si hay muy pocos o demasiados elementos en la matriz de manera que no coincida con la cadena de formato, se muestra un error. El talón de Aquiles es eso "%c"*5, y %w(w o r l d)ambos pueden existir de forma independiente, y $><<solo necesita un argumento de ambos. Por lo tanto, hay algunas formas diferentes de destrozar este programa en primos sin errores.


Validado usando esto:

s = 'eval(*[($>.write("world")-1).chr])'
puts s.size
(1...s.length).each do |len| #how much to remove
  (0...len).each do |i| #where to remove from
    to_test = s.dup
    to_test.slice!(i,len)
    begin #Feels so backwards; I want it to error and I'm sad when it works.
      eval(to_test)
      puts to_test
      puts "WORKED :("
      exit
    rescue SyntaxError
      #Have to have a separate rescue since syntax errors
      #are not in the same category as most other errors
      #in ruby, and so are not caught by default with 
      #a plain rescue
    rescue
      #this is good
    end
  end
end
Shelvacu
fuente
Una explicación a lo largo de las líneas de la respuesta del histocrático sería agradable. Parece que está utilizando el mismo enfoque básico, pero como no conozco a Ruby, no puedo entender los detalles.
ThisSuitIsBlackNot
@ThisSuitIsBlackNot ¿Hice lo mejor que pude, algo que no entiende?
Shelvacu
Excelente explicación, gracias!
ThisSuitIsBlackNot
6

Python 3 , 43 bytes

for[]in{5:[]}[open(1,"w").write("world")]:a

Pruébalo en línea!

Cómo funciona

Para protegernos contra las eliminaciones de subcadenas, utilizamos en open(1,"w").writelugar de print. En Python 3, writedevuelve el número de caracteres escritos, lo que verificaremos es 5asegurarnos de que no se eliminó ninguna parte de la cadena. Hacemos esto al buscar el valor de retorno en el diccionario {5:[]}y recorrer el resultado con for[]in…:a, que fallará si no obtuvimos un iterable vacío o si la fordeclaración se elimina.

Anders Kaseorg
fuente
4

Javascript (Node.js), 93 95 bytes

if(l=arguments.callee.toString().length,l!=158)throw l;console.log("world");if(g=l!=158)throw g

Compruebe su propio tamaño dos veces, por lo que si falta algún carácter, se genera un error. La longitud es 156 porque Node.js antecede function (exports, require, module, __filename, __dirname) {al código en tiempo de ejecución.

Gracias Martin Büttner por señalar un error. Corregido ahora.

Naouak
fuente
4

Perl 5.10+, 71 63 bytes

(${open 0;@{\(read(0,$a,63)!=63?die:@_)};say"world"});{$a//die}

Imprime worldcon una nueva línea final. Corre así:

perl -M5.010 file

Esto se basa en el recuento de bytes del código fuente, por lo que filedebe contener el código anterior y nada más (sin shebang, sin línea nueva). Se requiere Perl 5.10+ sayy el operador definido u //.


Es increíblemente difícil hacer un programa prístino con Perl, porque:

  • Cualquier identificador bareword (por ejemplo foo, a, _) es una declaración válida con no strict 'subs';(el valor predeterminado). Esto significa que el programa no puede comenzar ni terminar con una letra, número o guión bajo.

  • Como explica tchrist , "los identificadores especificados mediante desreferencia simbólica no tienen absolutamente ninguna restricción en sus nombres". Esto significa que el programa no puede comenzar con cualquiera de los sellos $, @, %, o *, ya que la eliminación de todo menos el primer y último personaje se deje siempre un nombre de variable válido.

  • Muchas funciones integradas (incluidas la mayoría de las funciones capaces de producir resultados) funcionan $_de forma predeterminada, por lo que las llamadas a menudo funcionarán incluso si elimina el argumento (por ejemplo, say"world"vs. say).

Cómo funciona

Esta solución se inspiró en la respuesta Node.js de Naouak , que verifica su propia longitud para asegurarse de que no se hayan eliminado los caracteres.

El programa tiene dos secciones, una dentro de paréntesis y la otra dentro de un bloque:

(...);{...}

La primera sección lee el archivo fuente y muere si tiene menos de 63 caracteres. La segunda sección verifica que se readejecute con éxito. Si se elimina cualquiera de las secciones (con o sin paréntesis o llaves), la otra sección generará una excepción.

Quitar el medio o el lado izquierdo o derecho del programa desequilibrará los paréntesis y / o llaves, causando un error de sintaxis.

Si el primero diese altera (a d, e, di, de, o ie, que son todos identificadores válidos), la comprobación de longitud se convierte en:

@{\(read(0,$a,63)!=63?di:@_)};

que evalúa a:

@{\'di'};

Esto toma una referencia a una cadena e intenta desreferenciarla como una matriz, produciendo un error:

Not an ARRAY reference

Si se altera cualquier otra declaración, la verificación de longitud fallará y el programa morirá.


Prístino verificado con el siguiente programa:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use File::Temp;
use List::MoreUtils qw(uniq);

sub delete_substr {
    my ($str, $offset, $len) = @_;

    my $tmp = $str;
    substr($tmp, $offset, $len) = '';

    return $tmp;
}

sub generate_subprograms {
    my ($source) = @_;

    my $tot_len = length $source;
    my @subprograms;                                             

    foreach my $len (1 .. $tot_len - 1) { 
        foreach my $offset (0 .. $tot_len - $len) {
            push @subprograms, delete_substr($source, $offset, $len);
        }                                                        
    }                                                            

    return uniq @subprograms;                                    
}                                                                

chomp(my $source = <DATA>);                                                                                                       
my $temp = File::Temp->new;                                                                                        

foreach my $subprogram ( generate_subprograms($source) ) {       
    print $temp $subprogram;

    my $ret = system(qq{/usr/bin/perl -M5.010 $temp > /dev/null 2>&1});
    say($subprogram), last if $ret == 0;

    truncate $temp, 0;
    seek $temp, 0, 0;
}

__DATA__
(${open 0;@{\(read(0,$a,63)!=63?die:@_)};say"world"});{$a//die}
ThisSuitIsBlackNot
fuente
4

Ruby + coreutils, 33 27 26 bytes

`base#{$>.write"world
"}4`

Pruébalo en línea!

Los backticks en ruby ​​ejecutan el comando dentro de ellos y devuelven lo que el programa puso en STDOUT como una cadena. La #{expr}sintaxis permite incrustar expresiones en cadenas y backticks. Este programa podría reescribirse (de manera no prístina) como:

system("base" + (STDOUT.write("world\n")).to_s + "4")

IO#writedevuelve el número de bytes escritos, por lo que si la cadena se acorta, no será el número correcto. #{}incrustar automáticamente convierte el número en una cadena. Si se elimina alguna pieza y no se produce un error de sintaxis, se ejecutará el comando incorrecto. Si "world"se elimina parte de, uno de los base04intentos base54intentará ejecutarse.

La nueva línea, ya sea dentro o fuera de la cadena, es obligatoria. De lo contrario, `basese pueden eliminar los primeros 5 caracteres ( ), lo que convierte la línea completa en un comentario. También debe haber uno o más caracteres entre el primer backtick y #, de lo contrario, se {pueden eliminar para hacer que todo sea un comentario de shell .


exec(*[(s="ec%co earth")%s[10]])

execReemplaza el proceso actual de ruby ​​con el comando especificado. Vea mi otra respuesta para una explicación de la meth(*[])sintaxis y la necesidad de la misma.

(s="ec%co earth")asigna la cadena "ec% co earth" a la variable s. Las asignaciones devuelven lo que se asignó, por lo que la cadena también se devuelve.

"format string %d" % 5es azúcar sintáctico para sprintf("format string %d",5), sin embargo, los espacios alrededor %no son necesarios.

s[10]obtiene el carácter en la cadena en el índice 10. Cuando no está destrozado, este carácter es "h", la última letra de la cadena. Sin embargo, eliminar cualquier carácter de la cadena significa que la cadena es más corta, por lo que no hay ningún carácter en el índice 10, por lo que se s[10]devuelve nily "%c" % nilcausa un error.

si %s[10]se elimina, entonces ruby ​​intenta ejecutar el comando ec%co earthque no funciona.

Cambiando 10a 1, o 0también se traduce en un comando desconocido (ya sea eceoo ecco). Eliminarlo por completo no es técnicamente un error de sintaxis, ya que llama al método #[]en la cadena, pero luego se queja de que no hay suficientes argumentos.


Una nota sobre cómo resolver esto en general: debe tener algún contenedor que verifique el código en su interior en un sentido abstracto mientras es impecable. Por ejemplo, un programa con división al final ( blablabla/somevar) nunca funcionará porque una división siempre se puede eliminar ( blablabla). Estos son algunos de estos envoltorios que he usado hasta ahora:

  • eval(*[código ])utilizado por histocrat y en mi primera respuesta. Valida que la salida es un programa ruby ​​válido
  • exec(*[código ])utilizado anteriormente, valida que la respuesta es un comando válido
  • `#{ código }`

La sintaxis de retroceso también ejecuta un comando (y, por lo tanto, valida que sea válido), sin embargo, STDOUT se captura como una cadena en lugar de salir como el STDOUT del proceso principal '(Ruby). Debido a esto no pude usarlo para esta respuesta, EDITAR: lo hice funcionar. Limitaciones descritas anteriormente.

Editar: Gracias a @histocrat por señalar algunos defectos

Shelvacu
fuente
Enfoque genial! Puede (y, por lo tanto, debe) eliminar el espacio entre writey el inicio de la cadena, pero no creo que eso afecte el estado prístino. Además, en mi máquina base64colgará esperando la entrada, lo que podría estar en contra de las reglas.
histocrat
@histocrat Wow, estoy sorprendido de que $>.write"world"funcione, ¡gracias! En cuanto a la base64 en espera de entrada, parece variar según el sistema. TIO funciona bien. Eso hace que sea aún más confuso si sigue las reglas.
Shelvacu
3

PowerShell, (97 bytes + 5 para el nombre del programa) = 102 bytes

"$(try{if(($a=(gc .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a

Se controla antes de que se destruya ... dos veces.

Espera que se guardan como c.ps1y ejecutados desde el directorio local, tales como:
PS C:\Tools\Scripts\Golfing\> .\c.ps1.

El alias gces la abreviatura Get-Contenty es similar a la catlectura de un archivo (en este caso, nuestra ruta de ejecución .\c.ps1). Obtenemos .Lengthel archivo, lo configuramos $ay verificamos si no es igual a 97 con -eq97. Si es igual (es decir, el programa no se ha modificado), imprimimos con "world"y ejecutamos un comando no válido a. Esto obliga catcha que surta efecto, lo que nos permite controlarnos nuevamente. Esta vez, si nuestro código no es igual a 97, lanzamos un comando no válido para que nuestro programa tenga errores e imprima texto de error en la salida. Entonces clear()el error y exitnormalmente.

Es obvio que si alguna de las ifdeclaraciones se manipula, la otra tendrá un error. Si "world";se altera cualquier parte de , la primera ifcausará un error. Como tiene que ser contiguo, no podemos eliminar ambas ifdeclaraciones. Las cadenas en el medio resultarán en paréntesis no coincidentes, o resultarán en la {a}ejecución del segundo . El try/ catches detectar el error de la primera ifinstrucción para que podamos borrarlo correctamente. El exterior "$( )"evita que las cadenas de ambos extremos se corten. Lo último ;aes evitar que partes del medio se corten y que resulten en programas válidos (por ejemplo "it}a)";a, que se imprimirán it}a)y luego se producirán errores).

Hay varias circunstancias especiales:

  • Si se eliminan gc, gc<space>o gc .\, el programa eventualmente fallará con un poco de error de falta de memoria (debido a repetidas llamadas de autoejecución) y probablemente bloqueará el shell (y tal vez la computadora). No probado.
  • Si se eliminan <space>.\c.ps1o .\c.ps1, el programa se detendrá y solicitará la entrada del usuario. No importa lo que ingrese el usuario, el programa seguirá teniendo errores, ya que el recuento de tamaños será incorrecto.
  • Si una subcadena que comienza en $y termina antes de que "se corte la última , el programa generará lo que quede y luego generará un error porque ano es válido.

Verificado con lo siguiente:

$x='"$(try{if(($a=(gc .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yy='"$(try{if(($a=( .\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yyy='"$(try{if(($a=(.\c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'
$yyyy='"$(try{if(($a=(c.ps1).Length)-eq97){"world";a}}catch{if($a-ne97){a}$error.clear();exit}a)";a'

for($i=1;$i-lt$x.Length;$i++){
  for($j=0;$j-lt($x.Length-$i);$j++){
    $y=($x[0..$j]+$x[($i+$j+1)..$x.Length])-join''
    $y>.\c.ps1
    $error.clear()
    if(!($y-in($yy,$yyy,$yyyy))){try{.\c.ps1}catch{};if(!($error)){exit}}
    $q++;
    write-host -n "."
    if(!($q%150)){""}
  }
}
"No success."

(¡Gracias a Martin por su amplia ayuda!)

AdmBorkBork
fuente
3

C (gcc) (Linux, -Werror=undef), 66 bytes

main(a){a
=
1
/
(puts("world")/
6);
#if(7^__LINE__)
#else
}
#endif

Pruébalo en línea!

¡Gran reto! Esto fue engañosamente difícil, ¡pero estoy bastante seguro de que tengo un programa válido ahora!

Utiliza un comando de preprocesador para que no se puedan eliminar nuevas líneas, ya que el corchete de cierre mainse incluye solo si __LINE__==6. También evita que se limpie por maincompleto, ya que eso deja #endifflotando (por lo que es importante que #endifesté fuera de main).

Lo utilicé #elseporque me he convencido bastante de que no hay una versión de __LINE__==6que no se pueda eliminar una subcadena y aún así sea verdad, ya que ambas 6y __LINE__por sí mismas son verdaderas. También se usa -Werror=undefpara que algo así #ifdef(LINE__)no se evalúe como falso, pero es un error.

Con gcc (en Linux, al menos), putsdevuelve el número de caracteres impresos (incluida la nueva línea final), por lo que al eliminar cualquier parte de la cadena se puts("...")/6devuelve 0, lo que 1/0provoca una excepción de punto flotante. Tenga en cuenta que esta excepción no se produce a menos que 1/0se asigne a algo, por lo que a=se requiere.

Ninguna otra parte de una línea se puede eliminar sin crear un error, generalmente un error de sintaxis o un error de enlace.

Como beneficio adicional, esto proporciona una solución de 86 bytes para C ++ bastante trivialmente, solo agregue #include <cstdio>y declare acomo un int. Pruébalo en línea! (C ++)

Chris
fuente
A menos que me equivoque, puede eliminarlo 1/mientras deja la nueva línea y aún se ejecutará .
gastropner
@gastropner Tienes razón. 1se suponía que en la línea anterior, creo.
Chris
Lamentablemente, lo mismo ocurre. A continuación, puede eliminar =1. Creo que necesitas poner el 1 en una línea por sí solo.
Gastropner
@gastropner Creo que tienes razón. Veré más tarde. ¡Gracias!
Chris
2

PHP, 73 bytes

<?=call_user_func(($p='ns')|(($f="u{$p}erialize"))?$f:'','s:5:"world"');

Explicacion

Asumo la configuración predeterminada de php.ini. Entonces short_tags está deshabilitado. Esto significa que no puede eliminar el =de la etiqueta de apertura.

Esto es básicamente <?=unserialize('s:5:"world"');.

Si elimina cualquier parte de la cadena serializada, obtendrá un error.

Simplemente puede eliminar unserializey el script solo generará la cadena serializada. Para superar esto lo uso call_user_func. Eliminar uno de los parámetros dará como resultado un error.

'<?=call_user_func('unserialize','s:5:"world"');

Sin embargo, puede eliminar un, para llamar a la serializefunción. Entonces sacamos 'ns'. Eliminar cualquier carácter no daría como resultado un nombre de función incorrecto.

<?=call_user_func(($p='ns')&&($f="u{$p}erialize")?$f:'','s:5:"world"');

Usaremos una asignación en línea para usar la asignación de variables con la etiqueta de salida. En lugar de usar &&, usamos '|' para evitar eliminar una sola &o eliminar la $fasignación

Podrías eliminar ='ns')&&($f="u{$p}erialize"y terminar con ($p)?$f:''. Por lo tanto, agrego paréntesis adicionales alrededor $f="u{$p}erialize".

Nota

Técnicamente, puede eliminar las etiquetas de apertura sin producir un error. Sin embargo, esto ya no es un script PHP, sino solo un archivo de texto sin formato.

Jasny - Arnold Daniels
fuente
2
Acerca de su última nota, el archivo de texto sin formato seguiría siendo un programa PHP válido, ¿verdad? Entonces no estoy seguro de que esto sea válido.
Aficiones de Calvin
Ya no es PHP, sino texto sin formato / html, por lo que ya no es un programa php válido
Martijn
1

Matlab (77)

bsxfun(@(c,b)arrayfun(@(x)getfield(c,{x}),conv(b,ismember(4,b))),'world',1:5)

intentalo

Nota:

Siguiendo el consejo de @ Optimiser de diseñar una RCP o algo así, me enfrenté a una subcadena imprevista que no condujo a ningún error de compilación cuando se eliminó, por ejemplo: ¡eliminar arrayfun(@(x)a(x),prod(b,ismember(4,1:5))),de esta edición anterior feval(@(a)arrayfun(@(x)a(x),prod(b,ismember(4,1:5))),'world')no genera ningún error! También, para la misma edición reciente, hubo bsxfun(@(a,b)arrayfun(@(x)(x),prod(b,ismember(4,b))),'world',1:5)y bsxfun(@(a,b)a,'world',1:5), si me preguntaron cómo estaba cuando los descubrí en mi consola de salida, lloré como un bebé, así que aquí está el programa:

b=0;string='bsxfun(@(c,b)arrayfun(@(x)getfield(c,{x}),conv(b,ismember(4,b))),''world'',1:5)'
for u=1:numel(string),for j=u:numel(string)-2,try a=eval([string(1:u) string(j+2:end)]);catch(b); a=0;end; if a~=0, ['here is it : ' string(1:u) string(j+2:end)],end;end;end

Un ejemplo de un programa no prístino

editar:

Gracias a todos al lado de @Martin por señalar mi código anterior (sin errores).

Abr001am
fuente
1

SmileBASIC, 63 bytes

REPEAT
A=1/(PRGSIZE(0,1)==63)?"world
UNTIL 1/(PRGSIZE(0,1)==63)
12Me21
fuente
1

Un peral , 17 bytes

Este programa contiene bytes con el conjunto de bits alto (que no son válidos UTF-8 y, por lo tanto, no se pueden publicar en TIO), así que aquí hay un xxdvolcado hexadecimal reversible:

00000000: 7072 696e 7427 776f 726c 6427 23cd 4290  print'world'#.B.
00000010: bf                                       .

Explicación

Esto es solo print'world'con una suma de verificación añadida. Verifiqué por fuerza bruta que ninguna de las posibles eliminaciones da un programa con una suma de verificación válida, por lo que obtiene un error después de una posible eliminación.

Bastante aburrido, pero vincula al líder actual, así que sentí que valía la pena publicarlo.

ais523
fuente