골프 “내 골프”C also declare “current

배경

내를 들어 C에 제출, 내가 처리 도구가 필요합니다. 다른 많은 언어들에서와 같이, 공백은 대부분 C 소스와 관련이 없지만 (항상 그런 것은 아닙니다!) 여전히 인간에게 코드를 훨씬 더 이해하기 쉽게 만듭니다. 단일 중복 공백이없는 완전 골프 C 프로그램은 거의 읽을 수없는 경우가 많습니다.

따라서 공백과 때로는 주석을 포함하여 제출을 위해 코드를 C로 작성하고 싶습니다 . 그래서 프로그램은 작성하는 동안 이해하기 쉬운 구조를 유지합니다. 마지막 단계는 모든 주석과 중복 공백을 제거하는 것입니다. 이것은 인턴 컴퓨터 프로그램 이 실제로 수행해야하는 지루하고 생각이없는 작업입니다 .

직무

다음 규칙에 따라 일부 “골프 된”C 소스에서 주석 및 중복 공백을 제거하는 프로그램 또는 기능을 작성하십시오.

  • \줄의 맨 마지막 문자로 (백 슬래시)는 인 라인을 계속 . 이것을 찾으면 다음 행을 동일한 논리 행의 일부로 취급해야합니다 (예를 들어, 다른 작업을 수행하기 전에 \및 다음 \n(개행)을 완전히 제거 할 수 있음 )
  • 주석은로 시작하는 한 줄 형식 만 사용합니다 //. 따라서 제거하기 //위해 문자열 리터럴 외부에서 발생 하는 모든 논리 행을 무시합니다 (아래 참조).
  • 공백 문자는 (공백), \t(탭) 및 \n(개행 문자이므로 논리 행의 끝)입니다.
  • 일련의 공백을 찾으면 공백이 아닌 문자를 검사하십시오. 만약

    • 둘 다 영숫자 또는 밑줄 (범위 [a-zA-Z0-9_]) 또는
    • 둘 다 +또는
    • 둘 다 -또는
    • 앞에 /오는 것은 있고 다음 것은*

    그런 다음 시퀀스를 단일 공백 ​​( ) 문자 로 바꾸십시오 .

    그렇지 않으면 시퀀스를 완전히 제거하십시오.

    이 규칙에는 몇 가지 예외가 있습니다 .

    • 프리 프로세서 지시문 은 출력에서 ​​고유 한 행에 나타나야합니다. 전 처리기 지시문은로 시작하는 줄입니다 #.
    • 문자열 리터럴 또는 문자 리터럴 안에서 공백을 제거해서는 안됩니다. 모든 "(큰 따옴표) / '직접 백 슬래시의 홀수 덧붙일되지 않는다 (따옴표)는 ( \)를 시작 또는 끝 문자열 문자 / 문자 리터럴 . 문자열 및 문자 리터럴은 시작된 줄과 동일한 줄에서 끝나는 것이 보장됩니다. 문자열 리터럴문자 리터럴은 소위, 중첩 될 수 없습니다 '돌며 문자열 리터럴 뿐만 아니라 ", 안쪽 문자 그대로 어떤 특별한 의미가 없습니다.

I / O 사양

입력 및 출력은 개행 문자를 포함하는 문자 시퀀스 (문자열)이거나 개행 문자를 포함하지 않는 문자열의 배열 / 목록이어야합니다. 배열 / 목록을 사용하도록 선택한 경우 각 요소는 한 줄을 나타내므로 각 요소 뒤에 줄 바꿈이 내재 됩니다.

입력이 유효한 C 프로그램 소스 코드라고 가정 할 수 있습니다. 이것은 또한 인쇄 가능한 ASCII 문자, 탭 및 줄 바꿈 만 포함한다는 것을 의미합니다. 잘못된 입력에 대해 정의되지 않은 동작이 허용됩니다.

선행 / 후행 공백 / 빈 줄허용되지 않습니다 .

테스트 사례

  1. 입력

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

    산출

    main(){printf("Hello, World!");}
    
  2. 입력

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

    산출

    #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. 입력

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

    산출

    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. 입력

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

    산출

    x;
    #include<stdio.h>
    int main(){puts("hello // there");}
    
  5. 입력 (실제 예제)

    // 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();
            }
        }
    }
    

    산출

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

이것은 이므로 가장 짧은 (바이트 단위) 유효한 답변이 이깁니다.



답변

, 148 135 133 138 바이트

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

