Crie um programa com um simples GOTO


25

A história em quadrinhos XKCD GOTO

Sua tarefa é criar o maior programa possível que use exatamente um GOTO, sem o qual todo o programa (ou pelo menos uma grande parte dele) deve ser completamente reestruturado. A pontuação é contada como o número de instruções em seu código que mudam de lugar ou são introduzidas recentemente (remover instruções não adiciona à sua pontuação) quando o código é reestruturado sem o GOTO (outras pessoas podem contestar sua reestruturação, apresentando uma descrição mais elegante). Como esse é o código do boliche, a pontuação mais alta vence.

Nota: Não reivindico qualquer responsabilidade por ataques do velociraptor ao tentar este desafio.


2
O único goto parece problemático. Todo código C em que consigo pensar que usa um único goto pode ser trivialmente alterado para usar construções estruturadas. Vários gotos no entanto ...
Pubby

A alegação de @ Pubby parece se manter contra as duas soluções atuais. Substituir gotopor switchparece possível para ambos.
ugoren

@Pubby Quantos gotos você precisa para criar uma solução viável? Se o problema, como indicado atualmente, for impossível, eu posso criar um problema alternativo.
Joe Z.

Eu acho que você tem permissão para incorporar o desenho animado, desde que haja um link também.
Luser droog

11
Não está qualificado, mas eu realmente fiz isso .
Luser droog

Respostas:


11

C fizzbuzz

Esta solução funciona com a idéia de interrupções e rotular variáveis ​​(somente gcc, desculpe). O programa configura um timer que periodicamente chama main, onde vamos para o que for que a última execução do nosso manipulador de interrupções (main) nos disse que deveríamos.

Eu nunca usei temporizadores ou variáveis ​​de rótulo antes, então acho que há muito o que fazer aqui.

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

rundeve ser declarado volatile, caso contrário, while(run)pode ser "otimizado" para while(1). Ou então, basta ir a algum lugar que ligue exit.
ugoren

@ugoren Bom argumento. Ativei as otimizações (O1, O2 e Os) e tudo isso quebrou o programa. Infelizmente, apenas adicionando 'volátil' na frente do run, gotoloc e num não o corrigiram. Pode ser que o gcc não tenha sido criado para otimizar esse tipo de código.
shiona

Definir volatile int numfora do main deve fazê-lo. Com static, o gcc acha que sabe quem pode mexer com ele.
26613 ugoren

infelizmente não posso criar gotoloc fora do main, ou poderia, mas teria que defini-lo como zero fora e depois redefinir apenas no início do main se for zero. E as estatísticas de apelo a desaparecer. Portanto, acho melhor dizer que estou usando C de maneira ruim, pois o gcc não o otimiza corretamente, por isso não tente.
shiona

5

Perl

Não sou muito bom no boliche, mas suspeito que isso possa interessar ao OP. Esta é uma peneira de Eratóstenes usando uma variável goto. Se isso fosse "refatorado", duvido que algo seria reutilizável, além das primeiras linhas. Quando a peneira termina, todos os 1s restantes na @primesmatriz correspondem aos valores primos.

Para maior diversão, não são utilizados ands, ors, ternários, condicionais ou operadores de comparação de qualquer tipo.

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

Caso haja alguma confusão sobre o motivo pelo qual estou postando isso aqui, em uma pergunta separada (agora excluída), o OP afirmou que "essa era a pergunta que ele realmente queria fazer", mas não tinha certeza se era possível .
primo

Caso haja alguma confusão sobre qual pergunta eu postei, foi uma questão de criar código usando apenas GOTOs, em vez de apenas um.
Joe Z.

11
@ JoeZeng eu originalmente tinha três, mas reduzi-o para um, para que também fosse uma solução válida para esse problema.
Primo

3

C

Meu uso de macros talvez não o torne "um GOTO".
E é bastante curto, então "completamente reestruturado" não é muito.
Mas aqui está a minha tentativa de qualquer maneira.

Lê um número da entrada padrão, imprime-o modulu 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;
}

11
Sim, usar macros como essa não é "um GOTO". Mas, mesmo assim, você precisaria fornecer a reestruturação do programa sem usar um GOTO. A remoção de instruções não aumenta a sua pontuação.
Joe Z.

Imprimir um módulo numérico 3 seria fácil usando apenas a printfe scanf. A pontuação da sua solução provavelmente seria de 2 ou 3. #
Joe Z.

11
Ponto justo. Mas não consigo pensar por que alguém iria querer programar algo que imprime n%3dessa maneira. Deve ser um programa complicado quando o GOTO é removido , não quando é introduzido .
Joe Z.

2
"Por quê?" é irrelevante para este site - ele é cheio de maneiras estúpidas de fazer coisas estúpidas. Se você remover goto, o programa não funcionará. Mas o que você esperava - que o programa fosse complicado apenas com a remoção?
ugoren

11
Pela remoção e reestruturação subsequente, sim. Um exemplo simples pode ser o uso de goto para interromper vários loops aninhados.
Joe Z.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.