Golf benim "golf öncesi" C


12

Arka fon

Benim için C gönderimleri, bir işleme aracı gerekir. Diğer birçok dilde olduğu gibi, beyaz alan çoğunlukla C kaynağında önemsizdir (ancak her zaman değil!) - yine de kodu insanlar için çok daha anlaşılır hale getirir. Tek bir yedek boşluk içermeyen, tamamen golf edilmiş bir C programı genellikle zar zor okunabilir.

Bu nedenle, beyaz alanı ve bazen yorumları içeren bir başvurusu için C kodumu yazmak istiyorum , böylece program yazarken anlaşılır bir yapı tutar. Son adım, tüm yorumları ve gereksiz boşlukları kaldırmaktır. Bu, bir stajyer bilgisayar programı tarafından gerçekten yapılması gereken sıkıcı ve akılsız bir görevdir .

Görev

Aşağıdaki kurallara göre bazı "golf öncesi" C kaynaklarından yorumları ve gereksiz boşlukları ortadan kaldıran bir program veya işlev yazın:

  • Bir \satırdaki en son karakter olan A (ters eğik çizgi) bir satır devamıdır . Bunu bulursanız, aşağıdaki satırı aynı mantıksal satırın bir parçası olarak ele almanız gerekir (örneğin, başka bir şey yapmadan önce \ve aşağıdaki satırları\n (yeni satır) tamamen kaldırabilirsiniz )
  • Yorumlar ile başlayarak yalnızca tek satırlı biçim kullanılır //. Bu nedenle, bunları kaldırmak için, //bir dizgi değişmezinin dışında karşılaştığınız her yerde mantıksal çizginin geri kalanını yoksayarsınız (aşağıya bakın).
  • Boşluk karakterleri (boşluk), \t(sekme) ve \n(satırsonu, yani burada mantıksal bir satırın sonu).
  • Bir dizi boşluk bulduğunuzda, onu çevreleyen boşluk olmayan karakterleri inceleyin. Eğer

    • her ikisi de alfasayısal veya alt çizgi (aralık [a-zA-Z0-9_]) veya
    • ikisi de +ya
    • ikisi de -ya
    • bir önceki /ve bir sonraki*

    ardından diziyi tek bir boşluk ( ) karakteriyle değiştirin.

    Aksi takdirde, diziyi tamamen ortadan kaldırın.

    Bu kuralın bazı istisnaları vardır :

    • Önişlemci yönergeleri çıktınızda kendi satırlarında görünmelidir. Bir önişlemci yönergesi ile başlayan bir satırdır #.
    • Bir dizgi değişmezinin veya karakter değişmezinin içinde boşluk bırakmamalısınız. Herhangi "(çift tırnak) / 'doğrudan ters eğik bir tek sayı ile preceeded değildir (tek tırnak) ( \) Bir başlatır veya uçları düz dize / karakter değişmezi . Dize ve karakter değişmezlerinin başladıkları satırla biteceğinden emin olabilirsiniz. dize hazır ve karakter değişmezleri bir nedenle, iç içe olamaz 'bir iç dize yanı sıra bir "bir içeriye karakterin yazı herhangi bir özel anlamı yoktur.

I / O özellikleri

Giriş ve çıkış, satırsonu karakterleri içeren karakter dizileri (dizeler) veya satırsonu karakterleri içermeyen diziler / dizeler listesi olmalıdır. Dizileri / listeleri kullanmayı seçerseniz, her öğe bir satırı temsil eder, bu nedenle yeni satırlar her öğeden sonra örtük olur .

Girişin geçerli bir C programı kaynak kodu olduğunu varsayabilirsiniz. Bu aynı zamanda yalnızca yazdırılabilir ASCII karakterlerini, sekmelerini ve yeni satırları içerdiği anlamına gelir. Hatalı biçimlendirilmiş girdide tanımlanmamış davranışa izin verilir.

Ön ve arka boşluk / boş satır edilir izin .

