tryブロック内のすべてがすでにキャッチされているときにcatchに到達する


19

これは、私が推測する構文によってJavaとC#に制限されています。

このプログラミングパズルでExceptionは、キャッチできるがキャッチブロックの最後に再びスローされるを生成します。

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
}

このスニペットの前後にコードを自由に配置できます。

外側のcatchブロックに到達する最短のコードが優先されます。


1
Pythonも競争できると思います。
user12205

1
スニペットの前後にコードを自由に配置できます。
user21634

2
残念です。解決策があります。@ algorithmshark、Michael、Jan Dvorakへ:これは一般的なプログラミングの質問ではありません。キリンがキリンではないときと似ているプログラミングパズルです。。私はこれを再開するために指名しています。
user12205

1
うーん
TheDoctor

1
私は挿入の長さの合計で行くと思います@algorithmshark
user12205

回答:


24

C#、46(定型文を含む88)

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

このAbort()メソッドはThreadAbortExceptionを発生させます。これは、各catchブロックの終わりで自動的に再スローされる特別な例外です(Thread.ResetAbort()呼び出されない限り)。


20

C# 24文字

意図した前に内側のtryブロックを終了し、tryブロックの外側で例外を発生させます。

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

1
これは天才だ!なぜ私はそれを考えなかったのですか?(ところで、例外をスローするのではなく、実際に例外を発生させることで短縮できますか?例int a=1/0;?)
user12205

必要int a=ですか?いくつかの言語は、あなただけの式を書いてみましょう1/0
gnibbler

これは完全な実例ではありませんか?したがって、24文字はカウントされません
マット

13

Java、76または31

新しい行を無視して、コードに行われた挿入のみをカウントします。私が追加したすべてをカウントする場合は76 、最初の行と最後の行を除外する場合は31、つまりカウントのみ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){}
}}

申し訳ありませんが、私はあなたの数え方に注意を払いませんでした。答えを更新して、他のカウント方法を追加します。そうでない場合は基本的にC#とJavaボイラープレートを比較するので、tryブロック内の文字をカウントする方が良いと考えています。ただし、誰かがtryブロックの外に重要なコードを含む回答を送信すると(ルールで許可されているように)、それは複雑になる可能性があります。
BenM

@BenM心配する必要はありません。なぜそのように数えたのか理解しています。OPがどちらの方法をカウントするかを指定しなかったというだけなので、両方を含めると思いました。
user12205

非常に賢い解決策。
ニコラスバルブレスコ

@NicolasBarbulesco正直に言うと、ライアンの答えは私のものよりも賢いと思います。結局のところ、スニペットのcatchブロックを追加しましたが、彼は追加しませんでした。
user12205

3

警告:これらのプログラムはクローン爆弾(それほど危険ではないが、まだ危険な形式のフォーク爆弾)です。など、サンドボックスまたはリソース制限なしで本番システム上でそれらを実行しないでください。クローン爆弾は、ループ内にスレッドを作成します(ループ内にプロセスを作成するフォーク爆弾とは異なります)。したがって、問題のプロセスを強制終了するだけでスレッドを停止できます(フォーク爆弾よりも危険性が低くなります。片付ける); しかし、なんとかするまで(またはプログラムが勝って自然に終了するまで)、CPUのほとんどを占有する可能性があります。これらのプログラムが使用できるメモリ量とCPU時間を制限するようにOSに依頼すると、テストする安全な環境が作成されます。

Java(OpenJDK 8)65 60バイト(ラッパーをわずかに変更)

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

オンラインでお試しください!

catch (Exception …)質問のの両方のインスタンスをに変更する必要がありますcatch (Throwable …)。理論的には、これは安全性を高めるものでありそれ以上ではありませんが、このソリューションを可能にします。

ラムダではなくメソッド参照を使用して、この回答の最初のバージョンで5バイトを節約しました。

Java 4、104バイト(未テスト、元のラッパーで動作するはずです)

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

オンラインでお試しください!(リンクはJava 8実装にリンクしているため、機能しません)

Javaの最新バージョンから削除された機能を使用すると、を必要とするパズルのバージョンでも解決できExceptionます。おそらく、少なくとも。(Java 4は今では非常に古く、どの機能が含まれていて含まれていなかったか覚えていません。ご覧のように、Javaには以前よりも多くの機能がなかったため、より冗長でした。ラムダなので、内部クラスを作成する必要がありました。)

