đạt được bắt khi mọi thứ trong khối thử đã bị bắt


19

Điều này được giới hạn ở Java và C # theo cú pháp tôi đoán.

Trong câu đố lập trình này, bạn phải tạo ra những Exceptions có thể bị bắt nhưng lại bị ném vào cuối khối bắt.

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
}

Bạn có thể tự do đặt mã trước và sau đoạn trích này.

Mã ngắn nhất để đạt được catchkhối bên ngoài chiến thắng.


1
Tôi nghĩ Python cũng có thể cạnh tranh.
dùng12205

1
Bạn có thể tự do đặt mã trước và sau đoạn trích của tôi.
user21634

2
Quá tệ, nó đã đóng cửa. Tôi đã có một giải pháp . Đối với @alerskymshark, Michael và Jan Dvorak: Đây KHÔNG phải là một câu hỏi lập trình chung. Nó là một câu đố lập trình, tương tự như Khi nào một con hươu cao cổ không phải là một con hươu cao cổ? . Tôi đang đề cử điều này để mở lại.
dùng12205

1
Uhhhhhh, ai vậy ???
TheDoctor

1
@alerskymshark Tôi sẽ đi với tổng độ dài của các lần chèn
user12205

Câu trả lời:


24

C #, 46 (88 bao gồm cả nồi hơi)

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

Các Abort()phương pháp làm nảy sinh một ThreadAbortException , mà là một ngoại lệ đặc biệt mà được tự động rethrown ở phần cuối của mỗi khối catch (trừ khi Thread.ResetAbort()được gọi).


20

Nhân vật C # 24

chấm dứt khối thử bên trong trước khi dự định, cho phép tôi gây ra ngoại lệ bên ngoài khối thử.

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

1
Người đàn ông này là thiên tài! Tại sao tôi không nghĩ về điều đó? (Btw bạn có thể rút ngắn nó bằng cách thực sự gây ra một ngoại lệ thay vì ném một ngoại lệ? Ví dụ int a=1/0;?)
user12205

Bạn có cần int a=ở đó không? Một số ngôn ngữ cho phép bạn chỉ cần viết biểu thức1/0
gnibbler

Đây không phải là một ví dụ làm việc hoàn chỉnh, phải không? Vì vậy, 24 ký tự không được tính ...
Matt

13

Java, 76 hoặc 31

Chỉ đếm các phần chèn vào mã, bỏ qua các dòng mới. 76 nếu bạn đếm mọi thứ tôi đã thêm, 31 nếu bạn loại trừ dòng đầu tiên và dòng cuối cùng, tức là chỉ tính 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){}
}}

Rất tiếc, xin lỗi, tôi đã không chú ý đến cách bạn đếm. Tôi sẽ cập nhật câu trả lời của tôi để thêm phương pháp đếm khác. Tôi nghĩ rằng chỉ cần đếm các ký tự trong khối thử là tốt hơn, vì nếu không, về cơ bản chúng ta sẽ so sánh bản tóm tắt C # với Java. Nhưng điều đó có thể trở nên phức tạp nếu ai đó gửi câu trả lời với mã quan trọng bên ngoài khối thử (theo quy định được cho phép).
BenM

@BenM Không phải lo lắng, và tôi hiểu lý do tại sao bạn tính nó theo cách đó. Chỉ là OP không chỉ định cách tính nào, vì vậy tôi đoán tôi sẽ bao gồm cả hai.
dùng12205

Giải pháp rất thông minh.
Nicolas Barbulesco

@NicolasBarbulesco Thành thật mà nói tôi nghĩ câu trả lời của Ryan thông minh hơn tôi. Rốt cuộc, tôi đã thêm một catchkhối sau đoạn trích, anh ấy đã không làm thế.
dùng12205

3

