하나의 간단한 GOTO로 프로그램 구축


25

XKCD GOTO 만화

당신의 임무는 정확히 하나의 GOTO를 사용하여 가능한 한 가장 큰 프로그램을 만드는 것입니다. 점수는 코드가 GOTO없이 재구성 될 때 장소변경 하거나 새로 도입 된 (설명을 제거해도 점수에 추가되지 않는) 코드의 문장 수로 계산됩니다 (다른 사람들은 더 많은 것을 제시함으로써 구조 조정에 도전 할 수 있음) 우아한 하나). 이것이 코드 볼링이므로 최고 점수가 이깁니다.

참고 :이 도전을 시도하여 벨로시 랩터 공격에 대한 책임을 주장하지 않습니다.


2
하나의 고토는 문제가 보인다. 내가 생각할 수있는 모든 C 코드는 단일 goto를 사용하여 구조적 구조를 사용하도록 간단하게 변경할 수 있습니다. 그러나 여러 고
토스

@Pubby의 주장은 현재 두 가지 솔루션에 반대되는 것으로 보입니다. 두 가지 모두 교체 gotoswitch가능해 보입니다.
ugoren

@Pubby 실행 가능한 솔루션을 만들려면 몇 개의 goto가 필요합니까? 현재 언급 된 문제가 불가능한 경우 다른 문제를 만들 수 있습니다.
Joe Z.

링크가있는 한 만화를 포함시킬 수 있다고 생각합니다.
luser droog

답변:


11

C 피즈 버즈

이 솔루션은 인터럽트 및 레이블 변수에 대한 아이디어를 바탕으로 실행됩니다 (gcc 만 해당, 죄송합니다). 이 프로그램은 주기적으로 main을 호출하는 타이머를 설정합니다. 인터럽트 처리기 (main)의 마지막 실행 위치는 우리에게 알려야합니다.

나는 전에 타이머 또는 레이블 변수를 사용한 적이 없으므로 여기에 볼이 많이 있다고 생각합니다.

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

run선언해야합니다 volatile. 그렇지 않으면 while(run)"최적화"될 수 있습니다 while(1). 또는 대신을 호출하는 곳으로 이동하십시오 exit.
ugoren

@ugoren 좋은 지적. 나는 최적화 (O1, O2 및 Os)를 켜고 모든 사람들이 프로그램을 중단했습니다. 불행히도 실행 앞에 '휘발성'을 추가하면 gotoloc과 num이 수정되지 않았습니다. 이러한 종류의 코드를 최적화하기 위해 gcc가 빌드되지 않았을 수 있습니다.
shiona

volatile int num메인 외부에서 정의 하면됩니다. staticgcc를 사용하면 누가 엉망인지 알 수 있다고 생각합니다.
ugoren

불행히도 메인 외부에 gotoloc을 만들 수 없거나 외부에서 0으로 설정 한 다음 0의 경우 메인의 시작 부분에서만 재설정해야합니다. 그리고 항소 통계는 사라질 것입니다. 따라서 C를 나쁜 방법으로 사용하고 있다고 말하는 것이 가장 좋습니다 .gcc는 올바르게 최적화하지 않으므로 시도하지 마십시오.
shiona

5

나는 볼링을 잘하지 않지만 OP에 관심이있을 것 같습니다. 이것은 변수 goto를 사용하는 에라토스테네스의 체입니다. 이것이 '리팩토링 된'것이었을 것입니다. 아마도 처음 몇 줄을 제외하고는 재사용 할 수 있을지 의심됩니다. 체가 끝나면 배열에 남아있는 모든 1s는 @primes소수 값에 해당합니다.

재미를 더하기 위해 ands, ors, ternaries, conditional 또는 모든 종류의 비교 연산자가 사용되지 않습니다.

@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:

내가 왜 여기에 이것을 게시하고 있는지에 대해 혼란스러워하는 경우 별도의 질문 (현재 삭제됨)에서 OP는 "이것은 실제로 물어보고 싶은 질문"이라고 말했지만 가능한지 확실하지 않았습니다. .
primo

내가 게시 한 질문에 대해 혼동이있는 경우 하나가 아닌 GOTO 사용하여 코드를 작성하는 것에 대한 질문이었습니다 .
Joe Z.

1
@JoeZeng 원래 3 개를 가지고 있었지만이 문제에 대한 올바른 해결책이되도록 1 개로 줄였습니다.
primo

3

기음

매크로 사용으로 "하나의 GOTO"가되지는 않을 것입니다.
그리고 그것은 짧기 때문에 "완전히 재구성 된"것은 그리 많지 않습니다.
그러나 여기 내 시도가 있습니다.

표준 입력에서 숫자를 읽고 모듈러스 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
예, 그런 매크로를 사용하는 것은 "하나의 GOTO"가 아닙니다. 그러나 그때도 GOTO를 사용하지 않고 프로그램의 재구성을 제공해야합니다. 문장을 제거해도 점수에 추가되지 않습니다.
Joe Z.

숫자 3을 모듈로 인쇄하면 단지를 사용하여 쉬운 것입니다 printfscanf. 귀하의 솔루션의 점수는 대부분 약 2 또는 3입니다.
Joe Z.

1
페어 포인트. 그래도 왜 그런 식으로 인쇄 하는 것을 프로그래밍 하려는 사람이 있는지 생각할 수 없습니다 n%3. 그것은 GOTO 가 소개 될 때가 아니라 제거 될 때 복잡 해지는 프로그램이어야한다 .
Joe Z.

2
"왜?" 이 사이트와 관련이 없습니다. 어리석은 일을하는 어리석은 방법들로 가득합니다. 를 제거 goto하면 프로그램이 작동하지 않습니다. 그러나 당신은 무엇을 기대 했습니까? 프로그램은 제거만으로 복잡해질 것입니까?
ugoren

1
제거 및 후속 구조 조정을 통해 가능합니다. 간단한 예는 goto를 사용하여 여러 개의 중첩 루프에서 벗어날 수 있습니다.
Joe Z.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.