説明

この質問に対する解決策のほとんどは、C#にあります(コードインジェクションの形式として不均衡なブラケットを使用して不正を行うJavaソリューション、およびJavaにもないPerlソリューションと共に)。したがって、このパズルがJavaでも「適切に」解決される方法を示すのは試してみる価値があると思いました。

両方のプログラムは実質的に同一です(したがって、誤って非Java-4機能を使用した場合を除き、最初のプログラムが機能するという事実から、2番目のプログラムも機能するという確信が得られます。 Thread#stop Java 5では非推奨になりました)。

JavaのThread#stopメソッドは、問題のスレッドにthrowableをスローすることにより、舞台裏で機能します。目的のスロー可能オブジェクトはThreadDeathError特に、人々が例外を包括的にキャッチしようとし、Javaの設計者がそのようなことを望んでいないためです)、それはあなたが何かをスローすることを可能にします(または、APIの後のある時点でJavaの設計者は、これが信じられないほど悪いアイデアであることに気づき、引数を取るメソッドのバージョンを完全に削除しました)。もちろん、投げるバージョンでさえ、ThreadDeathほとんど保証することができないかなり危険な操作です(たとえば、このパズルを「不可能」に解決することができます)。それを使用しますが、Java 8の時点ではまだ動作します。

このプログラムは、新しいスレッドを生成し、メインスレッドに例外を強制的にスローするように要求することで機能します。運が良ければ、内側のcatchブロックの外側にいる時点でそれを行います(catchループが存在するため、プログラムが終了するまで外側のブロックをエスケープすることはできません)。ループは既に便利に追加されているため、そのループを使用してスレッドを作成し続けることで、そのうちの1つが最終的に正しいタイミングに到達することを期待して、バイトを節約できます。これは通常、数秒以内に発生するようです。

(TIO注:現在のバージョンのTIOは、おそらくすべてのスレッドが作成されているため、実行の早い段階でこのプログラムを強制終了する傾向があります。 「You won!」の出力を取得します。)


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

    }

1
プログラミングパズルとコードゴルフへようこそ!この質問はコードとゴルフの課題なので、コードをできるだけ短くして、回答の先頭に文字数を含めてください。ありがとう!
ProgramFOX

1

Perl 5、37または36バイト

eval {
    while (1) {
        eval {

 

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

 

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

オンラインでお試しください!

この質問もPerlに変換されて、そこに興味深いパズルを作成するのに十分なことがわかりました。Perlのtry同等の関数は(少しわかりにくい)と呼ばevalれ、例外@_が発生した場合は例外を設定し、そうでない場合はnull文字列を設定します。そのため、catchブロックは@_ヌル文字列と比較して実装されます。

このソリューションは、オブジェクトを作成することで機能します(クラスは全体としてプログラムです。クラスのような任意のPerlファイルを使用できます。Javaの逆のようなものです(ファイルのような任意のクラスを使用できます)。それはbless[]部分です(bless通常、最初に物をオブジェクトにするプリミティブとして、コンストラクタの奥深くにのみ表示されますが、本当に必要な場合は直接使用できます。[]オブジェクトのメモリアロケータ-これはリストコンストラクタですケース–クラスが指定されていないため、現在実行中のクラスと見なされます。一方、「クラス」(つまり、メインファイル)にカスタムの文字列比較メソッドを提供しますuse overloadそのメソッドに例外をスローさせます(したがって、ループから抜け出してパズルを解きます)。私たちは実際に置くことができますuse overload従来は他のメソッド定義と一緒になってファイルの先頭に近づいていましたが、代わりに与えられたギャップに入れることができ、それでも動作します。(ファイルの最後に置くと、その後のセミコロンを省略できますが、36バイトの解決策になりますが、最初に末尾のセミコロンがあるプログラムに依存するため、これは間違いなく不正行為です。保証されていません。)文字列比較操作をオーバーロードし、Perlに文字列比較を自動生成させる方が、文字列比較を直接オーバーロードするよりも実際には短くなります(一部の演算子をオーバーロードすると他の演算子もオーバーロードするため)。

今、私たちがしなければならないことは、を使用してオブジェクトを投げることですdie。がeval終了し、$@(例外があったかどうかを確認するために)null文字列と比較しようとすると、比較は別の例外をスローし、outsideをエスケープしevalます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.