Test senaryoları

  1. giriş

    main() {
        printf("Hello, World!"); // hi
    }
    

    çıktı

    main(){printf("Hello, World!");}
    
  2. giriş

    #define max(x, y) \
        x > y ? x : y
    #define I(x) scanf("%d", &x)
    a;
    b; // just a needless comment, \
            because we can!
    main()
    {
        I(a);
        I(b);
        printf("\" max \": %d\n", max(a, b));
    }
    

    çıktı

    #define max(x,y)x>y?x:y
    #define I(x)scanf("%d",&x)
    a;b;main(){I(a);I(b);printf("\" max \": %d\n",max(a,b));}
    
  3. giriş

    x[10];*c;i;
    main()
    {
        int _e;
        for(; scanf("%d", &x) > 0 && ++_e;);
        for(c = x + _e; c --> x; i = 100 / *x, printf("%d ", i - --_e));
    }
    

    çıktı

    x[10];*c;i;main(){int _e;for(;scanf("%d",&x)>0&&++_e;);for(c=x+_e;c-->x;i=100/ *x,printf("%d ",i- --_e));}
    
  4. giriş

    x;
    #include <stdio.h>
    int main()
    {
        puts("hello // there");
    }
    

    çıktı

    x;
    #include<stdio.h>
    int main(){puts("hello // there");}
    
  5. girdi (gerçek dünya örneği)

    // often used functions/keywords:
    #define P printf(
    #define A case
    #define B break
    
    // loops for copying rows upwards/downwards are similar -> macro
    #define L(i, e, t, f, s) \
            for (o=i; o e;){ strcpy(l[o t], l[o f]); c[o t]=c[s o]; }
    
    // range check for rows/columns is similar -> macro
    #define R(m,o) { return b<1|b>m ? m o : b; }
    
    // checking for numerical input is needed twice (move and print command):
    #define N(f) sscanf(f, "%d,%d", &i, &j) || sscanf(f, ",%d", &j)
    
    // room for 999 rows with each 999 cols (not specified, should be enough)
    // also declare "current line pointers" (*L for data, *C for line length),
    // an input buffer (a) and scratch variables
    r, i, j, o, z, c[999], *C, x=1, y=1;
    char a[999], l[999][999], (*L)[999];
    
    // move rows down from current cursor position
    D()
    {
        L(r, >y, , -1, --)
        r++ ? strcpy(l[o], l[o-1]+--x), c[o-1]=x, l[o-1][x]=0 : 0;
        c[y++] = strlen(l[o]);
        x=1;
    }
    
    // move rows up, appending uppermost to current line
    U()
    {
        strcat(*L, l[y]);
        *C = strlen(*L);
        L(y+1, <r, -1, , ++)
        --r;
        *l[r] = c[r] = 0;
    }
    
    // normalize positions, treat 0 as max
    X(b) R(c[y-1], +1)
    Y(b) R(r, )
    
    main()
    {
        for(;;) // forever
        {
            // initialize z as current line index, the current line pointers,
            // i and j for default values of positioning
            z = i = y;
            L = l + --z;
            C = c + z;
            j = x;
    
            // prompt:
            !r || y/r && x > *C
                ? P "end> ")
                : P "%d,%d> ", y, x);
    
            // read a line of input (using scanf so we don't need an include)
            scanf("%[^\n]%*c", a)
    
                // no command arguments -> make check easier:
                ? a[2] *= !!a[1],
    
                // numerical input -> have move command:
                // calculate new coordinates, checking for "relative"
                N(a)
                    ? y = Y(i + (i<0 | *a=='+') * y)
                        , x = X(j + (j<0 || strchr(a+1, '+')) * x)
                    :0
    
                // check for empty input, read single newline
                // and perform <return> command:
                : ( *a = D(), scanf("%*c") );
    
            switch(*a)
            {
                A 'e':
                    y = r;
                    x = c[r-1] + 1;
                    B;
    
                A 'b':
                    y = 1;
                    x = 1;
                    B;
    
                A 'L':
                    for(o = y-4; ++o < y+2;)
                        o<0 ^ o<r && P "%c%s\n", o^z ? ' ' : '>', l[o]);
                    for(o = x+1; --o;)
                        P " ");
                    P "^\n");
                    B;
    
                A 'l':
                    puts(*L);
                    B;
    
                A 'p':
                    i = 1;
                    j = 0;
                    N(a+2);
                    for(o = Y(i)-1; o<Y(j); ++o)
                        puts(l[o]);
                    B;
    
                A 'A':
                    y = r++;
                    strcpy(l[y], a+2);
                    x = c[y] = strlen(a+2);
                    ++x;
                    ++y;
                    B;
    
                A 'i':
                    D();
                    --y;
                    x=X(0);
                    // Commands i and r are very similar -> fall through
                    // from i to r after moving rows down and setting
                    // position at end of line:
    
                A 'r':
                    strcpy(*L+x-1, a+2);
                    *C = strlen(*L);
                    x = 1;
                    ++y > r && ++r;
                    B;
    
                A 'I':
                    o = strlen(a+2);
                    memmove(*L+x+o-1, *L+x-1, *C-x+1);
                    *C += o;
                    memcpy(*L+x-1, a+2, o);
                    x += o;
                    B;
    
                A 'd':
                    **L ? **L = *C = 0, x = 1 : U();
                    y = y>r ? r : y;
                    B;
    
                A 'j':
                    y<r && U();
            }
        }
    }
    

    çıktı

    #define P printf(
    #define A case
    #define B break
    #define L(i,e,t,f,s)for(o=i;o e;){strcpy(l[o t],l[o f]);c[o t]=c[s o];}
    #define R(m,o){return b<1|b>m?m o:b;}
    #define N(f)sscanf(f,"%d,%d",&i,&j)||sscanf(f,",%d",&j)
    r,i,j,o,z,c[999],*C,x=1,y=1;char a[999],l[999][999],(*L)[999];D(){L(r,>y,,-1,--)r++?strcpy(l[o],l[o-1]+--x),c[o-1]=x,l[o-1][x]=0:0;c[y++]=strlen(l[o]);x=1;}U(){strcat(*L,l[y]);*C=strlen(*L);L(y+1,<r,-1,,++)--r;*l[r]=c[r]=0;}X(b)R(c[y-1],+1)Y(b)R(r,)main(){for(;;){z=i=y;L=l+--z;C=c+z;j=x;!r||y/r&&x>*C?P"end> "):P"%d,%d> ",y,x);scanf("%[^\n]%*c",a)?a[2]*=!!a[1],N(a)?y=Y(i+(i<0|*a=='+')*y),x=X(j+(j<0||strchr(a+1,'+'))*x):0:(*a=D(),scanf("%*c"));switch(*a){A'e':y=r;x=c[r-1]+1;B;A'b':y=1;x=1;B;A'L':for(o=y-4;++o<y+2;)o<0^o<r&&P"%c%s\n",o^z?' ':'>',l[o]);for(o=x+1;--o;)P" ");P"^\n");B;A'l':puts(*L);B;A'p':i=1;j=0;N(a+2);for(o=Y(i)-1;o<Y(j);++o)puts(l[o]);B;A'A':y=r++;strcpy(l[y],a+2);x=c[y]=strlen(a+2);++x;++y;B;A'i':D();--y;x=X(0);A'r':strcpy(*L+x-1,a+2);*C=strlen(*L);x=1;++y>r&&++r;B;A'I':o=strlen(a+2);memmove(*L+x+o-1,*L+x-1,*C-x+1);*C+=o;memcpy(*L+x-1,a+2,o);x+=o;B;A'd':**L?**L=*C=0,x=1:U();y=y>r?r:y;B;A'j':y<r&&U();}}}
    

