ถึงตัวจับเมื่อทุกอย่างในบล็อคการลองถูกจับไปแล้ว


19

สิ่งนี้ จำกัด เฉพาะ Java และ C # ด้วยไวยากรณ์ที่ฉันเดา

ในปริศนาการเขียนโปรแกรมนี้คุณจะต้องสร้างExceptions ที่สามารถถูกจับได้ แต่จะถูกโยนอีกครั้งในตอนท้ายของบล็อกการจับ

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
Uhhhhhh, Whaaat ???
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ซึ่งเป็นข้อยกเว้นพิเศษที่ rethrown โดยอัตโนมัติในตอนท้ายของแต่ละบล็อกจับ (ยกเว้นกรณีที่Thread.ResetAbort()เรียกว่า)


20

อักขระC # 24

ยุติการลองบล็อกภายในก่อนที่จะอนุญาตให้ฉันทำให้เกิดข้อยกเว้นนอกบล็อกการลอง

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

1
ผู้ชายคนนี้เป็นอัจฉริยะ! ทำไมฉันไม่คิดอย่างนั้นล่ะ (Btw คุณสามารถย่อให้สั้นลงโดยทำให้เกิดข้อยกเว้นแทนการโยนข้อยกเว้นหรือไม่เช่นint a=1/0;?)
12205

คุณต้องการที่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 สำเร็จรูป แต่นั่นอาจซับซ้อนหากมีคนส่งคำตอบด้วยรหัสที่สำคัญนอกบล็อคลอง (ตามที่กฎอนุญาต)
BenM

@BenM ไม่ต้องกังวลและฉันเข้าใจว่าทำไมคุณนับมันเป็นอย่างนั้น เป็นเพียงว่า OP ไม่ได้ระบุวิธีการนับดังนั้นฉันจึงคิดว่าจะรวมทั้งสองอย่าง
user12205

ทางออกที่ฉลาดมาก
Nicolas Barbulesco

@ NicolasBarbulesco พูดตามตรงฉันคิดว่าคำตอบของ Ryan นั้นฉลาดกว่าของฉัน หลังจากทั้งหมดฉันเพิ่มcatchบล็อกหลังจากตัวอย่างเขาไม่ได้
user12205

3

คำเตือน : โปรแกรมเหล่านี้เป็นระเบิดโคลน (รูปแบบของการทิ้งระเบิดแบบอันตรายน้อย แต่ยังคงอันตราย); เป็นเช่นนี้ไม่ได้ทำงานกับพวกเขาในระบบการผลิตโดยไม่ต้อง Sandboxing หรือข้อ จำกัด ของทรัพยากร Clone bombs สร้างเธรดในลูป (ตรงข้ามกับ fork bombs, ซึ่งสร้างโพรเซสในลูป), ดังนั้นคุณสามารถหยุดพวกมันได้ง่ายๆโดยการฆ่าโพรเซสที่มีปัญหา (ทำให้พวกมันอันตรายน้อยกว่า fork fork) กำจัด); แต่พวกเขาจะผูก CPU ส่วนใหญ่ของคุณจนกว่าคุณจะจัดการทำเช่นนั้น (หรือจนกว่าโปรแกรมจะชนะและออกตามธรรมชาติด้วยตัวเอง) การขอให้ระบบปฏิบัติการของคุณ จำกัด จำนวนหน่วยความจำและเวลา CPU ที่โปรแกรมเหล่านี้อนุญาตให้ใช้ควรสร้างสภาพแวดล้อมที่ปลอดภัยสำหรับการทดสอบ

Java (OpenJDK 8) , 65 60 ไบต์ (โดยมีการดัดแปลงเล็กน้อยกับ wrapper)

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

ลองออนไลน์!

ต้องใช้ทั้งกรณีของในคำถามที่จะเปลี่ยนไปcatch (Exception …) catch (Throwable …)ในทางทฤษฎีแล้วควรมีความปลอดภัยมากขึ้นไม่น้อยไปกว่านี้ แต่จะช่วยให้การแก้ปัญหานี้เป็นไปได้

ฉันบันทึก 5 ไบต์ในเวอร์ชันแรกของคำตอบนี้โดยใช้การอ้างอิงเมธอดมากกว่าแลมบ์ดา

