Erstellen Sie ein Programm mit einem einfachen GOTO


25

Der XKCD GOTO Comic

Ihre Aufgabe ist es, das größte Programm zu erstellen, das Sie können und das genau ein GOTO verwendet, ohne das das gesamte Programm (oder zumindest ein großer Teil davon) vollständig umstrukturiert werden muss. Die Punktzahl wird als die Anzahl der Anweisungen in Ihrem Code gezählt, die die Position ändern oder neu eingeführt werden (das Entfernen von Anweisungen trägt nicht zu Ihrer Punktzahl bei), wenn der Code ohne das GOTO umstrukturiert wird (andere dürfen Ihre Umstrukturierung anfechten, indem sie eine weitere Anweisung vorlegen elegantes). Da dies Code-Bowling ist, gewinnt die höchste Punktzahl.

Hinweis: Ich übernehme keine Haftung für Velociraptor-Angriffe, wenn ich diese Herausforderung versuche.


2
Der eine Goto scheint problematisch. Jeder C-Code, von dem ich denke, dass er ein einzelnes goto verwendet, kann trivial geändert werden, um strukturierte Konstrukte zu verwenden. Mehrere gotos jedoch ...
Pubby

@Pubbys Behauptung scheint gegen die aktuellen beiden Lösungen zu stimmen. Ersetzen gotodurch switchscheint für beide möglich.
Ugoren

@Pubby Wie viele Goto benötigen Sie, um eine funktionsfähige Lösung zu erstellen? Wenn das derzeit angegebene Problem nicht möglich ist, kann ich ein alternatives Problem erstellen.
Joe Z.

Ich denke, du darfst den Cartoon einbetten, solange es auch einen Link gibt.
Luser Droog

1
Es ist nicht qualifiziert, aber ich habe es wirklich getan .
Luser Droog

Antworten:


11

C Fizzbuzz

Diese Lösung basiert auf der Idee von Interrupts und Label-Variablen (nur gcc, sorry). Das Programm richtet einen Timer ein, der periodisch main aufruft, wo wir zu dem Punkt gelangen, den uns die letzte Ausführung unseres Interrupt-Handlers (main) befohlen hat.

Ich habe noch nie zuvor Timer oder Label-Variablen verwendet. Ich denke, hier gibt es viel zu tun.

#include <sys/time.h>
#include <signal.h>
#include <stdio.h>

int main(int argc)
{
    static int run = 1;
    static int* gotoloc = &&init;
    static int num = 0;
    static int limit = 50;

    goto *gotoloc;
init:
    signal(SIGVTALRM, (void (*)(int)) main);
    gotoloc = &&loop;

    struct itimerval it_val;

    it_val.it_value.tv_sec = 0;
    it_val.it_value.tv_usec = 100000;
    it_val.it_interval.tv_sec = 0;
    it_val.it_interval.tv_usec = 100000;
    setitimer(ITIMER_VIRTUAL, &it_val, NULL);

    while(run);

loop:
    num = num + 1;
    run = num < limit;
    gotoloc = &&notfizz + (&&fizz - &&notfizz) * !(num % 3);
    return 1;

fizz:
    printf("fizz");
    gotoloc = &&notbuzz + (&&buzz - &&notbuzz) * !(num % 5);
    return 1;

notfizz:
    gotoloc = &&notfizzbuzz + (&&buzz - &&notfizzbuzz) * !(num % 5);
    return 1;

buzz:
    printf("buzz\n");
    gotoloc = &&loop;
    return 1;

notbuzz:
    printf("\n");
    gotoloc = &&loop;
    return 1;

notfizzbuzz:
    printf("%d\n", num);
    gotoloc = &&loop;
    return 1;
}

runsollte deklariert werden volatile, ansonsten while(run)kann "optimiert" werden while(1). Oder gehen Sie einfach zu einem Ort, der Sie anruft exit.
Ugoren

@ugoren Guter Punkt. Ich habe Optimierungen (O1, O2 und Os) aktiviert und alle haben das Programm gebrochen. Leider haben gotoloc und num es nicht geschafft, 'volatile' vor dem Lauf hinzuzufügen. Es könnte sein, dass gcc nicht für die Optimierung dieser Art von Code entwickelt wurde.
Shiona

Das Definieren volatile int numaußerhalb von main sollte es tun. Mit static, glaubt gcc, dass es weiß, wer sich damit anlegen kann.
Ugoren