Bu , çok kısa (bayt cinsinden) geçerli cevap kazanır.



Yanıtlar:


4

Pip , 148 135 133 138 bayt

aRM"\
"R`("|').*?(?<!\\)(\\\\)*\1`{lPBaC:++i+191}R[`//.*``#.*`{X*aJw.`(?=`}.')M[A`\w`RL2"++""--""/*"]w`¶+`'·C(192+,#l)][x_WR'¶{aRw'·}xnsl]

Bayt sayılır CP-1252 , yani ve ·her bayt bulunmaktadır. Bunun, C kodunun (gerçek bir komut satırında) bol kaçış dizilerinin kullanılmasını gerektirecek tek bir komut satırı argümanı olarak beklediğini unutmayın. Çevrimiçi deneyin de çok daha kolay !

Hafif soluksuz versiyonun açıklaması

Kod, birkaç hile ile bir dizi değiştirme işlemi yapar.

Ters eğik çizgi devamları

Hepimiz RMdeğişmez dizenin oluşumları

"\
"

yani ters eğik çizgi ve ardından satırsonu.

Dize ve karakter değişmez değerleri

Bir geri çağırma işleviyle normal ifade değiştirme kullanıyoruz:

`("|').*?(?<!\\)(\\\\)*\1`

{
 lPBa
 C(++i + 191)
}

Normal ifade, tek veya çift tırnak .*?işareti ile eşleşir , ardından 0 veya daha fazla karakterle eşleşen, açgözlü olmayan bir değer gelir . Önceki karakterin ters eğik çizgi olmadığından emin olmak için olumsuz bir bakış açımız var; sonra tekrar çift eğik çizgi ve ardından açılış sınırlayıcısını eşleştiriyoruz.

Geri arama işlevi, dizgi / karakter değişmezini alır ve listenin arkasına iter l. Daha sonra, karakter kodu 192 ( À) ile başlayan ve her değişmez değer değiştirilerek artan bir karakter döndürür . Böylece, kod şöyle dönüştürülür:

printf("%c", '\'');

printf(À, Á);

Bu yedek karakterlerin kaynak kodunda yer almamaları garanti edilir, yani daha sonra açıkça değiştirebiliriz.

Yorumlar

`//.*`

x

Normal ifade //artı yeni satıra kadar olan her şeyle eşleşir ve onun yerine x(boş dizeye önceden ayarlanmış) konur.

Önişlemci yönergeleri

`#.*`

_WR'¶

Bir pound işareti ile başlayan yeni satır olmayan karakterleri sarar .

Kaldırılmaması gereken alanlar

{
 (
  X*a J w.`(?=`
 ) . ')
}
M
[
 A`\w` RL 2
 "++"
 "--"
 "/*"
]

{
 a R w '·
}

Burada çok şey oluyor. İlk bölüm aşağıdaki regexler listesini oluşturur:

[
 `(?a)\w\s+(?=(?a)\w)`  Whitespace surrounded by [a-zA-Z_]
 `\+\s+(?=\+)`          Whitespace surrounded by +
 `\-\s+(?=\-)`          Whitespace surrounded by -
 `\/\s+(?=\*)`          Whitespace surrounded by / *
]

Örneğin, sadece maç için lookaheads kullanımına dikkat e in define P printf. Bu maç bu şekilde tüketmez P, yani bir sonraki maç bunu kullanabilir.

Bu regexes listesini, bir işlevi listenin içerdiği bir listeyle eşleyerek oluştururuz

[
 [`(?a)\w` `(?a)\w`]
 "++"
 "--"
 "/*"
]

ve işlev bunu her öğeye yapar:

(X*aJw.`(?=`).')
 X*a              Map unary X to elements/chars a: converts to regex, escaping as needed
                  Regexes like `\w` stay unchanged; strings like "+" become `\+`
    J             Join the resulting list on:
     w             Preset variable for `\s+`
      .`(?=`       plus the beginning of the lookahead syntax
(           ).')  Concatenate the closing paren of the lookahead

Normal ifadelerimizi aldıktan sonra, bunların oluşumlarını bu geri arama işleviyle değiştiririz:

{aRw'·}

her maçta boşluk koşusunun yerini alır ·.

Boşluğun ortadan kaldırılması ve temizlenmesi

[w `¶+` '·]

[x n s]

Art arda üç değiştirme w, boş dize ( x), satırsonu ve boşluk için boşlukların ( ) boşluklarının yerine geçer ·.

Dize ve karakter değişmez değerlerini geri değiştirme

C(192+,#l)

l

Karakterleri alıp 192 + range(len(l))dönüştürerek değişmezler için ikame olarak kullandığımız tüm karakterlerin bir listesini oluştururuz . Daha sonra bunların her birini, ilişkili değişmez değeri ile değiştirebiliriz l.

Ve bu kadar! Ortaya çıkan dize otomatik yazdırılır.


Harika, etkilendim (+1)! //Dize hazır bilgisi içerisine dahil etmek kesinlikle bir test vakası için iyi bir fikirdir, yarın bir tane ekleyeceğim.
Felix Palmen

Uhm ... şimdi burada da ince bir böcek buldum ...
Felix Palmen

14 gün sonra (gelecek haftanın sonu) bir kazanan seçeceğim ve bu hatayı düzeltmek için zaman bulursanız çözümünüz ilk aday olacaktır . Şu anda en düşük puanınız var :)
Felix Palmen

1
@FelixPalmen Sabit!
DLosc

7

Haskell , 327 360 418 394 bayt

g.(m.w.r.r=<<).lines.f
n:c:z="\n#_0123456789"++['A'..'Z']++['a'..'z']
(!)x=elem x
f('\\':'\n':a)=f a
f(a:b)=a:f b
f a=a
m('#':a)=c:a++[n]
m a=a
g(a:'#':b)=a:[n|a/=n]++c:g b
g(a:b)=a:g b
g a=a
s=span(!" \t")
r=reverse.snd.s
l n(a:b)d|a==d,n=a:w(snd$s b)|1>0=a:l(not$n&&a=='\\')b d
w('/':'/':_)=[]
w(a:b)|a!"\"'"=a:l(1>0)b a|(p,q:u)<-s b=a:[' '|p>"",a!z&&q!z||[a,q]!words"++ -- /*"]++w(q:u)
w a=a

Çevrimiçi deneyin!

Bu yazmak çok eğlenceliydi! İlk olarak ffonksiyon gelir ve satır sonundaki tüm ters eğik çizgileri kaldırır, ardından linesonu yeni satırlardaki bir dizeler listesine böler. Daha sonra bir grup işlevi satırlara eşler ve hepsini bir araya getiririz. Bu işlevler: Sol (, şerit boşluk t) ve sağdan ( olduğunu ); boşlukları ortadan kaldırmak, dize ve karakter değişmezlerini yok saymak ve yorumları kaldırmak ( ); ve son olarak, satır # ile başlıyorsa sonuna yeni satır karakteri ekler. Tüm satırlar bir araya getirildikten sonra # karakter arar ve öncesinde bir satırsonu olmasını sağlar.r.t.rrreversewg

wbiraz karmaşık olduğundan daha fazla açıklayacağım. İlk ben "//" için kontrol çünkü wben bir dize hazır bilgi içinde değilim biliyorum Bu bir yorum olduğunu biliyorum, bu yüzden satırın geri kalanını bırakın. Sonra kafanın bir dize veya karakter değişmezi için bir sınırlayıcı olup olmadığını kontrol ediyorum. Eğer öyleyse onu başa ve lkarakterlerden geçen batonu geçiririm , nçift ​​sayıda ardışık eğik çizgi varsa , "kaçış" durumunu takip eder . Bir lsınırlayıcı algıladığında ve kaçış durumunda olmadığında , ilk karakterin boşluk olmamasını beklediği için wboşluktan sonra boşluğu ortadan kaldırmak için kırparak batona geri geçer w. Ne zamanwkuyrukta boşluk aramak için yayılma alanı kullanan bir sınırlayıcı bulamaz. Varsa, etrafındaki karakterlerin temasa geçirilip getirilemeyeceğini kontrol eder ve varsa boşluk ekler. Sonra boşluk sona erdikten sonra tekrar eder. Boşluk yoksa boşluk yerleştirilmez ve yine de hareket eder.

DÜZENLEME: @DLosc programımda aslında benim de kısaltmak için bir yol neden bir hata işaret ettiğiniz için çok teşekkürler! Kalıp eşleşmesi için Yaşasın!

EDIT2: Spesifikasyonu okumayı bitirmemiş bir aptalım! Bunu işaret ettiğiniz için tekrar teşekkürler DLosc!

EDIT3: Sadece döndü bazı can sıkıcı tip azaltma şey fark e=elemiçine Char->[Char]->Booldolayısıyla üzerinde kırma, nedense e[a,q]. Doğru olmaya zorlamak için bir tür imza eklemem gerekiyordu. Bunu nasıl düzeltebileceğimi bilen var mı? Daha önce Haskell'de bu problemi yaşamadım. TIO

EDIT4: @FelixPalmen hata için hızlı düzeltme bana gösterdi. Biraz zamanım olduğunda golf oynamaya çalışabilirim.

EDIT5: @Lynn sayesinde -24 bayt! Teşekkür ederim! n:c:z=...Gerçekten harika gibi desen eşleme kullanarak küresel kapsamda bir şeyler atayabileceğinizi bilmiyordum ! elemBen de bunu düşünmüş olsaydım bir operatör yapmak iyi bir fikir .



2
Sen içine çalışan korkulan monomorfizm kısıtlama ; tanımlamak e x y=elem x y(hatta çift e x=elem x) probleminizi çözer. ( eBir operatörün adını değiştirdim (!).)
Lynn

3

Cı, 497 494 490 489 bayt

C'yi işlediğimiz için, bunu C kullanarak yapalım ! İşlev f()char işaretçisinden girişi alır pve işaretçiye qçıkarır ve girişin ASCII'de olduğunu varsayar:

#define O*q++
#define R (r=*p++)
#define V(c)(isalnum(c)||c==95)
char*p,*q,r,s,t;d(){isspace(r)?g():r==47&&*p==r?c(),g():r==92?e():(O=s=r)==34?b():r==39?O=R,a():r?a():(O=r);}a(){R;d();}b(){((O=R)==34?a:r==92?O=R,b:b)();}c(){while(R-10)p+=r==92;}e(){R-10?s=O=92,O=r,a():h();}j(){(!isspace(R)?r==47&&*p==r?c(),j:(t=r==35,d):j)();}f(){t=*p==35;j();}i(){V(s)&&V(r)||s==47&&r==42||(s==43||s==45)&&r==s&&*p==s?O=32:0;d();}h(){isspace(R)?g():i();}g(){(r==10?t?O=r,j:*p==35?s-10?s=O=r,j:0:h:h)();}

Dosyanın iyi biçimlendirildiğini varsayıyoruz - dize ve karakter değişmez değerleri kapalı ve son satırda bir yorum varsa, dosyayı kapatmak için yeni bir satır olması gerekir.

açıklama

Golf öncesi versiyon biraz daha okunaklı, korkarım:

#define O *q++=
#define R (r=*p++)
#define V(c)(isalnum(c)||c=='_')
char*p,*q,r,s,t;
d(){isspace(r)?g():r=='/'&&*p==r?c(),g():r=='\\'?e():(O s=r)=='"'?b():r=='\''?O R,a():r?a():(O r);}
a(){R;d();}
b(){((O R)=='"'?a:r=='\\'?O R,b:b)();}
c(){while(R!='\n')p+=r=='\\';}
e(){R!='\n'?s=O'\\',O r,a():h();}
j(){(!isspace(R)?r=='/'&&*p==r?c(),j:(t=r=='#',d):j)();}
f(){t=*p=='#';j();}
i(){V(s)&&V(r)||s=='/'&&r=='*'||(s=='+'||s=='-')&&r==s&&*p==s?O' ':0;d();}
h(){isspace(R)?g():i();}
g(){(r=='\n'?t?O r,j:*p=='#'?s!='\n'?s=O r,j:0:h:h)();}

Kuyruk özyineleme ile bir durum makinesi uygular. Yardımcı makrolar ve değişkenler

  • Oiçin o ıkış
  • Riçin r içine EAD girişir
  • Vv alid tanımlayıcı karakterlerini belirlemek için (beri !isalnum('_'))
  • pve q- Açıklandığı gibi G / Ç işaretçileri
  • r- Son karakter olmaya r ead
  • s- s son kullanılan boşluk olmayan karakter
  • t- t ag bir önişlemci direktifi üzerinde çalışırken

Eyaletlerimiz

  • a() - normal C kodu
  • b() - dizgi değişmezi
  • c() - yorum Yap
  • d() - okuduktan sonra normal C kodu r
  • e() - kaçış dizisi
  • f() - başlangıç ​​durumu (ana işlev)
  • g() - boşlukta
  • h()- boşlukta - g()veyai()
  • i() - boşluktan hemen sonra - boşluk karakteri eklememiz gerekir mi?
  • j() - ilk boşluk - asla boşluk karakteri girmeyin

Test programı

#define DEMO(code)                              \
    do {                                        \
        char in[] = code;                       \
        char out[sizeof in];                    \
        p=in;q=out;f();                         \
        puts("vvvvvvvvvv");                     \
        puts(out);                              \
        puts("^^^^^^^^^^");                     \
    } while (0)

#include<stdio.h>
#include<stdlib.h>
int main()
{
    DEMO(
         "main() {\n"
         "    printf(\"Hello, World!\"); // hi\n"
         "}\n"
         );
    DEMO(
         "#define max(x, y)                               \\\n"
         "    x > y ? x : y\n"
         "#define I(x) scanf(\"%d\", &x)\n"
         "a;\n"
         "b; // just a needless comment, \\\n"
         "        because we can!\n"
         "main()\n"
         "{\n"
         "    I(a);\n"
         "    I(b);\n"
         "    printf(\"\\\" max \\\": %d\\n\", max(a, b));\n"
         "}\n"
         );
    DEMO(
         "x[10];*c;i;\n"
         "main()\n"
         "{\n"
         "    int _e;\n"
         "    for(; scanf(\"%d\", &x) > 0 && ++_e;);\n"
         "    for(c = x + _e; c --> x; i = 100 / *x, printf(\"%d \", i - --_e));\n"
         "}\n"
         );
    DEMO(
         "// often used functions/keywords:\n"
         "#define P printf(\n"
         "#define A case\n"
         "#define B break\n"
         "\n"
         "// loops for copying rows upwards/downwards are similar -> macro\n"
         "#define L(i, e, t, f, s) \\\n"
         "        for (o=i; o e;){ strcpy(l[o t], l[o f]); c[o t]=c[s o]; }\n"
         "\n"
         "// range check for rows/columns is similar -> macro\n"
         "#define R(m,o) { return b<1|b>m ? m o : b; }\n"
         "\n"
         "// checking for numerical input is needed twice (move and print command):\n"
         "#define N(f) sscanf(f, \"%d,%d\", &i, &j) || sscanf(f, \",%d\", &j)\n"
         "\n"
         "// room for 999 rows with each 999 cols (not specified, should be enough)\n"
         "// also declare \"current line pointers\" (*L for data, *C for line length),\n"
         "// an input buffer (a) and scratch variables\n"
         "r, i, j, o, z, c[999], *C, x=1, y=1;\n"
         "char a[999], l[999][999], (*L)[999];\n"
         "\n"
         "// move rows down from current cursor position\n"
         "D()\n"
         "{\n"
         "    L(r, >y, , -1, --)\n"
         "    r++ ? strcpy(l[o], l[o-1]+--x), c[o-1]=x, l[o-1][x]=0 : 0;\n"
         "    c[y++] = strlen(l[o]);\n"
         "    x=1;\n"
         "}\n"
         "\n"
         "// move rows up, appending uppermost to current line\n"
         "U()\n"
         "{\n"
         "    strcat(*L, l[y]);\n"
         "    *C = strlen(*L);\n"
         "    L(y+1, <r, -1, , ++)\n"
         "    --r;\n"
         "    *l[r] = c[r] = 0;\n"
         "}\n"
         "\n"
         "// normalize positions, treat 0 as max\n"
         "X(b) R(c[y-1], +1)\n"
         "Y(b) R(r, )\n"
         "\n"
         "main()\n"
         "{\n"
         "    for(;;) // forever\n"
         "    {\n"
         "        // initialize z as current line index, the current line pointers,\n"
         "        // i and j for default values of positioning\n"
         "        z = i = y;\n"
         "        L = l + --z;\n"
         "        C = c + z;\n"
         "        j = x;\n"
         "\n"
         "        // prompt:\n"
         "        !r || y/r && x > *C\n"
         "            ? P \"end> \")\n"
         "            : P \"%d,%d> \", y, x);\n"
         "\n"
         "        // read a line of input (using scanf so we don't need an include)\n"
         "        scanf(\"%[^\\n]%*c\", a)\n"
         "\n"
         "            // no command arguments -> make check easier:\n"
         "            ? a[2] *= !!a[1],\n"
         "\n"
         "            // numerical input -> have move command:\n"
         "            // calculate new coordinates, checking for \"relative\"\n"
         "            N(a)\n"
         "                ? y = Y(i + (i<0 | *a=='+') * y)\n"
         "                    , x = X(j + (j<0 || strchr(a+1, '+')) * x)\n"
         "                :0\n"
         "\n"
         "            // check for empty input, read single newline\n"
         "            // and perform <return> command:\n"
         "            : ( *a = D(), scanf(\"%*c\") );\n"
         "\n"
         "        switch(*a)\n"
         "        {\n"
         "            A 'e':\n"
         "                y = r;\n"
         "                x = c[r-1] + 1;\n"
         "                B;\n"
         "\n"
         "            A 'b':\n"
         "                y = 1;\n"
         "                x = 1;\n"
         "                B;\n"
         "\n"
         "            A 'L':\n"
         "                for(o = y-4; ++o < y+2;)\n"
         "                    o<0 ^ o<r && P \"%c%s\\n\", o^z ? ' ' : '>', l[o]);\n"
         "                for(o = x+1; --o;)\n"
         "                    P \" \");\n"
         "                P \"^\\n\");\n"
         "                B;\n"
         "\n"
         "            A 'l':\n"
         "                puts(*L);\n"
         "                B;\n"
         "\n"
         "            A 'p':\n"
         "                i = 1;\n"
         "                j = 0;\n"
         "                N(a+2);\n"
         "                for(o = Y(i)-1; o<Y(j); ++o)\n"
         "                    puts(l[o]);\n"
         "                B;\n"
         "\n"
         "            A 'A':\n"
         "                y = r++;\n"
         "                strcpy(l[y], a+2);\n"
         "                x = c[y] = strlen(a+2);\n"
         "                ++x;\n"
         "                ++y;\n"
         "                B;\n"
         "\n"
         "            A 'i':\n"
         "                D();\n"
         "                --y;\n"
         "                x=X(0);\n"
         "                // Commands i and r are very similar -> fall through\n"
         "                // from i to r after moving rows down and setting\n"
         "                // position at end of line:\n"
         "\n"
         "            A 'r':\n"
         "                strcpy(*L+x-1, a+2);\n"
         "                *C = strlen(*L);\n"
         "                x = 1;\n"
         "                ++y > r && ++r;\n"
         "                B;\n"
         "\n"
         "            A 'I':\n"
         "                o = strlen(a+2);\n"
         "                memmove(*L+x+o-1, *L+x-1, *C-x+1);\n"
         "                *C += o;\n"
         "                memcpy(*L+x-1, a+2, o);\n"
         "                x += o;\n"
         "                B;\n"
         "\n"
         "            A 'd':\n"
         "                **L ? **L = *C = 0, x = 1 : U();\n"
         "                y = y>r ? r : y;\n"
         "                B;\n"
         "\n"
         "            A 'j':\n"
         "                y<r && U();\n"
         "        }\n"
         "    }\n"
         "}\n";);
}

Bu üretir

main(){printf("Hello, World!");}
#define max(x,y)x>y?x:y
#define I(x)scanf("%d",&x)
a;b;main(){I(a);I(b);printf("\" max \": %d\n",max(a,b));}
x[10];*c;i;main(){int _e;for(;scanf("%d",&x)>0&&++_e;);for(c=x+_e;c-->x;i=100/ *x,printf("%d ",i- --_e));}
#define P printf(
#define A case
#define B break
#define L(i,e,t,f,s)for(o=i;o e;){strcpy(l[o t],l[o f]);c[o t]=c[s o];}
#define R(m,o){return b<1|b>m?m o:b;}
#define N(f)sscanf(f,"%d,%d",&i,&j)||sscanf(f,",%d",&j)
r,i,j,o,z,c[999],*C,x=1,y=1;char a[999],l[999][999],(*L)[999];D(){L(r,>y,,-1,--)r++?strcpy(l[o],l[o-1]+--x),c[o-1]=x,l[o-1][x]=0:0;c[y++]=strlen(l[o]);x=1;}U(){strcat(*L,l[y]);*C=strlen(*L);L(y+1,<r,-1,,++)--r;*l[r]=c[r]=0;}X(b)R(c[y-1],+1)Y(b)R(r,)main(){for(;;){z=i=y;L=l+--z;C=c+z;j=x;!r||y/r&&x>*C?P"end> "):P"%d,%d> ",y,x);scanf("%[^\n]%*c",a)?a[2]*=!!a[1],N(a)?y=Y(i+(i<0|*a=='+')*y),x=X(j+(j<0||strchr(a+1,'+'))*x):0:(*a=D(),scanf("%*c"));switch(*a){A'e':y=r;x=c[r-1]+1;B;A'b':y=1;x=1;B;A'L':for(o=y-4;++o<y+2;)o<0^o<r&&P"%c%s\n",o^z?' ' :'>',l[o]);for(o=x+1;--o;)P" ");P"^\n");B;A'l':puts(*L);B;A'p':i=1;j=0;N(a+2);for(o=Y(i)-1;o<Y(j);++o)puts(l[o]);B;A'A':y=r++;strcpy(l[y],a+2);x=c[y]=strlen(a+2);++x;++y;B;A'i':D();--y;x=X(0);A'r':strcpy(*L+x-1,a+2);*C=strlen(*L);x=1;++y>r&&++r;B;A'I':o=strlen(a+2);memmove(*L+x+o-1,*L+x-1,*C-x+1);*C+=o;memcpy(*L+x-1,a+2,o);x+=o;B;A'd':**L?**L=*C=0,x=1:U();y=y>r?r:y;B;A'j':y<r&&U();}}}