Cảnh báo : Các chương trình này là bom nhân bản (một dạng bom ít nguy hiểm nhưng vẫn nguy hiểm); như vậy, không chạy chúng trên một hệ thống sản xuất mà không có giới hạn tài nguyên hoặc hộp cát . Bom nhân bản tạo ra các luồng trong một vòng lặp (trái ngược với bom ngã ba, tạo ra các quy trình trong một vòng lặp), do đó bạn có thể ngăn chặn chúng đơn giản bằng cách giết quá trình trong câu hỏi (làm cho chúng ít nguy hiểm hơn bom ngã ba, rất khó để dọn sạch); nhưng họ có thể sẽ buộc hầu hết CPU của bạn cho đến khi bạn quản lý để làm như vậy (hoặc cho đến khi chương trình chiến thắng và tự nhiên thoát ra). Yêu cầu HĐH của bạn đặt giới hạn về dung lượng bộ nhớ và thời gian CPU mà các chương trình này được phép sử dụng sẽ tạo ra một môi trường an toàn để kiểm tra chúng.

Java (OpenJDK 8) , 65 60 byte (với một sửa đổi nhỏ cho trình bao bọc)

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

Hãy thử trực tuyến!

Yêu cầu cả hai trường hợp catch (Exception …)trong câu hỏi được thay đổi thành catch (Throwable …). Về lý thuyết, điều này sẽ an toàn hơn , không ít hơn, nhưng nó cho phép giải pháp này khả thi.

Tôi đã lưu 5 byte qua phiên bản đầu tiên của câu trả lời này bằng cách sử dụng tham chiếu phương thức thay vì lambda.

Java 4, 104 byte (chưa được kiểm tra, sẽ hoạt động với trình bao bọc gốc)

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

Hãy thử trực tuyến! (liên kết đến bản triển khai Java 8, do đó sẽ không hoạt động)

Sử dụng các tính năng đã bị xóa khỏi các phiên bản Java hiện đại, có thể giải quyết ngay cả phiên bản câu đố cần có Exception. Có lẽ, ít nhất. (Hiện tại Java 4 đã rất cũ và tôi không thể nhớ những tính năng nào nó đã làm và không chứa. Như có thể thấy, có rất nhiều tính năng trong Java hồi đó và do đó nó dài dòng hơn; chúng tôi không có lambdas, vì vậy tôi phải tạo ra một lớp bên trong.)

Giải thích

Hầu hết các giải pháp cho câu hỏi này là trong C # (cùng với giải pháp Java gian lận thông qua việc sử dụng dấu ngoặc không cân bằng làm hình thức tiêm mã và giải pháp Perl không có trong Java). Vì vậy, tôi nghĩ rằng sẽ rất đáng để thử chỉ ra cách giải câu đố này "đúng" trong Java.

