mencapai tangkapan ketika segala sesuatu di blok percobaan sudah tertangkap

19

Ini terbatas pada Java dan C # oleh sintaks yang saya kira.

Dalam teka-teki pemrograman ini, Anda harus membuat Exceptions yang dapat ditangkap tetapi dilempar lagi di ujung blok tangkap.

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
}

Anda dapat dengan bebas memasukkan kode sebelum dan sesudah cuplikan ini.

Kode terpendek untuk mencapai catchblok luar menang.

pengguna21634
sumber
1
Saya pikir Python mungkin juga bisa bersaing.
user12205
1
Anda dapat dengan bebas memasukkan kode sebelum dan sesudah cuplikan saya.
user21634
2
Sayang sekali sudah ditutup. Saya punya solusi . Untuk @algorithmshark, Michael dan Jan Dvorak: Ini BUKAN pertanyaan pemrograman umum. Ini adalah teka-teki pemrograman, mirip dengan Kapan jerapah bukan jerapah? . Saya menominasikan ini untuk dibuka kembali.
user12205
1
Uhhhhhh, Whaaat ???
TheDoctor
1
@algorithmshark Saya akan pergi dengan jumlah panjang penyisipan
user12205

Jawaban:

24

C #, 46 (88 termasuk boilerplate)

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

The Abort()Metode menimbulkan ThreadAbortException , yang merupakan pengecualian khusus yang secara otomatis rethrown pada akhir setiap blok catch (kecuali Thread.ResetAbort()disebut).

BenM
sumber
20

C # 24 Karakter

menghentikan blok coba bagian dalam sebelum yang dimaksudkan, memungkinkan saya untuk membuat pengecualian di luar blok try.

}finally{int a=1/0;}try{
rans
sumber
1
Man ini jenius! Kenapa aku tidak memikirkan itu? (Btw dapatkah Anda mempersingkat dengan benar-benar menyebabkan pengecualian alih-alih melempar pengecualian? Misalnya int a=1/0;?)
user12205
Apakah kamu perlu di int a=sana? Beberapa bahasa memungkinkan Anda menulis ekspresi1/0
gnibbler
Ini bukan contoh kerja yang lengkap, bukan? Jadi 24 karakter tidak masuk hitungan ...
Matt
13

Java, 76 atau 31

Hanya menghitung penyisipan yang dilakukan pada kode, mengabaikan baris baru. 76 jika Anda menghitung semua yang saya tambahkan, 31 jika Anda mengecualikan baris pertama dan baris terakhir, yaitu hanya menghitung 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){}
}}
pengguna12205
sumber
Ups, maaf, saya tidak memperhatikan bagaimana Anda menghitung. Saya akan memperbarui jawaban saya untuk menambahkan metode penghitungan lainnya. Saya rasa hanya menghitung karakter di blok try lebih baik, karena kalau tidak kita pada dasarnya akan membandingkan C # vs Java boilerplate. Tapi itu bisa menjadi rumit jika seseorang mengirimkan jawaban dengan kode penting di luar blok try (seperti yang diizinkan oleh aturan).
BenM
@ Ben, jangan khawatir, dan saya mengerti mengapa Anda menghitungnya seperti itu. Hanya saja OP tidak menentukan cara menghitung yang mana, jadi saya pikir saya akan memasukkan keduanya.
user12205
Solusi yang sangat pintar.
Nicolas Barbulesco
@NicolasBarbulesco Sejujurnya saya pikir jawaban oleh Ryan lebih pintar dari pada saya. Lagi pula, saya menambahkan satu catchblok setelah potongan, dia tidak.
user12205
3

Peringatan : Program-program ini adalah bom klon (semacam bom fork yang tidak berbahaya tapi masih berbahaya); dengan demikian, jangan menjalankannya pada sistem produksi tanpa sandboxing atau batasan sumber daya . Bom klon membuat utas dalam satu lingkaran (tidak seperti bom fork, yang menciptakan proses dalam satu lingkaran), sehingga Anda dapat menghentikannya hanya dengan membunuh proses yang dimaksud (membuatnya jauh lebih berbahaya daripada bom fork, yang bisa sangat sulit untuk membersihkan); tetapi mereka kemungkinan akan mengikat sebagian besar CPU Anda sampai Anda berhasil melakukannya (atau sampai program menang dan keluar secara alami dengan sendirinya). Meminta OS Anda untuk membatasi jumlah memori dan waktu CPU yang diizinkan untuk digunakan oleh program ini harus menciptakan lingkungan yang aman untuk mengujinya.

Java (OpenJDK 8) , 65 60 byte (dengan sedikit modifikasi pada pembungkus)

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

Cobalah online!

Membutuhkan kedua contoh catch (Exception …)dalam pertanyaan untuk diubah catch (Throwable …). Secara teori ini seharusnya lebih aman, tidak kurang, tetapi memungkinkan solusi ini dimungkinkan.

Saya menyimpan 5 byte dari versi pertama jawaban ini menggunakan referensi metode daripada lambda.

Java 4, 104 byte (belum diuji, harus bekerja dengan pembungkus asli)

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

Cobalah online! (tautan menuju implementasi Java 8, sehingga tidak akan berfungsi)

Menggunakan fitur yang telah dihapus dari versi Java modern, dimungkinkan untuk menyelesaikan bahkan versi puzzle yang membutuhkan Exception. Mungkin setidaknya. (Java 4 sudah sangat tua sekarang dan saya tidak ingat fitur mana yang ia lakukan dan tidak mengandung. Seperti dapat dilihat, ada banyak fitur yang lebih sedikit di Jawa saat itu dan karena itu lebih verbose; kami tidak memiliki lambdas, jadi saya harus membuat kelas batin.)