sınırlama

Bu,

#define A (x)

adı genişletmeden ayıran alanı kaldırarak

#define A(x)

tamamen farklı bir anlamla. Bu durum test setlerinde yok, bu yüzden ele almayacağım.

Çok geçişli yerinde dönüşümle daha kısa bir sürüm üretebileceğimden şüpheleniyorum - bunu önümüzdeki hafta deneyebilirim.


Tanımının =sonundaki işareti kaldırarak bir bayt kaydedebilir Ove her çağrıyı izleyen alanı Oa olarak değiştirebilirsiniz =.
Zacharý

"Sınırlama" Hakkında) ayrıca söz kendisinde yorumumu bakınız - algılanması; bu harika bu çok fazla karmaşıklık eklersiniz.
Felix Palmen

@Zachary - bunun için teşekkürler - Genel kodu ASCII'ye özgü olarak değiştirdiğimde unuttum O'\\'ve O' 'her ikisi de bir alan kazandı.
Toby Speight


2

Cı,  705   663  640 bayt

40 bayt golf için @ Zacharý ve 23 bayt golf için @Nahuel Fouilleul sayesinde!

#define A(x)(x>47&x<58|x>64&x<91|x>96&x<123)
#define K if(*C==47&(C[1]==47|p==47)){if(p==47)--G;for(c=1;c;*C++-92||c++)*C-10||--c;if(d)p=*G++=10,--d;
#define D if(!d&*C==35){d=1;if(p&p-10)p=*G++=10;}
#define S K}if((A(p)&A(*C))|(p==*C&l==43|p==45)|p==47&*C==42|p==95&(A(*C)|*C==95)|*C==95&(A(p)|p==95))p=*G++=32;}
#define W*C<33|*C==92
#define F{for(;W;C++)
c,d,e,p,l;g(char*C,char*G)F;for(;*C;*C>32&&*C-34&&*C-39&&(p=*G++=*C),*C-34&&*C-39&&C++){l=e=0;if(*C==34)l=34;if(*C==39)l=39;if(l)for(*G++=l,p=*G++=*++C;*C++-l|e%2;e=*(C-1)-92?0:e+1)p=*G++=*C;K}D if(d){if(W)F{*C-92||++d;*C-10||--d;if(!d){p=*G++=10;goto E;}}S}else{if(W)F;S}E:D}*G=0;}