바이트로 계산됩니다 CP-1252 그래서, ·각 바이트 하나입니다. 이것은 C 코드가 단일 명령 행 인수로 예상되며, 실제 명령 행에서는 많은 이스케이프 시퀀스를 사용해야합니다. 온라인 에서 사용해보십시오!

약간 ungolfed 버전의 설명

이 코드는 몇 가지 트릭으로 많은 대체 작업을 수행합니다.

백 슬래시 연속

우리는 RM문자 그대로 모든 문자열

"\
"

즉, 백 슬래시 다음에 개행 문자가옵니다.

문자열과 문자 리터럴

콜백 함수와 함께 정규식 대체를 사용합니다.

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

{
 lPBa
 C(++i + 191)
}

정규식은 작은 따옴표 나 큰 따옴표 .*?와 일치하며 가능한 한 적은 수의 0 개 이상의 문자와 일치하는 욕심 이 없습니다. 우리는 이전 문자가 백 슬래시가 아니 었음을 확인하기 위해 부정적인 견해를 가지고 있습니다. 그런 다음 짝수의 백 슬래시와 시작 구분 기호를 다시 일치시킵니다.

콜백 함수는 문자열 / 문자 리터럴을 가져 와서 목록 뒤로 푸시합니다 l. 그런 다음 문자 코드 192 ( À)로 시작 하고 각 리터럴을 바꾸면 증가 하는 문자를 반환합니다 . 따라서 코드는 다음과 같이 변환됩니다.

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

printf(À, Á);

이러한 대체 문자는 소스 코드에서 발생하지 않는다는 것을 보장하므로 나중에 다시 대체 문자를 대체 할 수 있습니다.

코멘트

`//.*`

x

정규식 //은 개행까지 모든 것을 더하고 다음과 같이 바꿉니다.x (빈 문자열로 사전 설정)으로 .

전 처리기 지시문

`#.*`

_WR'¶

파운드 기호로 시작하는 개행 문자 이외의 문자를 줄 바꿈합니다 .

제거해서는 안되는 공간

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

{
 a R w '·
}

여기에 많은 일이 있습니다. 첫 번째 부분은 대체 할이 정규식 목록을 생성합니다.

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

예를 들어 e in 과 일치하는 lookaheads 사용에 유의하십시오 define P printf. 이렇게하면이 경기는을 소비하지 않으므로 P다음 경기에서 사용할 수 있습니다.

함수를 목록에 매핑하여이 정규 표현식 목록을 생성합니다.

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

함수는 이것을 각 요소에 대해 수행합니다.