leider kann ich kein gotoloc außerhalb des main erstellen, oder ich könnte, aber ich müsste es außerhalb auf null setzen und dann erst am anfang des main zurücksetzen, wenn es null ist. Und der Appell ist zu verblassen. Ich denke, es ist am besten zu sagen, dass ich C schlecht benutze, gcc es zu Recht nicht richtig optimiert, also versuche es nicht.
Shiona

5

Perl

Ich kann nicht sehr gut bowlen, aber ich vermute, das könnte den OP interessieren. Dies ist ein Eratosthenes-Sieb mit einer Variablen goto. Wäre dies "refactored", würde ich bezweifeln, dass etwas davon wiederverwendbar wäre, abgesehen von vielleicht den ersten paar Zeilen. Wenn das Sieb endet, entsprechen alle verbleibenden 1s im @primesArray den Primwerten.

Für zusätzlichen Spaß werden keine ands, ors, ternaries, conditionals oder Vergleichsoperatoren jeglicher Art verwendet.

@primes[2..1e4]=(1)x9999;
$a=2;
Y:
  $b=$a*~-$a;
X:
  $primes[$b+=$a+=$c=$a/100%2+$b/1e4%2]=0;
  goto"$c"^h;
Z:

Im Falle von Unklarheiten darüber, warum ich dies hier poste, erklärte das OP in einer separaten Frage (die jetzt gestrichen wurde): "Dies war die Frage, die er eigentlich stellen wollte", war sich jedoch nicht sicher, ob dies möglich war .
Primo

Falls es irgendwelche Unklarheiten darüber gibt, welche Frage ich gestellt habe, handelte es sich um eine Frage, bei der Code nur mit GOTOs und nicht nur mit einer erstellt wurde.
Joe Z.

1
@ JoeZeng Ich hatte ursprünglich drei, aber ich habe es auf eins reduziert, damit es auch eine gültige Lösung für dieses Problem ist.
Primo

3

C

Meine Verwendung von Makros macht es vielleicht nicht zu einem "GOTO".
Und es ist ziemlich kurz, so dass "komplett umstrukturiert" nicht viel ist.
Aber hier ist trotzdem mein Versuch.

Liest eine Zahl von der Standardeingabe und druckt sie in Modul 3.

int main() {
    char s[100], *p, r=0;
    void *pl[] = { &&a, &&b, &&c, &&d, &&e, &&f, &&g, &&h, &&i, &&j, &&a, &&b, &&x, &&y, &&z }, *p1;
    p = gets(s);
    #define N(n) (pl+n)[!*p*60+*p-48];p++;goto *p1
    a: p1=N(0);
    b: p1=N(1);
    c: p1=N(2);
    d: p1=N(0);
    e: p1=N(1);
    f: p1=N(2);
    g: p1=N(0);
    h: p1=N(1);
    i: p1=N(2);
    j: p1=N(0);
    z: r++;
    y: r++;
    x: printf("%d\n", r);

    return 0;
}

1
Ja, solche Makros zu verwenden, ist nicht "one GOTO". Aber selbst dann müssten Sie die Umstrukturierung des Programms ohne Verwendung eines GOTO durchführen. Das Entfernen von Anweisungen erhöht Ihre Punktzahl nicht.
Joe Z.

Das Drucken einer Zahl Modulo 3 wäre einfach, wenn Sie nur ein printfund verwenden scanf. Die Punktzahl Ihrer Lösung würde höchstwahrscheinlich bei 2 oder 3 liegen.
Joe Z.

1
Gutes Argument. Ich kann mir nicht vorstellen, warum irgendjemand jemals etwas programmieren möchte , das so gedruckt n%3wird. Es sollte ein Programm sein, das sich beim Entfernen des GOTO verwickelt und nicht beim Einführen .
Joe Z.

2
"Warum?" ist für diese Seite irrelevant - sie steckt voller dummer Methoden, dumme Dinge zu tun. Wenn Sie entfernen goto, funktioniert das Programm nicht. Aber was haben Sie erwartet - dass das Programm allein durch das Entfernen verwickelt wird?
Ugoren

1
Durch die Beseitigung und anschließende Umstrukturierung ja. Ein einfaches Beispiel könnte die Verwendung von goto sein, um aus mehreren verschachtelten Schleifen auszubrechen.
Joe Z.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.