alcance catch quando tudo no bloco try já está capturado


19

Isso é limitado a Java e C # pela sintaxe que eu acho.

Neste quebra-cabeça de programação, você deve produzir Exceptions que podem ser capturados, mas lançados novamente no final do bloco catch.

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
}

Você pode inserir código livremente antes e depois desse trecho.

O código mais curto para alcançar o catchbloco externo vence.


11
Eu acho que o Python também pode ser capaz de competir.
User12205

11
Você pode colocar código livremente antes e depois do meu trecho.
User21634

2
Pena que está fechado. Eu tenho uma solução . Para @algorithmshark, Michael e Jan Dvorak: Esta NÃO é uma questão de programação geral. É um quebra-cabeça de programação, semelhante a Quando uma girafa não é uma girafa? . Estou nomeando isso para reabrir.
User12205

11
Uhhhhhh, Whaaat ???
TheDoctor

11
@algorithmshark eu iria com a soma dos comprimentos das inserções
user12205

Respostas:


24

C #, 46 (88 incluindo clichê)

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#
        }
}}

O Abort()método gera um ThreadAbortException , que é uma exceção especial que é automaticamente relançada no final de cada bloco de captura (a menos que Thread.ResetAbort()seja chamado).


20

Personagens C # 24

finaliza o bloco try interno antes do pretendido, permitindo-me causar uma exceção fora do bloco try.

}finally{int a=1/0;}try{

11
Cara, isso é gênio! Por que eu não pensei nisso? (Btw você pode reduzi-lo por realmente causando uma exceção em vez de lançar uma exceção por exemplo? int a=1/0;?)
user12205

Você precisa de int a=lá? Algumas linguagens permitem que você acabou de escrever a expressão1/0
gnibbler

Este não é um exemplo completo de trabalho, é? Assim, os 24 caracteres não contam ...
Matt

13

Java, 76 ou 31

Contando apenas as inserções feitas no código, ignorando novas linhas. 76 se você contar tudo o que adicionei, 31 se você excluir a primeira e a última linha, ou seja, apenas a contagem 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){}
}}

Opa, desculpe, eu não prestei atenção em como você contava. Vou atualizar minha resposta para adicionar o outro método de contagem. Eu acho que apenas contar os caracteres no bloco try é melhor, pois caso contrário estaríamos basicamente comparando C # vs Java clichê. Mas isso pode se tornar complicado se alguém enviar uma resposta com código importante fora do bloco try (conforme permitido pelas regras).
BenM 27/05

@ BenM Não se preocupe, e eu entendo por que você contou dessa maneira. Só que o OP não especificou qual caminho contar, então achei que incluiria os dois.
User12205 27/05

Solução muito inteligente.
Nicolas Barbulesco 30/05

@NicolasBarbulesco Para ser sincero, acho que a resposta de Ryan é mais inteligente que a minha. Afinal, adicionei um catchbloco após o trecho, ele não.
User12205

3

Aviso : Esses programas são bombas clone (uma espécie de forma menos perigosa, mas ainda perigosa, de uma bomba bifurcada); como tal, não os execute em um sistema de produção sem sandboxing ou limites de recursos . As bombas clonadas criam threads em um loop (ao contrário das bombas de garfo, que criam processos em um loop), assim você pode detê-las simplesmente matando o processo em questão (tornando-as muito menos perigosas que as bombas de garfo, o que pode ser muito difícil de limpar); mas eles provavelmente amarrarão a maior parte de sua CPU até que você consiga fazê-lo (ou até o programa vencer e sair naturalmente por si só). Solicitar que o seu sistema operacional coloque limites à quantidade de memória e tempo de CPU que esses programas podem usar deve criar um ambiente seguro para testá-los.

Java (OpenJDK 8) , 65 60 bytes (com uma pequena modificação no wrapper)

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

Experimente online!

Requer que ambas as instâncias de catch (Exception …)na pergunta sejam alteradas para catch (Throwable …). Em teoria, isso deveria ser mais seguro, não menos, mas permite que essa solução seja possível.

Salvei 5 bytes sobre a primeira versão desta resposta usando uma referência de método em vez de uma lambda.

Java 4, 104 bytes (não testado, deve funcionar com o wrapper original)

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

Experimente online! (o link vai para uma implementação do Java 8, portanto, não funciona)

Usando recursos que foram removidos das versões modernas do Java, é possível resolver até a versão do quebra-cabeça que requer um Exception. Provavelmente, pelo menos. (O Java 4 já é muito antigo e não me lembro quais recursos ele contém ou não. Como pode ser visto, havia muito menos recursos no Java naquela época e, portanto, era mais detalhado; não tínhamos lambdas, então eu tive que criar uma classe interna.)

Explicações