Java 4, 104 ไบต์ (ไม่ได้ทดสอบควรทำงานกับ wrapper ต้นฉบับ)

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

ลองออนไลน์! (ลิงก์ไปที่การนำไปใช้ของ Java 8 ดังนั้นจะไม่ทำงาน)

การใช้คุณสมบัติที่ได้ถูกลบออกจากรุ่นที่ทันสมัยของ Java Exceptionก็เป็นไปได้ในการแก้แม้กระทั่งรุ่นของปริศนาที่ต้องใช้นั้น น่าจะเป็นอย่างน้อย (ตอนนี้ Java 4 นั้นเก่ามากและฉันจำไม่ได้ว่าฟีเจอร์ใดที่มันทำและไม่มีในขณะที่สามารถเห็นได้ว่ามีฟีเจอร์ใน Java จำนวนน้อยกว่ามากในตอนนั้น lambdas ดังนั้นฉันต้องสร้างชั้นใน)

คำอธิบาย

โซลูชันส่วนใหญ่สำหรับคำถามนี้อยู่ใน C # (ร่วมกับโซลูชัน Java ที่โกงผ่านการใช้วงเล็บเหลี่ยมที่ไม่สมดุลเป็นรูปแบบการฉีดโค้ดและโซลูชัน Perl ซึ่งไม่ได้อยู่ใน Java ด้วย) ดังนั้นฉันคิดว่ามันจะคุ้มค่าที่จะลองดูว่าปริศนานี้สามารถแก้ไขได้ "ถูกต้อง" ใน Java เช่นกัน

