alcanzar la captura cuando todo en el bloque de prueba ya está atrapado

19

Supongo que esto está limitado a Java y C # por la sintaxis.

En este rompecabezas de programación, debes producir Exceptions que se puedan atrapar pero que se vuelvan a lanzar al final del bloque de captura.

try
{
    while(true)
        try
        {
            // you are only allowed to modify code between this try { } brackets
        }
        catch(Exception ex2) {  }
}
catch(Exception ex1)
{
    // your goal is to reach this catch block by modifying the code ...
    // in the inner try block above
    // You win if you reach this part and execute on of the following code lines
    Console.WriteLine("You won!"); // for C#
    // Or
    System.out.println("You won!"); // for Java
}

Puedes poner código libremente antes y después de este fragmento.

El código más corto para alcanzar el catchbloque exterior gana.

usuario21634
fuente
1
Creo que Python también puede competir.
user12205
1
Puedes poner código libremente antes y después de mi fragmento.
user21634
2
Lástima que esté cerrado. Tengo una solución . Para @algorithmshark, Michael y Jan Dvorak: Esta NO es una pregunta de programación general. Es un rompecabezas de programación, similar a ¿ Cuándo una jirafa no es una jirafa? . Estoy nominando esto para reabrir.
user12205
1
Uhhhhhh, Whaaat ???
TheDoctor
1
@algorithmshark Iría con la suma de las longitudes de las inserciones
user12205

Respuestas:

24

C #, 46 (88 incluyendo repetitivo)

using System;class P{static void Main(){
        try
        {
            while(true)
                try
                {
                    System.Threading.Thread.CurrentThread.Abort();
                }
                catch(Exception ex2) {  }
        }
        catch(Exception ex1)
        {
            // your goal is to reach this catch block by modifying the code ...
            // in the inner try block above
            // You win if you reach this part and execute on of the following code lines
            Console.WriteLine("You won!"); // for C#
        }
}}

El Abort()método genera una ThreadAbortException , que es una excepción especial que se vuelve a generar automáticamente al final de cada bloque catch (a menos que Thread.ResetAbort()se llame).

BenM
fuente
20

Personajes C # 24

termina el bloque de prueba interno antes de lo previsto, lo que me permite causar una excepción fuera del bloque de prueba.

}finally{int a=1/0;}try{
rdans
fuente
1
Hombre, esto es genial! ¿Por qué no pensé en eso? (Por cierto, ¿puede acortarlo causando una excepción en lugar de lanzar una excepción, por ejemplo int a=1/0;?)
user12205
¿Necesitas int a=allí? Algunos idiomas le permiten simplemente escribir la expresión1/0
gnibbler
Este no es un ejemplo de trabajo completo, ¿verdad? Entonces los 24 caracteres no cuentan ...
Matt
13

Java, 76 o 31

Contando solo las inserciones realizadas en el código, ignorando nuevas líneas. 76 si cuenta todo lo que he agregado, 31 si excluye la primera línea y la última línea, es decir, solo cuenta int a=1/0;try{}catch(Error e){}.

class P{public static void main(String[]A){
try
{
    while(true)
        try
        {
            int a=1/0;try{
        }
        catch(Exception ex2) {  }
}
catch(Exception ex1)
{
    // your goal is to reach this catch block by modifying the code ...
    // in the inner try block above
    // You win if you reach this part and execute on of the following code lines
    //Console.WriteLine("You won!"); // for C#
    // Or
    System.out.println("You won!"); // for Java
}
}catch(Error e){}
}}
usuario12205
fuente
Vaya, lo siento, no presté atención a cómo contabas. Actualizaré mi respuesta para agregar el otro método de conteo. Creo que solo es mejor contar los caracteres en el bloque de prueba, ya que de lo contrario básicamente estaríamos comparando C # vs Java repetitivo. Pero eso podría complicarse si alguien envía una respuesta con un código importante fuera del bloque try (como lo permiten las reglas).
BenM
@BenM No se preocupe, y entiendo por qué lo contó de esa manera. Es solo que el OP no especificó qué manera de contar, así que pensé que incluiría ambos.
user12205
Solución muy inteligente.
Nicolas Barbulesco
@NicolasBarbulesco Para ser sincero, creo que la respuesta de Ryan es más inteligente que la mía. Después de todo, agregué un catchbloque después del fragmento, no lo hizo.
user12205
3

Advertencia : estos programas son bombas clónicas (una especie de forma de bomba tenedor menos peligrosa pero aún peligrosa); como tal, no los ejecute en un sistema de producción sin sandboxing o límites de recursos . Las bombas clónicas crean hilos en un bucle (a diferencia de las bombas de horquilla, que crean procesos en un bucle), por lo que puede detenerlas simplemente matando el proceso en cuestión (haciéndolas mucho menos peligrosas que las bombas de horquilla, lo que puede ser muy difícil de manejar). aclarar); pero probablemente atarán la mayor parte de su CPU hasta que logre hacerlo (o hasta que el programa gane y salga naturalmente por sí mismo). Pedirle a su sistema operativo que establezca límites en la cantidad de memoria y tiempo de CPU que estos programas pueden usar debería crear un entorno seguro en el que probarlos.

