raggiungere catch quando tutto nel blocco try è già stato catturato


19

Ciò è limitato a Java e C # dalla sintassi che immagino.

In questo rompicapo di programmazione, dovrai produrre messaggi Exceptionche possono essere catturati ma che vengono nuovamente lanciati alla fine del blocco di cattura.

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
}

Puoi inserire liberamente il codice prima e dopo questo frammento.

catchVince il codice più corto per raggiungere il blocco esterno .


1
Penso che Python possa anche essere in grado di competere.
user12205,

1
Puoi inserire liberamente il codice prima e dopo il mio frammento.
user21634,

2
Peccato che sia chiuso. Ho una soluzione . A @algorithmshark, Michael e Jan Dvorak: questa NON è una domanda di programmazione generale. È un puzzle di programmazione, simile a Quando una giraffa non è una giraffa? . Lo sto nominando per la riapertura.
user12205,

1
Uhhhhhh, Whaaat ???
TheDoctor,

1
@algorithmshark Vorrei andare con la somma delle lunghezze degli inserimenti
user12205

Risposte:


24

C #, 46 (88 incluso 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#
        }
}}

Il Abort()metodo genera una ThreadAbortException , che è un'eccezione speciale che viene automaticamente riproposta alla fine di ciascun blocco catch (a meno che non Thread.ResetAbort()venga chiamato).


20

Personaggi C # 24

termina il blocco try interno prima previsto, permettendomi di causare un'eccezione al di fuori del blocco try.

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

1
Amico, questo è geniale! Perché non ci ho pensato? (A proposito, puoi accorciarlo causando effettivamente un'eccezione invece di lanciare un'eccezione? Ad esempio int a=1/0;?)
user12205

Ti serve int a=lì? Alcune lingue ti permettono di scrivere semplicemente l'espressione1/0
gnibbler

Questo non è un esempio di lavoro completo, vero? Quindi i 24 personaggi non contano ...
Matt,

13

Java, 76 o 31

Contando solo gli inserimenti apportati al codice, ignorando le nuove righe. 76 se conti tutto ciò che ho aggiunto, 31 se escludi la prima riga e l'ultima riga, vale a dire solo il conteggio 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){}
}}

Oops, scusa, non ho prestato attenzione a come hai contato. Aggiornerò la mia risposta per aggiungere l'altro metodo di conteggio. Suppongo che il solo conteggio dei caratteri nel blocco try sia migliore, dal momento che altrimenti staremmo sostanzialmente confrontando C # vs Java plate. Ma ciò potrebbe complicarsi se qualcuno invia una risposta con un codice importante al di fuori del blocco try (come consentito dalle regole).
BenM,

@BenM Nessun problema, e capisco perché l'hai contato in quel modo. È solo che l'OP non ha specificato in che modo contare, quindi ho pensato di includere entrambi.
user12205,

Soluzione molto intelligente.
Nicolas Barbulesco,

@NicolasBarbulesco Ad essere sincero, penso che la risposta di Ryan sia più intelligente della mia. Dopo tutto, ho aggiunto un catchblocco dopo lo snippet, non l'ha fatto.
user12205

3

Avvertenza : questi programmi sono bombe a clone (una sorta di bomba a forcella meno pericolosa ma ancora pericolosa); come tale, non eseguirli su un sistema di produzione senza sandbox o limiti di risorse . Le bombe clonate creano fili in un ciclo (al contrario delle bombe a forcella, che creano processi in un ciclo), quindi puoi fermarli semplicemente uccidendo il processo in questione (rendendoli molto meno pericolosi delle bombe a forcella, che può essere molto difficile da mettere in ordine); ma probabilmente collegheranno la maggior parte della tua CPU fino a quando non riuscirai a farlo (o fino a quando il programma vincerà e uscirà naturalmente da solo). Chiedere al sistema operativo di porre limiti alla quantità di memoria e al tempo di CPU che questi programmi sono autorizzati a utilizzare dovrebbe creare un ambiente sicuro in cui testarli.

Java (OpenJDK 8) , 65 60 byte (con una leggera modifica al wrapper)

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

Provalo online!

Richiede la modifica di entrambe le istanze di catch (Exception …)nella domanda catch (Throwable …). Questo dovrebbe in teoria essere più sicuro, non meno, ma consente a questa soluzione di essere possibile.

Ho salvato 5 byte sulla prima versione di questa risposta usando un riferimento al metodo anziché un lambda.

Java 4, 104 byte (non testato, dovrebbe funzionare con il wrapper originale)

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