(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

정규식이 있으면 해당 콜백 함수로 해당 어커런스를 대체합니다.

{aRw'·}

각 일치하는 공백을으로 대체합니다 ·.

공백 제거 및 정리

[w `¶+` '·]

[x n s]

세 개의 연속 된 대체 w는 빈 문자열 ( x), 줄 바꿈 및 공백으로 나머지 공백 ( )을 대체 ·합니다.

문자열 및 문자 리터럴의 대체

C(192+,#l)

l

문자를 가져 와서 192 + range(len(l))문자로 변환하여 리터럴의 대체로 사용한 모든 문자 목록을 구성합니다 . 그런 다음 이들 각각을 관련 리터럴로 대체 할 수 있습니다 l.

그리고 그게 다야! 결과 문자열이 자동 인쇄됩니다.


답변

하스켈 , 327 360 418 394 바이트

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

온라인으로 사용해보십시오!

이것은 쓰는 재미가 많았습니다! 먼저 f함수가 와서 줄 끝의 모든 백 슬래시를 제거한 다음 줄 lines바꿈의 문자열 목록으로 나눕니다. 그런 다음 많은 함수를 라인에 매핑하고 다시 연결합니다. 이러한 기능 : 왼쪽 (공백을 제거 t) 및 오른쪽 ( 하다 ); 주석을 제거 할뿐만 아니라 문자열과 문자 리터럴을 무시하고 중간에서 공백을 제거합니다 . 마지막으로 줄이 #으로 시작하면 줄 바꿈 문자를 끝에 추가합니다. 모든 줄을 다시 연결 한 후 # 문자를 찾아서 줄 바꿈이 앞에 오도록합니다.r.t.rrreversewg

w조금 복잡해서 더 설명하겠습니다. 나는 w문자열 리터럴이 아니기 때문에 이것이 “//” 인지 확인하기 때문에 이것이 주석이라는 것을 알고 있으므로 나머지 줄을 삭제합니다. 다음으로 head가 문자열 또는 문자 리터럴의 구분 기호인지 확인합니다. 그것이 앞에 붙고 l문자를 통해 실행 되는 배턴을 통과 n하면 짝수의 연속 슬래시 가 있었으면 “탈출”상태를 추적합니다 . 때 l구분 기호를 감지하고 탈출 상태가 아닌 그것의 지휘봉 다시 전달w 하기 때문에 리터럴 후 공백을 제거하기 위해 트리밍, w예상하는가에 대한 첫 번째 문자 공백 수 없습니다. 언제w꼬리에서 공백을 찾기 위해 span을 사용하는 구분 기호를 찾지 않습니다. 존재하는 경우 주위의 문자가 접촉 할 수 없는지 확인하고 공백이 있으면 삽입합니다. 그런 다음 공백이 끝난 후에 반복됩니다. 공백이 없으면 공백이 삽입되지 않고 계속 이동합니다.

편집 : 내 프로그램의 버그를 지적하여 실제로 그것을 단축시키는 방법을 이끌어 낸 @DLosc에게 많은 감사드립니다! 패턴 매칭을위한 만세!

EDIT2 : 나는 사양을 읽지 못한 바보입니다! 그것을 지적 해 주셔서 다시 DLosc에게 감사드립니다!

EDIT3 : 그냥 돌아 서서 몇 가지 성가신 타입 감소 것을 발견 e=elemChar->[Char]->Bool따라서에 침입, 어떤 이유를 e[a,q]. 형식 서명을 추가하여 올바르게 입력해야했습니다. 누구든지 내가 어떻게 고칠 수 있는지 알고 있습니까? 나는 전에 Haskell에서이 문제를 본 적이 없다.TIO

EDIT4 : 버그 @FelixPalmen의 빠른 수정이 나에게 보여주었습니다. 시간이 좀 있으면 나중에 골프를 치려고 할 수도 있습니다.

EDIT5 : @Lynn 덕분에 -24 바이트! 감사합니다! n:c:z=...정말 멋진 패턴 일치를 사용하여 전역 범위에서 항목을 할당 할 수 있다는 것을 몰랐습니다 ! 또한 운영자가 elem생각 하기를 바라는 것이 좋습니다 .


답변

C, 497 494 490 489 바이트

우리는 C를 처리하고 있으므로 C를 사용하여 해봅시다 ! 함수 f()는 char 포인터에서 입력을 가져 p오고 pointer 로 출력 q하고 입력이 ASCII 인 것으로 가정합니다.

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

우리는 파일이 잘 구성되어 있다고 가정합니다-문자열과 문자 리터럴이 닫히고 마지막 줄에 주석이 있으면 닫을 줄 바꿈이 있어야합니다.

설명

프리 골프 버전은 약간 더 읽기 쉬워서 두렵습니다.

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

테일 재귀에 의해 상태 머신을 구현합니다. 도우미 매크로와 변수는

  • O대한 O utput
  • RR 로 입력 EADr
  • Vv 식별자 식별자 문자 를 결정하기 위해 (부터 !isalnum('_'))
  • pq-설명 된대로 I / O 포인터
  • r– 마지막 문자가 될 수 r에 EAD
  • s이야 aved 최근의 공백이 아닌 문자를
  • tt의 AG에 처리기 지시문에서 작업 할 때

우리주는

  • a() -일반 C 코드
  • b() -문자열 리터럴
  • c() -의견
  • d() -읽은 후 정상적인 C 코드 r
  • e() -탈출 순서
  • f() -초기 상태 (주 기능)
  • g() -공백으로
  • h()-공백으로- g()또는i()
  • i() -공백 직후-공백 문자를 삽입해야합니까?
  • j() -초기 공백-공백 문자를 삽입하지 마십시오

테스트 프로그램

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

이것은 생산

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();}}}

한정

이것은 다음과 같은 정의를 위반합니다.

#define A (x)

확장과 이름을 구분하는 공백을 제거하여

#define A(x)

완전히 다른 의미로 이 경우에는 테스트 세트가 없으므로 다루지 않겠습니다.

다중 패스 인플레 이스 변환으로 더 짧은 버전을 제작할 수있을 것으로 생각됩니다. 다음 주에 시도해 볼 수 있습니다.


답변

C,  705   663  640 바이트

40 바이트 골프를위한 @ Zacharý와 23 바이트 골프를위한 @Nahuel Fouilleul에게 감사드립니다!

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

온라인으로 사용해보십시오!


답변

Perl 5, 250 + 3 (-00n) , 167 + 1 (-p) 바이트

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

온라인으로 사용해보십시오


답변

파이썬 2 , 479 456 445 434 502 497 바이트

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'++ -- /*']

온라인으로 사용해보십시오!

편집 : 고정 포함하는 - -, + +/ *


답변