Java (OpenJDK 8) , 65 60 bytes (con una ligera modificación en el contenedor)

Thread x=Thread.currentThread();new Thread(x::stop).start();

Pruébalo en línea!

Requiere que ambas instancias de catch (Exception …)la pregunta se cambien a catch (Throwable …). En teoría, esto debería ser más seguro, no menos, pero permite que esta solución sea posible.

Ahorré 5 bytes en la primera versión de esta respuesta mediante el uso de una referencia de método en lugar de una lambda.

Java 4, 104 bytes (no probado, debería funcionar con el contenedor original)

final Thread x=Thread.currentThread();new Thread(){public void run(){x.stop(new Exception());}}.start();

Pruébalo en línea! (el enlace va a una implementación de Java 8, por lo tanto no funcionará)

Usando características que se han eliminado de las versiones modernas de Java, es posible resolver incluso la versión del rompecabezas que requiere un Exception. Probablemente, al menos. (Java 4 es muy antiguo por ahora y no puedo recordar qué características tenía y no contenía. Como se puede ver, había muchas menos características en Java en ese momento y, por lo tanto, era más detallado; no teníamos lambdas, así que tuve que crear una clase interna).

Explicaciones

La mayoría de las soluciones a esta pregunta están en C # (junto con una solución Java que engaña mediante el uso de corchetes desequilibrados como una forma de inyección de código, y una solución Perl que tampoco está en Java). Así que pensé que valdría la pena intentar mostrar cómo este rompecabezas también se puede resolver "correctamente" en Java.