Provalo online! (il collegamento va a un'implementazione Java 8, quindi non funzionerà)

Utilizzando le funzionalità che sono state rimosse dalle versioni moderne di Java, è possibile risolvere anche la versione del puzzle che richiede un Exception. Probabilmente, almeno. (Java 4 è ormai molto vecchio e non riesco a ricordare quali funzioni avesse e non contenesse. Come si può vedere, allora c'erano molte meno funzioni in Java ed era quindi più prolisso; non avevamo lambdas, quindi ho dovuto creare una classe interiore.)

spiegazioni

La maggior parte delle soluzioni a questa domanda sono in C # (insieme a una soluzione Java che imbroglia usando le parentesi sbilanciate come una forma di iniezione di codice e una soluzione Perl che non è anche in Java). Quindi ho pensato che valesse la pena provare a mostrare come questo puzzle possa essere risolto "correttamente" anche in Java.

Entrambi i programmi sono effettivamente identici (quindi il fatto che il primo programma funzioni mi dà la sicurezza che anche il secondo programma funzionerebbe, a meno che non abbia accidentalmente usato una funzione non Java-4; è Thread#stopstato deprecato in Java 5).

Il Thread#stopmetodo Java funziona, dietro le quinte, tramite il lancio di un lancio nel thread in questione. Il lancio previsto per lo scopo è ThreadDeath(un Error, in particolare perché le persone spesso cercano di catturare eccezioni e i progettisti di Java non volevano che ciò accadesse), anche se ti consente di lanciare qualsiasi cosa (o l'abitudine a; a un certo punto dopo che l'API era progettato, i progettisti di Java hanno capito che si trattava di una pessima idea e hanno rimosso la versione del metodo che prende apertamente gli argomenti). Naturalmente, anche la versione che genera ThreadDeathè un'operazione abbastanza rischiosa di cui puoi fare poche garanzie (ad esempio, ti consente di risolvere questo puzzle, qualcosa che "non dovrebbe" essere possibile), quindi non dovresti usalo, ma a partire da Java 8, funziona ancora.

Questo programma funziona generando un nuovo thread e chiedendogli di restituire forzatamente un'eccezione nel thread principale. Se siamo fortunati, lo farà in un momento in cui siamo fuori dal catchblocco interno (non possiamo sfuggire al catchblocco esterno fino a quando il programma non termina, perché c'è un ciclo attorno ad esso). Poiché abbiamo già aggiunto il loop convenientemente, è un risparmio di byte utilizzare semplicemente quel loop per consentirci di continuare a creare thread, nella speranza che uno di essi alla fine raggiunga il tempismo corretto. Questo sembra accadere normalmente entro un paio di secondi.

(Nota TIO: l'attuale versione di TIO è abbastanza incline a uccidere questo programma all'inizio della sua esecuzione, presumibilmente a causa della creazione di tutti i thread. Può funzionare su TIO, ma non funziona in modo affidabile, quindi spesso sono necessari alcuni tentativi per ottieni l'output "Hai vinto!".)


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
Benvenuto in Programmazione di puzzle e codice golf! Poiché questa domanda è una sfida di golf del codice , prova a rendere il tuo codice il più breve possibile e includi il conteggio dei caratteri nella parte superiore della risposta. Grazie!
Programma FOX

1

Perl 5 , 37 o 36 byte

eval {
    while (1) {
        eval {

 

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

 

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

Provalo online!

Si scopre che questa domanda si traduce in Perl abbastanza bene da creare anche un puzzle interessante lì. L' tryequivalente di Perl viene chiamato (un po 'confusamente) evale specifica un'eccezione impostando @_un'eccezione se si è verificata, altrimenti la stringa nulla. Come tale, un catchblocco viene implementato confrontandolo @_con la stringa nulla.

Questa soluzione funziona creando un oggetto (la cui classe è il programma nel suo insieme; è possibile utilizzare file Perl arbitrari come le classi, un po 'come il contrario di Java (dove è possibile utilizzare classi arbitrarie come i file)). Questa è la bless[]parte (bless normalmente appare in profondità solo all'interno dei costruttori, come la primitiva che trasforma le cose in oggetti in primo luogo, ma puoi usarle direttamente se vuoi davvero;[] è l'allocatore di memoria per l'oggetto - un costruttore di elenchi, in questo case - e la classe non viene data, quindi si presume che sia quella attualmente in esecuzione). Nel frattempo, diamo alla nostra "classe" (cioè il file principale) un metodo di confronto-stringa personalizzato tramite use overload, e facciamo in modo che tale metodo generi un'eccezione (uscendo dal ciclo e risolvendo il puzzle); possiamo effettivamente mettere iluse overloadovunque, e sebbene tradizionalmente andrebbe d'accordo con le altre definizioni di metodo e si avvicinasse alla cima del file, possiamo metterlo nello spazio che ci è stato dato invece e funziona ancora. (Se lo mettiamo alla fine del file, potremmo omettere il punto e virgola dopo di esso, portando a una soluzione a 36 byte, ma questo è probabilmente un imbroglio in quanto dipende dal programma che ha un punto e virgola finale in primo luogo, che è non garantito.) In realtà è più breve sovraccaricare l'operazione di stringify e lasciare che Perl generi automaticamente un confronto di stringhe da quello, che sarebbe sovraccaricare il confronto di stringhe direttamente (perché sovraccaricare alcuni operatori ti costringe a sovraccaricare anche altri operatori).

Ora, tutto ciò che dobbiamo fare è lanciare il nostro oggetto usando die. Il evalcomando termina, quindi quando proviamo a confrontare $@la stringa nulla (per vedere se c'era un'eccezione), il confronto genera un'altra eccezione e fuggiamo dall'esterno eval.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.