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
파이썬도 경쟁 할 수 있다고 생각합니다.
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을 발생 Thread.ResetAbort()시킵니다.이 예외 는 호출 되지 않은 경우 각 catch 블록의 끝에서 자동으로 다시 발생하는 특수 예외입니다 .


20

C # 24 자

의도 된 내부 try 블록을 종료하여 try 블록 외부에서 예외를 일으킬 수 있습니다.

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

1
이게 천재 야! 왜 그렇게 생각하지 않았습니까? (하지만 실제로 예외를 발생시키는 대신 예외를 발생 시켜서 단축시킬 수 있습니까? 예) int a=1/0;?
user12205

int a=거기에 필요 합니까? 일부 언어는 단지 표현 쓸 수1/0
gnibbler

이것은 완전한 실례가 아닙니다. 그렇지 않습니까? 그래서 24 문자는 계산하지 않습니다 ...
Matt

13

자바, 76 또는 31

줄 바꿈을 무시하고 코드에 대한 삽입 만 계산합니다. 76 내가 추가 한 모든 것을 세면 31, 첫 번째 줄과 마지막 줄을 제외하면 31, 즉 counting 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){}
}}

죄송합니다. 계산 방법에 신경 쓰지 않았습니다. 다른 계산 방법을 추가하기 위해 답변을 업데이트하겠습니다. try 블록의 문자 수를 계산하는 것이 좋습니다. 그렇지 않으면 기본적으로 C #과 Java 상용구를 비교하기 때문입니다. 그러나 누군가가 try 블록 외부에 중요한 코드로 답변을 제출하면 규칙이 허용하는 것처럼 복잡해질 수 있습니다.
BenM

@BenM 걱정하지 마세요. 왜 그런 식으로 계산했는지 이해합니다. OP가 계산 방법을 지정하지 않았기 때문에 두 가지를 모두 포함한다고 생각했습니다.
user12205

매우 영리한 솔루션.
Nicolas Barbulesco 13:30에

@NicolasBarbulesco 솔직히 말해서 Ryan의 대답은 나의 것보다 더 영리하다고 생각합니다. 결국, 나는 발췌 catch 블록 추가 했지만 그는하지 않았다.
user12205

3

경고 :이 프로그램은 클론 폭탄 (위험하지는 않지만 여전히 위험한 형태의 포크 폭탄)입니다. 따라서 샌드 박싱이나 리소스 제한없이 프로덕션 시스템에서 실행하지 마십시오 . 복제 폭탄은 루프에서 프로세스를 생성하는 포크 ​​폭탄과 달리 루프에서 스레드를 생성하므로 문제가있는 프로세스를 죽여서 간단히 중지 할 수 있습니다 (포크 폭탄보다 훨씬 덜 위험하게 만들 수 있음). 정리); 그러나 그렇게 할 때까지 (또는 프로그램이 자연스럽게 이기고 자연스럽게 나올 때까지) 대부분의 CPU를 묶을 것입니다. OS에 이러한 프로그램의 사용이 허용 된 메모리 및 CPU 시간에 제한을 두도록 요청하면 테스트 할 안전한 환경이 만들어집니다.

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-4가 아닌 기능을 사용하지 않으면 Thread#stopJava 5에서 더 이상 사용되지 않는 한 두 번째 프로그램도 작동한다는 확신을줍니다 .)

Java의 Thread#stop메소드는 문제의 스레드에 Throwable을 던져서 뒤에서 작동합니다. throw 가능 객체는 목적을위한 것입니다 ThreadDeath(AN Error, 사람들은 담요 - 캐치 예외로 시도하고 자바의 디자이너는 일어나고 싶지 않았어 특히 때문에) 당신이 아무것도 (또는 사용을 던질 수 있지만, 일부 지점에서 API가 된 후 자바 디자이너들은이 아이디어가 엄청나게 나쁜 아이디어라는 것을 깨달았고 인수를 바로 취하는 메소드 버전을 제거했습니다). 물론, 던지는 버전조차도 ThreadDeath상당히 위험한 작업으로 보증을 거의 할 수 없습니다 (예를 들어,이 퍼즐을 해결할 수 있습니다 ( "불가능")). 그것을 사용하지만 Java 8부터는 여전히 작동합니다.

이 프로그램은 새로운 스레드를 생성하고 강제로 예외를 메인 스레드에 다시 던지도록 요청함으로써 작동합니다. 운이 좋으면 내부 catch블록 외부에있는 시점에서 그렇게 할 것입니다 ( catch루프가 있기 때문에 프로그램이 끝날 때까지 외부 블록을 벗어날 수는 없습니다 ). 루프가 이미 편리하게 추가 되었기 때문에 단순히 루프를 사용하여 스레드를 계속 만들 수 있도록하는 것은 바이트 절약입니다. 스레드 중 하나가 올바른 타이밍에 도달하기를 바랍니다. 이것은 일반적으로 몇 초 안에 발생하는 것 같습니다.

(TIO 참고 : 현재 버전의 TIO는 생성 된 모든 스레드로 인해이 프로그램을 실행 초기에 강제 종료하는 경향이 있습니다. TIO에서 작동 할 수 있지만 안정적으로 작동하지 않으므로 몇 가지 시도가 필요합니다. "You won!"출력을 얻습니다.)


1

씨#

    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로 해석된다는 것이 밝혀졌습니다. 펄의 try등가물은 (약간 혼란스럽고) eval예외가 발생하면 예외로 설정 @_하고 그렇지 않으면 null 문자열을 지정하여 예외를 지정합니다 . 따라서 , 널 문자열 catch과 비교 @_하여 블록이 구현된다 .

이 솔루션은 객체를 생성함으로써 작동합니다 (클래스 전체가 프로그램입니다; 클래스와 같은 임의의 Perl 파일을 사용할 수 있습니다 (Java와 반대의 종류 (파일과 같은 임의의 클래스를 사용할 수있는 것과 같은))). 그 bless[]부분은 ( bless일반적으로 생성자 내부에만 깊게 나타납니다. 처음에는 객체를 물건으로 만드는 기본 요소이지만, 실제로 원한다면 직접 사용할 수 있습니다. []객체의 메모리 할당 자입니다. case – 클래스가 주어지지 않았으므로 현재 실행중인 것으로 가정합니다). 한편, 우리는 "class"(즉, 메인 파일)에을 통해 커스텀 비교 문자열 방식을 제공하고 use overload, 그 메소드가 예외를 던지도록합니다 (따라서 루프에서 빠져 나와 퍼즐 풀기). 우리는 실제로 넣을 수 있습니다use overload전통적으로 다른 메소드 정의와 함께 들어가고 파일의 상단에 가까워 지더라도 대신 주어진 간격에 넣을 수 있으며 여전히 작동합니다. (파일 끝에 파일을 넣으면 세미콜론을 생략하여 36 바이트 솔루션을 만들 수 있지만 처음에는 끝에 세미콜론이있는 프로그램에 따라 부정 행위가 될 수 있습니다. 실제로 stringify 작업에 과부하가 걸리고 Perl이 문자열 비교를 직접 오버로드하는 것보다 문자열 비교를 자동 생성하도록하는 것이 실제로 더 짧습니다 (일부 연산자에 과부하가 걸리면 다른 연산자에 과부하가 걸리기 때문입니다).

이제 우리가해야 할 일은를 사용하여 객체를 던지는 것 die입니다. eval우리가 비교 할 때 종료 후 $@널 문자열 비교는 또 다른 예외가 발생하고 우리는 외부를 탈출, (예외가 있다면 볼 수 있습니다) eval.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.