A maioria das soluções para esta pergunta está em C # (junto com uma solução Java que engana usando colchetes desbalanceados como uma forma de injeção de código e uma solução Perl que também não está em Java). Então pensei que valeria a pena tentar mostrar como esse quebra-cabeça também pode ser resolvido "adequadamente" em Java.

Ambos os programas são efetivamente idênticos (portanto, o fato de o primeiro programa funcionar me dá grande confiança de que o segundo programa também funcionaria, a menos que eu tenha acidentalmente usado um recurso que não seja Java-4; Thread#stopfoi preterido no Java 5).

O Thread#stopmétodo de Java funciona, nos bastidores, fazendo com que um lançamento seja lançado no encadeamento em questão. O lançamento planejado para esse fim é ThreadDeath( Errorespecificamente, porque as pessoas geralmente tentam capturar exceções e os designers de Java não queriam que isso acontecesse), embora isso permita que você jogue qualquer coisa (ou acostume-se; em algum momento após o término da API) projetados, os designers de Java perceberam que essa era uma idéia incrivelmente ruim e removeram a versão do método que leva os argumentos diretamente). Obviamente, mesmo a versão lançada ThreadDeathé uma operação bastante arriscada sobre a qual você pode dar poucas garantias (por exemplo, permite solucionar esse quebra-cabeça, algo que "não deveria" ser possível), então você não deve use-o, mas a partir do Java 8, ele ainda funciona.

Esse programa funciona gerando um novo encadeamento e solicitando que ele force uma exceção de volta ao encadeamento principal. Se tivermos sorte, isso será feito em um momento em que estamos fora do catchbloco interno (não podemos escapar do catchbloco externo até que o programa termine, porque há um loop em torno dele). Como já adicionamos o loop de maneira conveniente, é economizador de bytes simplesmente usá-lo para permitir a criação de threads, na esperança de que um deles atinja o tempo correto. Isso normalmente parece acontecer em alguns segundos.

(Nota do TIO: a versão atual do TIO está bastante inclinada a interromper esse programa no início de sua execução, provavelmente devido a todos os threads que estão sendo criados. Ele pode funcionar no TIO, mas não funciona de maneira confiável, portanto, muitas vezes são necessárias algumas tentativas para obtenha a saída "Você ganhou!".)


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");

    }

11
Bem-vindo à programação de quebra-cabeças e código de golfe! Como esta pergunta é um desafio ao código-golfe , tente tornar o seu código o mais curto possível e inclua a contagem de caracteres na parte superior da sua resposta. Obrigado!
precisa

1

Perl 5 , 37 ou 36 bytes

eval {
    while (1) {
        eval {

 

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

 

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

Experimente online!

Acontece que essa pergunta se traduz em Perl bem o suficiente para criar um quebra-cabeça interessante também. O tryequivalente de Perl é chamado (um pouco confuso) evale especifica uma exceção definindo @_como uma exceção se ela ocorreu e a cadeia nula caso contrário. Como tal, um catchbloco é implementado via comparação @_com a cadeia nula.

Essa solução funciona criando um objeto (cuja classe é o programa como um todo; você pode usar arquivos Perl arbitrários como classes, como o inverso do Java (onde você pode usar classes arbitrárias como arquivos)). Essa é a bless[]parte ( blessnormalmente só aparece no fundo dos construtores, como a primitiva que transforma as coisas em objetos em primeiro lugar, mas você pode usá-la diretamente se realmente quiser; []é o alocador de memória para o objeto - um construtor de lista, neste case - e como a classe não é fornecida, é considerada a que está sendo executada atualmente). Enquanto isso, damos à nossa "classe" (ou seja, o arquivo principal) um método personalizado de comparação com string use overload, e fazemos com que esse método crie uma exceção (quebrando assim o ciclo e resolvendo o quebra-cabeça); podemos colocar ouse overloadem qualquer lugar e, embora tradicionalmente se encaixe nas outras definições de método e se aproxime da parte superior do arquivo, podemos colocá-lo na lacuna que recebemos e ainda funciona. (Se colocarmos no final do arquivo, poderíamos omitir o ponto-e-vírgula após ele, levando a uma solução de 36 bytes, mas isso é trapaça, pois é indiscutível uma trapaça, pois depende do programa ter um ponto-e-vírgula à direita em primeiro lugar, o que é não é garantido.) Na verdade, é mais curto sobrecarregar a operação stringify e permitir que o Perl gere automaticamente uma comparação de strings a partir disso, do que sobrecarregar diretamente a comparação de strings (porque sobrecarregar alguns operadores também obriga a sobrecarregar outros operadores).

Agora, tudo o que precisamos fazer é jogar nosso objeto usando die. Ele evaltermina e, quando tentamos comparar $@com a cadeia nula (para ver se houve uma exceção), a comparação lança outra exceção e escapamos do exterior eval.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.