โปรแกรมทั้งสองเหมือนกันอย่างมีประสิทธิภาพ (ดังนั้นความจริงที่ว่าโปรแกรมแรกทำงานให้ฉันมั่นใจสูงว่าโปรแกรมที่สองจะทำงานเกินไปเว้นแต่ฉันจะใช้คุณสมบัติที่ไม่ใช่ Java-4 โดยไม่ตั้งใจThread#stopถูกเลิกใช้ใน Java 5)

ของ Java Thread#stopวิธีการใช้งานได้เบื้องหลังโดยทำให้โยนเข้าไปในกระทู้ที่มีปัญหาได้ การโยนได้เพื่อจุดประสงค์คือThreadDeath( Errorโดยเฉพาะเนื่องจากคนมักจะพยายามยกเว้นข้อผิดพลาดและนักออกแบบของ Java ไม่ต้องการให้เกิดขึ้น) แม้ว่ามันจะช่วยให้คุณสามารถโยนอะไรก็ได้ (หรือคุ้นเคยกับบางจุดหลังจาก API เป็น ออกแบบโดยนักออกแบบของจาวาตระหนักว่านี่เป็นความคิดที่ไม่ดีอย่างไม่น่าเชื่อและลบวิธีการในการโต้แย้งออกทันที แน่นอนว่าแม้กระทั่งเวอร์ชั่นที่ThreadDeathมีการดำเนินการที่ค่อนข้างเสี่ยงซึ่งคุณสามารถรับประกันได้เล็กน้อย (ตัวอย่างเช่นมันช่วยให้คุณสามารถไขปริศนานี้ได้ซึ่งเป็นสิ่งที่ "ไม่ควร" เป็นไปได้) ดังนั้นคุณจึงไม่ควร ใช้มัน แต่ใน Java 8 มันยังใช้งานได้

โปรแกรมนี้ทำงานโดยการวางไข่เธรดใหม่และขอให้บังคับให้โยนข้อยกเว้นกลับเข้าไปในเธรดหลัก หากเราโชคดีมันจะทำอย่างนั้นในช่วงเวลาที่เราอยู่นอกcatchบล็อกด้านใน(เราไม่สามารถหลบหนีcatchบล็อกด้านนอกได้จนกว่าโปรแกรมจะจบลงเพราะมีลูปอยู่รอบ ๆ ) เนื่องจากเราได้เพิ่มการวนซ้ำอย่างสะดวกแล้วจึงเป็นการประหยัดแบบไบต์โดยใช้การวนซ้ำนั้นเพื่อให้เราสามารถสร้างเธรดได้โดยหวังว่าหนึ่งในนั้นจะเข้าจังหวะที่ถูกต้องในที่สุด โดยปกติดูเหมือนว่าจะเกิดขึ้นภายในไม่กี่วินาที

(หมายเหตุ TIO: เวอร์ชันปัจจุบันของ TIO ค่อนข้างมีแนวโน้มที่จะฆ่าโปรแกรมนี้ในช่วงต้นของการดำเนินการสันนิษฐานว่าเป็นเพราะกระทู้ทั้งหมดที่ถูกสร้างขึ้นมันสามารถทำงานกับ TIO แต่ไม่ได้ทำงานได้อย่างน่าเชื่อถือดังนั้นมักจะต้องพยายามสองสามครั้ง รับผลลัพธ์ "คุณชนะ!")


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
ยินดีต้อนรับสู่ Programming Puzzles & Code Golf! เนื่องจากคำถามนี้เป็นความท้าทายของรหัสกอล์ฟโปรดพยายามทำให้รหัสของคุณสั้นที่สุดเท่าที่จะเป็นไปได้และรวมจำนวนอักขระที่ด้านบนสุดของคำตอบของคุณ ขอบคุณ!
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และระบุข้อยกเว้นโดยการตั้งค่า@_ข้อยกเว้นถ้ามันเกิดขึ้นและสตริงเป็นอย่างอื่น เป็นเช่นนี้catchการใช้งานบล็อกผ่านการเปรียบเทียบ@_กับสตริง null

โซลูชันนี้ทำงานโดยการสร้างวัตถุ (ซึ่งคลาสเป็นโปรแกรมโดยรวมคุณสามารถใช้ไฟล์ Perl โดยพลการเช่นคลาสเรียงลำดับเหมือนย้อนกลับของ Java (ซึ่งคุณสามารถใช้คลาสตามอำเภอใจเช่นไฟล์)) นั่นเป็นbless[]ส่วนหนึ่ง ( blessโดยปกติแล้วจะปรากฏในส่วนลึกของคอนสตรัคเตอร์เป็นแบบดั้งเดิมที่ทำให้สิ่งต่าง ๆ เป็นวัตถุในตอนแรก แต่คุณสามารถใช้งานได้โดยตรงถ้าคุณต้องการจริงๆ[]คือตัวจัดสรรหน่วยความจำสำหรับวัตถุ - ตัวสร้างรายการในนี้ กรณี - และไม่ได้รับคลาสดังนั้นจึงถือว่าเป็นหนึ่งในปัจจุบันดำเนินการหนึ่ง) ในขณะเดียวกันเราให้ "class" ของเรา (เช่นไฟล์หลัก) วิธีการเปรียบเทียบกับสตริงแบบกำหนดเองผ่านuse overloadและทำให้วิธีการนั้นมีข้อยกเว้น (ซึ่งทำให้หลุดออกจากวงและแก้ปริศนา); เราสามารถใส่use overloadที่ใดก็ตามและถึงแม้ว่ามันจะมีการนิยามตามวิธีการแบบดั้งเดิมและใกล้ด้านบนสุดของไฟล์ แต่เราสามารถใส่ลงในช่องว่างที่เราได้รับแทนและยังใช้งานได้ (หากเราวางไว้ที่ท้ายไฟล์เราสามารถตัดเครื่องหมายอัฒภาคออกหลังจากนั้นนำไปสู่โซลูชันขนาด 36 ไบต์ แต่นี่เป็นการโกงเนื้อหาเนื่องจากขึ้นอยู่กับโปรแกรมที่มีเครื่องหมายอัฒภาคต่อท้ายในตอนแรกซึ่งก็คือ ไม่รับประกัน) จริง ๆ แล้วมันสั้นกว่าที่จะโอเวอร์โหลดการดำเนินการ stringify และอนุญาตให้ Perl สร้างสตริงโดยอัตโนมัติเปรียบเทียบกับสิ่งนั้นมากกว่าที่จะเป็นการโอเวอร์โหลดสตริงเปรียบเทียบโดยตรง (เพราะการบรรทุกเกินจำนวนผู้ให้บริการบางราย

dieตอนนี้สิ่งที่เราต้องทำคือการโยนวัตถุของเราโดยใช้ evalสิ้นสุดลงแล้วเมื่อเราพยายามที่จะเปรียบเทียบ$@เพื่อสตริง (เพื่อดูว่ามีข้อยกเว้น) evalเปรียบเทียบพ่นยกเว้นอีกและเราหนีออกไปข้างนอก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.