Cả hai chương trình đều giống hệt nhau một cách hiệu quả (do đó, thực tế là chương trình đầu tiên hoạt động mang lại cho tôi sự tin tưởng cao rằng chương trình thứ hai cũng hoạt động, trừ khi tôi vô tình sử dụng một tính năng không phải là Java-4; Thread#stopkhông được dùng trong Java 5).

Thread#stopPhương thức của Java hoạt động, đằng sau hậu trường, thông qua việc khiến cho một cú ném có thể bị ném vào luồng đang nghi vấn. Mục đích có thể ném được nhằm mục đích là ThreadDeath(một Error, cụ thể là vì mọi người thường cố gắng bắt ngoại lệ và các nhà thiết kế của Java không muốn điều đó xảy ra), mặc dù nó cho phép bạn ném bất cứ thứ gì (hoặc đã từng sử dụng; vào một lúc nào đó sau API được thiết kế, các nhà thiết kế của Java nhận ra rằng đây là một ý tưởng cực kỳ tồi tệ và đã loại bỏ phiên bản của phương thức đưa các đối số hoàn toàn). Tất nhiên, ngay cả phiên bản ném ThreadDeathlà một hoạt động khá rủi ro mà bạn có thể đảm bảo một vài điều (ví dụ, nó cho phép bạn giải câu đố này, một điều "không nên" có thể), vì vậy bạn không được phép sử dụng nó, nhưng kể từ Java 8, nó vẫn hoạt động.

Chương trình này hoạt động bằng cách sinh ra một luồng mới và yêu cầu nó buộc phải ném ngoại lệ trở lại luồng chính. Nếu chúng ta may mắn, nó sẽ làm điều đó vào một thời điểm khi chúng ta ở bên ngoài catchkhối bên trong (chúng ta không thể thoát khỏi catchkhối bên ngoài cho đến khi chương trình kết thúc, bởi vì có một vòng lặp xung quanh nó). Vì chúng ta đã thêm vòng lặp một cách thuận tiện, nên tiết kiệm byte chỉ đơn giản là sử dụng vòng lặp đó để cho phép chúng ta tiếp tục tạo chủ đề, với hy vọng rằng một trong số chúng cuối cùng sẽ đạt được thời gian chính xác. Điều này thường xảy ra trong vài giây.

(Lưu ý về TIO: phiên bản hiện tại của TIO khá có xu hướng giết chương trình này sớm khi thực hiện, có lẽ là do tất cả các luồng được tạo. Nó có thể hoạt động trên TIO, nhưng không hoạt động đáng tin cậy, do đó thường cần một vài lần thử nhận đầu ra "Bạn đã thắng!".)


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
Chào mừng bạn đến với Câu đố lập trình & Code Golf! Vì câu hỏi này là một thử thách chơi gôn mã , vui lòng cố gắng làm cho mã của bạn càng ngắn càng tốt và bao gồm số ký tự ở đầu câu trả lời của bạn. Cảm ơn!
Chương trìnhFOX

1

Perl 5 , 37 hoặc 36 byte

eval {
    while (1) {
        eval {

 

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

 

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

Hãy thử trực tuyến!

Hóa ra câu hỏi này chuyển thành Perl đủ tốt để tạo ra một câu đố thú vị ở đó. tryTương đương của Perl được gọi (một chút khó hiểu) evalvà chỉ định một ngoại lệ bằng cách đặt @_thành một ngoại lệ nếu nó xảy ra và chuỗi null khác. Như vậy, một catchkhối được thực hiện thông qua so sánh @_với chuỗi null.

Giải pháp này hoạt động bằng cách tạo một đối tượng (có toàn bộ lớp là chương trình; bạn có thể sử dụng các tệp Perl tùy ý như các lớp, giống như đảo ngược của Java (nơi bạn có thể sử dụng các lớp tùy ý như các tệp)). Đó là bless[]phần ( blessthường chỉ xuất hiện sâu bên trong các hàm tạo, như là phần nguyên thủy biến mọi thứ thành các đối tượng ở vị trí đầu tiên, nhưng bạn có thể sử dụng nó trực tiếp nếu bạn thực sự muốn; []là cấp phát bộ nhớ cho đối tượng - một hàm tạo danh sách, trong phần này trường hợp - và lớp không được đưa ra nên nó được coi là lớp hiện đang thực thi). Trong khi đó, chúng tôi cung cấp cho "lớp" (tức là tệp chính) một phương thức so sánh chuỗi tùy chỉnh thông qua use overloadvà làm cho phương thức đó đưa ra một ngoại lệ (do đó thoát ra khỏi vòng lặp và giải câu đố); chúng ta thực sự có thể đặtuse overloadở bất cứ đâu, và mặc dù theo truyền thống sẽ đi vào với các định nghĩa phương thức khác và gần đầu tệp, chúng ta có thể đặt nó vào khoảng trống mà chúng ta đã đưa ra thay vào đó và nó vẫn hoạt động. (Nếu chúng ta đặt nó ở cuối tệp, chúng ta có thể bỏ qua dấu chấm phẩy sau nó, dẫn đến một giải pháp 36 byte, nhưng điều này được cho là gian lận vì nó phụ thuộc vào chương trình có dấu chấm phẩy ở vị trí đầu tiên, đó là không được bảo đảm.) Thực sự ngắn hơn khi quá tải hoạt động xâu chuỗi và để Perl tự động tạo một chuỗi so sánh từ đó, so với việc quá tải chuỗi so sánh trực tiếp (vì quá tải một số toán tử cũng buộc bạn phải quá tải các toán tử khác).

Bây giờ, tất cả những gì chúng ta phải làm là ném đối tượng của chúng ta bằng cách sử dụng die. Các evalchấm dứt, sau đó khi chúng ta cố gắng so sánh $@với chuỗi null (để xem có ngoại lệ nào không), phép so sánh sẽ ném một ngoại lệ khác và chúng ta thoát ra bên ngoài eval.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.