Çevrimiçi deneyin!


Can for(;W;C++){}haline for(;W;C++);?
Zacharý

@ Zacharý hiç istenmedi. Bu son adım için bir çok şey: gereksiz boşlukları ve yorumları kaldırın.
Felix Palmen

Koduna atıfta bulunuyordum, meydan okumayı değil.
Zacharý

@ Zacharý haha ​​Anlıyorum ... kod ve giriş aynı dilde olduğunda garip;)
Felix Palmen

Bu 665 bayt için çalışır mı? goo.gl/E6tk8V
Zacharý

2

Perl 5, 250 + 3 (-00n) , 167 + 1 (-p) bayt

$_.=<>while s/\\
//;s,(//.*)|(("|')(\\.|.)*?\3)|/?[^"'/]+,$1|$2?$2:$&=~s@(\S?)\K\s+(?=(.?))@"$1$2"=~/\w\w|\+\+|--|\/\*/&&$"@ger,ge;$d++&&$l+/^#/&&s/^/
/,$l=/^#/m if/./

Çevrimiçi deneyin


Evet, optimal olmayan bir çözüm koydum. Ben sadece tio bağlantısını ekledim, zamanım olduğunda golf için bakacağım.
Nahuel Fouilleul

önişlemci yönergesi kod önce yerleştirildiğinde kendi satırında, test durumlarda olduğu gibi ancak gerekirse ben değişiklik ekleyeceğim
Nahuel Fouilleul

1
güncelleme bkz. güncelleme
Nahuel Fouilleul

0

Python 2 , 479 456 445 434 502 497 bayt

e=enumerate
import re
u=re.sub
def f(s):
 r=()
 for l in u(r'\\\n','',s).split('\n'):
	s=p=w=0;L=[]
	for i,c in e(l):
	 if(p<1)*'//'==l[i:i+2]:l=l[:i]
	 if c in"'\""and w%2<1:
		if p in(c,0):L+=[l[s:i+1]];s=i+1
		p=[0,c][p<1]
	 w=[0,w+1]['\\'==c]
	r+=L+[l[s:]],
 S=''
 for l in r:s=''.join([u('. .',R,u('. .',R,u('\s+',' ',x))).strip(),x][i%2]for i,x in e(l));S+=['%s','\n%s\n'][s[:1]=='#']%s
 print u('\n\n','\n',S).strip()
def R(m):g=m.group(0);f=g[::2];return[f,g][f.isalnum()or f in'++ -- /*']

Çevrimiçi deneyin!

Düzenleme: Sabit dahil etmek - -, + +ve/ *

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.