Basit bir GOTO ile bir program oluşturun


25

XKCD GOTO çizgi romanı

Göreviniz, tüm programın (veya en azından büyük bir kısmının) tamamen yeniden yapılandırılması gereken tam olarak bir GOTO kullanan en büyük programı oluşturmaktır. Puan, kodunuzdaki yerleri değiştiren veya yeni tanıtılan (ifadeleri kaldırmak puanınıza eklenmez) GOTO olmadan yeniden yapılandırıldığında (diğerlerinin daha fazlasını göstererek yeniden yapılandırma işleminize meydan okumasına izin verilir) sayılır. zarif olanı). Bu kod bowling olduğu için en yüksek puan kazanır.

Not: Bu zorluğa teşebbüs ederek velociraptor saldırıları için herhangi bir sorumluluk kabul etmiyorum.


2
Tek git sorunlu görünüyor. Tek bir goto kullandığını düşünebildiğim her C kodu yapısal yapıları kullanmak için önemsiz bir şekilde değiştirilebilir. Ancak birden fazla goto ...
Pubby

@ Pubby'nin iddiası mevcut iki çözüme aykırı görünüyor. Değiştirme gotoile switchikisi için mümkün gözükmektedir.
ugoren

@Pubby Uygulanabilir bir çözüm oluşturmak için kaç tane beye ihtiyacınız var? Hali hazırda bildirildiği gibi sorun imkansızsa alternatif bir problem yaratabilirim.
Joe Z.

Sanırım, bir link olduğu sürece, karikatürü gömmenize izin veriliyor.
luser droog,

1
Nitelikli değil, ama ben gerçekten yaptım .
luser droog

Yanıtlar:


11

C fizzbuzz

Bu çözüm, kesinti ve etiket değişkenleri fikrine dayanıyor (yalnızca gcc, üzgünüm). Program, periyodik olarak ana olarak adlandırılan, kesme işleyicimizin (ana) en son işlemini hangisi yapmamız gerektiğini bize bildirmemiz gereken bir zamanlayıcı kurar.

Daha önce zamanlayıcıları veya etiket değişkenlerini daha önce hiç kullanmadım, bu yüzden burada kaplayacak çok şey olduğunu düşünüyorum.

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

runilan edilmelidir volatile, aksi takdirde while(run)"optimize" edilebilir while(1). Veya bunun yerine, sadece çağıran bir yere gidin exit.
ugoren

@ugoren İyi nokta. Optimizasyonları açtım (O1, O2 ve Os) ve tüm bunlar programı bozdu. Maalesef, çalışmanın önüne sadece 'uçucu' eklemek, gotoloc ve num düzeltmedi. Bu tür bir kodu optimize etmek için gcc yapılı olmayabilir.
shiona

volatile int numAna dışında tanımlamak gerekir. İle static, gcc onunla kim teneke karışıklık bildiğini düşünüyor.
Şubat'ta ugoren

maalesef ana dışında gotoloc oluşturamıyorum, ya da yapabiliyorum, ama bunu sıfıra ayarlamalıydım ve sonra sıfır olduğunda sadece ana başlangıcında sıfırladım. Ve temyiz istatistiklerini solmaya. Bu yüzden, C'yi kötü bir şekilde kullandığımı söylemenin en iyisi olduğunu düşünüyorum, gcc doğru bir şekilde optimize etmiyor, bu yüzden denemeyin.
shiona

5

Perl

Bowlingde pek iyi değilim ama bunun OP'yi ilgilendireceğinden şüpheliyim. Bu değişken bir goto kullanan bir Eratosthenes Elek. Bunun 'yeniden biçimlendirilmesi' mümkün olsaydı, belki de ilk birkaç satır dışında, herhangi birinin yeniden kullanılabileceğinden şüpheliydim. Ne zaman elek uçları, geri kalan tüm 1s @primesasal değerlere dizisi tekabül.

Daha fazla eğlence için, hiçbir şey, orlar, üçlüler, şartlamalar ya da her türlü karşılaştırma operatörleri kullanılmaz.

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

Bunu neden burada yayınladığımla ilgili herhangi bir karışıklık olması durumunda, ayrı bir soruda (şimdi silindi), OP "aslında sormak istediği soru buydu ", ancak mümkün olup olmadığından emin değildi. .
primo

Hangi soruyu gönderdiğimle ilgili herhangi bir karışıklık olması durumunda , sadece bir tane yerine sadece GOTO kullanarak kod oluşturma ile ilgili bir soruydu .
Joe Z.

1
@JoeZeng Başlangıçta üç tane vardı, ancak bu sorunun da geçerli bir çözümü olması için bir taneye düşürdüm.
primo

3

C

Makroları kullanmam belki de "bir GOTO" yapmıyor.
Ve oldukça kısa, yani "tamamen yeniden yapılandırılmış" çok değil.
Ama işte yine de girişimim.

Standart girişten bir sayı okur, onu modulu 3 olarak basar.

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
Evet, böyle makroları kullanmak "bir GOTO" değil. Ancak o zaman bile, bir GOTO kullanmadan programın yeniden yapılandırılmasını sağlamanız gerekir. İfadeleri kaldırmak puanınıza eklenmez.
Joe Z.

Modulo 3 bir sayıyı basmak, sadece a printfve kullanarak kolay olacaktır scanf. Çözümünüzün puanı muhtemelen 2 veya 3 olacaktır.
Joe Z.

1
Doğru tespit. Yine de neden birisinin bu şekilde basılan bir şeyi programlamak istediğini düşünemiyorum n%3. GOTO çıkarıldığında , tanıtıldığı zaman değil , yoğunlaşan bir program olmalıdır .
Joe Z.

2
"Niye ya?" Bu site ile alakasız - aptalca şeyler yapmanın aptalca yollarıyla dolu. Kaldırırsanız goto, program çalışmaz. Ancak ne bekliyordunuz - programın tek başına kaldırılmasıyla toplanacağını mı?
ugoren

1
Çıkarılması ve daha sonra yeniden yapılanma, evet. Basit bir örnek, çoklu iç içe döngülerden çıkmak için goto kullanımı olabilir.
Joe Z.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.