Ambos programas son efectivamente idénticos (por lo tanto, el hecho de que el primer programa funcione me da mucha confianza en que el segundo programa también funcionaría, a menos que accidentalmente haya usado una característica que no sea Java-4; Thread#stopfue desaprobada en Java 5).

El Thread#stopmétodo de Java funciona, detrás de escena, al hacer que se arroje un elemento arrojable al hilo en cuestión. Lo que se puede usar para ese propósito es ThreadDeath(y Error, específicamente, porque la gente a menudo trata de ocultar las excepciones y los diseñadores de Java no querían que eso sucediera), aunque le permite lanzar cualquier cosa (o solía hacerlo; en algún momento después de que la API fue diseñado, los diseñadores de Java se dieron cuenta de que esta era una idea increíblemente mala y eliminaron la versión del método que toma los argumentos directamente). Por supuesto, incluso la versión que arroja ThreadDeathes una operación bastante arriesgada sobre la que puede hacer pocas garantías (por ejemplo, le permite resolver este rompecabezas, algo que "no debería" ser posible), por lo que no debe hacerlo úsalo, pero a partir de Java 8, todavía funciona.

Este programa funciona generando un nuevo hilo y pidiéndole que arroje una excepción al hilo principal. Si tenemos suerte, lo hará en un momento dado cuando estemos fuera del catchbloque interno (no podemos escapar del catchbloque externo hasta que finalice el programa, porque hay un bucle a su alrededor). Debido a que ya tenemos el bucle convenientemente agregado, es un ahorro de bytes simplemente usar ese bucle para permitirnos seguir creando subprocesos, con la esperanza de que uno de ellos finalmente llegue al momento correcto. Esto normalmente parece suceder en un par de segundos.

(Nota de TIO: la versión actual de TIO está bastante inclinada a matar este programa al principio de su ejecución, presumiblemente debido a todos los hilos que se están creando. Puede funcionar en TIO, pero no funciona de manera confiable, por lo que a menudo se requieren algunos intentos para obtén la salida "¡Ganaste!")

ais523
fuente
1

C#

    try
    {
        int i = 0, j = 1, k;

        int flag = 0;
        lbl:
        if (flag == 1)
        {
            k = j / i;
        }

        while (true)
            try
            {
                k = j / i;

            }
            catch (Exception e)
            {
                flag = 1;
                goto lbl;
                //Console.WriteLine("loose");

            }
    }
    catch (Exception e)
    {
        Console.WriteLine("Won");

    }
devendra
fuente
1
¡Bienvenido a Programming Puzzles & Code Golf! Como esta pregunta es un desafío de código de golf , intente hacer su código lo más breve posible e incluya el recuento de caracteres en la parte superior de su respuesta. ¡Gracias!
ProgramFOX
1

Perl 5 , 37 o 36 bytes

eval {
    while (1) {
        eval {

 

use overload'""',sub{die};die bless[]

 

        };
        $@ eq "" or 0;
    }
};
$@ eq "" or print "You won!\n";

Pruébalo en línea!

Resulta que esta pregunta se traduce en Perl lo suficientemente bien como para hacer un rompecabezas interesante allí también. El tryequivalente de Perl se llama (un poco confuso) eval, y especifica una excepción estableciendo @_una excepción si ocurrió, y la cadena nula de lo contrario. Como tal, un catchbloque se implementa mediante la comparación @_con la cadena nula.

Esta solución funciona creando un objeto (cuya clase es el programa en su conjunto; puede usar archivos Perl arbitrarios como clases, algo así como el reverso de Java (donde puede usar clases arbitrarias como archivos)). Esa es la bless[]parte ( blessnormalmente solo aparece en el interior de los constructores, como la primitiva que convierte las cosas en objetos en primer lugar, pero puede usarla directamente si realmente lo desea; []es el asignador de memoria para el objeto, un constructor de listas, en este case - y la clase no se da, por lo que se supone que es la que se está ejecutando actualmente). Mientras tanto, le damos a nuestra "clase" (es decir, el archivo principal) un método personalizado de comparación a cadena a través de use overload, y hacemos que ese método arroje una excepción (rompiendo así el bucle y resolviendo el rompecabezas); en realidad podemos poner eluse overloaden cualquier lugar, y aunque tradicionalmente iría con las otras definiciones de métodos y se acercaría a la parte superior del archivo, podemos colocarlo en el espacio que se nos ha dado y aún funciona. (Si lo colocamos al final del archivo, podríamos omitir el punto y coma después de él, lo que llevaría a una solución de 36 bytes, pero esto podría decirse que es una trampa, ya que depende del programa que tenga un punto y coma final en primer lugar, que es no está garantizado.) En realidad, es más corto sobrecargar la operación stringify y dejar que Perl genere automáticamente una comparación de cadenas a partir de eso, de lo que sería sobrecargar la comparación de cadenas directamente (porque la sobrecarga de algunos operadores también obliga a sobrecargar a otros operadores).

Ahora, todo lo que tenemos que hacer es lanzar nuestro objeto usando die. Los evaltermina, a continuación, cuando se intenta comparar $@a la cadena nula (a ver si había una excepción), la comparación arroja otra excepción y que escapan al exterior eval.


fuente