Penjelasan

Sebagian besar solusi untuk pertanyaan ini adalah dalam C # (bersama-sama dengan solusi Java yang menipu melalui menggunakan tanda kurung tidak seimbang sebagai bentuk injeksi kode, dan solusi Perl yang juga tidak di Jawa). Jadi saya pikir ada baiknya mencoba menunjukkan bagaimana teka-teki ini dapat diselesaikan dengan "benar" di Jawa juga.

Kedua program secara efektif identik (dengan demikian fakta bahwa program pertama berfungsi memberi saya kepercayaan tinggi bahwa program kedua juga akan berfungsi, kecuali saya secara tidak sengaja menggunakan fitur non-Java-4; Thread#stopsudah tidak digunakan lagi di Java 5).

Thread#stopMetode Java bekerja, di belakang layar, melalui menyebabkan lemparan untuk dilemparkan ke utas yang dimaksud. The throwable yang dimaksudkan untuk tujuan tersebut adalah ThreadDeath(an Error, khususnya karena orang sering mencoba untuk menyelimuti pengecualian dan desainer Java tidak ingin hal itu terjadi), meskipun hal itu memungkinkan Anda untuk melempar apa saja (atau dulu; di beberapa titik setelah API adalah dirancang, desainer Java menyadari bahwa ini adalah ide yang sangat buruk dan menghapus versi metode yang mengambil argumen langsung). Tentu saja, bahkan versi yang melempar ThreadDeathadalah operasi yang cukup berisiko di mana Anda dapat membuat beberapa jaminan (misalnya, memungkinkan Anda untuk memecahkan teka-teki ini, sesuatu yang "seharusnya" tidak mungkin), sehingga Anda tidak seharusnya gunakan itu, tetapi pada Java 8, masih berfungsi.

Program ini bekerja dengan menelurkan utas baru, dan memintanya untuk secara paksa melemparkan pengecualian kembali ke utas utama. Jika kita beruntung, itu akan melakukan itu pada suatu saat ketika kita berada di luar catchblok dalam (kita tidak dapat melarikan diri dari catchblok luar sampai program berakhir, karena ada lingkaran di sekitarnya). Karena kami telah menambahkan loop dengan mudah, menghemat byte untuk menggunakan loop itu agar kami dapat terus membuat utas, dengan harapan salah satu dari mereka pada akhirnya akan mencapai waktu yang tepat. Ini biasanya terjadi dalam beberapa detik.

(Catatan TIO: versi TIO saat ini cukup cenderung untuk mematikan program ini di awal pelaksanaannya, mungkin karena semua utas sedang dibuat. Ini dapat bekerja pada TIO, tetapi tidak bekerja dengan andal, sehingga seringkali beberapa upaya diperlukan untuk dapatkan hasil "Anda menang!".)

ais523
sumber
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
sumber
1
Selamat Datang di Programming Puzzles & Code Golf! Karena pertanyaan ini adalah tantangan kode-golf , coba buat kode Anda sesingkat mungkin dan sertakan jumlah karakter di bagian atas jawaban Anda. Terima kasih!
ProgramFOX
1

Perl 5 , 37 atau 36 byte

eval {
    while (1) {
        eval {

 

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

 

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

Cobalah online!

Ternyata pertanyaan ini diterjemahkan ke dalam Perl cukup baik untuk membuat teka-teki yang menarik di sana juga. trySetara Perl disebut (sedikit membingungkan) eval, dan menentukan pengecualian dengan menetapkan @_pengecualian jika itu terjadi, dan string nol sebaliknya. Dengan demikian, sebuah catchblok diimplementasikan melalui membandingkan @_ke string nol.

Solusi ini bekerja dengan membuat objek (yang kelasnya adalah program secara keseluruhan; Anda dapat menggunakan file Perl sewenang-wenang seperti kelas, semacam kebalikan dari Java (di mana Anda dapat menggunakan kelas sewenang-wenang seperti file)). Itulah bless[]bagian ( blessbiasanya hanya muncul jauh di dalam konstruktor, sebagai primitif yang membuat benda menjadi objek di tempat pertama, tetapi Anda dapat menggunakannya secara langsung jika Anda benar-benar ingin; []adalah pengalokasi memori untuk objek - konstruktor daftar, dalam hal ini case - dan kelas tidak diberikan sehingga dianggap sebagai yang sedang dieksekusi). Sementara itu, kami memberikan "class" kami (yaitu file utama) metode custom-to-string via use overload, dan membuat metode itu melempar pengecualian (sehingga keluar dari loop dan memecahkan teka-teki); kita benar-benar dapat menempatkanuse overloaddi mana saja, dan meskipun secara tradisional akan masuk dengan definisi metode lain dan mendekati bagian atas file, kita dapat memasukkannya ke dalam celah yang telah kita berikan sebagai gantinya dan masih berfungsi. (Jika kita meletakkannya di akhir file, kita bisa menghilangkan titik koma setelahnya, yang mengarah ke solusi 36-byte, tetapi ini bisa dibilang curang karena tergantung pada program yang memiliki tanda titik koma di tempat pertama, yaitu tidak dijamin.) Ini sebenarnya lebih pendek untuk membebani operasi stringify dan membiarkan Perl melakukan autogenerasi sebuah string dibandingkan dengan itu, daripada melakukan overload string secara langsung (karena overloading beberapa operator memaksa Anda untuk membebani operator lain juga).

Sekarang, yang harus kita lakukan adalah melempar objek kita menggunakan die. The evalberakhir, maka ketika kita mencoba untuk membandingkan $@dengan nol tali (untuk melihat apakah ada pengecualian), perbandingan melempar pengecualian lain dan kami melarikan diri di luar eval.


sumber