배경
내를 들어 코드 골프 C에 제출, 내가 처리 도구가 필요합니다. 다른 많은 언어들에서와 같이, 공백은 대부분 C 소스와 관련이 없지만 (항상 그런 것은 아닙니다!) 여전히 인간에게 코드를 훨씬 더 이해하기 쉽게 만듭니다. 단일 중복 공백이없는 완전 골프 C 프로그램은 거의 읽을 수없는 경우가 많습니다.
따라서 공백과 때로는 주석을 포함하여 코드 골프 제출을 위해 코드를 C로 작성하고 싶습니다 . 그래서 프로그램은 작성하는 동안 이해하기 쉬운 구조를 유지합니다. 마지막 단계는 모든 주석과 중복 공백을 제거하는 것입니다. 이것은 인턴 컴퓨터 프로그램 이 실제로 수행해야하는 지루하고 생각이없는 작업입니다 .
직무
다음 규칙에 따라 일부 “골프 된”C 소스에서 주석 및 중복 공백을 제거하는 프로그램 또는 기능을 작성하십시오.
\
줄의 맨 마지막 문자로 (백 슬래시)는 인 라인을 계속 . 이것을 찾으면 다음 행을 동일한 논리 행의 일부로 취급해야합니다 (예를 들어, 다른 작업을 수행하기 전에\
및 다음\n
(개행)을 완전히 제거 할 수 있음 )- 주석은로 시작하는 한 줄 형식 만 사용합니다
//
. 따라서 제거하기//
위해 문자열 리터럴 외부에서 발생 하는 모든 논리 행을 무시합니다 (아래 참조). - 공백 문자는
(공백),
\t
(탭) 및\n
(개행 문자이므로 논리 행의 끝)입니다. -
일련의 공백을 찾으면 공백이 아닌 문자를 검사하십시오. 만약
- 둘 다 영숫자 또는 밑줄 (범위
[a-zA-Z0-9_]
) 또는 - 둘 다
+
또는 - 둘 다
-
또는 - 앞에
/
오는 것은 있고 다음 것은*
그런 다음 시퀀스를 단일 공백 (
) 문자 로 바꾸십시오 .
그렇지 않으면 시퀀스를 완전히 제거하십시오.
이 규칙에는 몇 가지 예외가 있습니다 .
- 프리 프로세서 지시문 은 출력에서 고유 한 행에 나타나야합니다. 전 처리기 지시문은로 시작하는 줄입니다
#
. - 문자열 리터럴 또는 문자 리터럴 안에서 공백을 제거해서는 안됩니다. 모든
"
(큰 따옴표) /'
직접 백 슬래시의 홀수 덧붙일되지 않는다 (따옴표)는 (\
)를 시작 또는 끝 문자열 문자 / 문자 리터럴 . 문자열 및 문자 리터럴은 시작된 줄과 동일한 줄에서 끝나는 것이 보장됩니다. 문자열 리터럴 과 문자 리터럴은 소위, 중첩 될 수 없습니다'
돌며 문자열 리터럴 뿐만 아니라"
, 안쪽 문자 그대로 어떤 특별한 의미가 없습니다.
- 둘 다 영숫자 또는 밑줄 (범위
I / O 사양
입력 및 출력은 개행 문자를 포함하는 문자 시퀀스 (문자열)이거나 개행 문자를 포함하지 않는 문자열의 배열 / 목록이어야합니다. 배열 / 목록을 사용하도록 선택한 경우 각 요소는 한 줄을 나타내므로 각 요소 뒤에 줄 바꿈이 내재 됩니다.
입력이 유효한 C 프로그램 소스 코드라고 가정 할 수 있습니다. 이것은 또한 인쇄 가능한 ASCII 문자, 탭 및 줄 바꿈 만 포함한다는 것을 의미합니다. 잘못된 입력에 대해 정의되지 않은 동작이 허용됩니다.
선행 / 후행 공백 / 빈 줄 은 허용되지 않습니다 .
테스트 사례
-
입력
main() { printf("Hello, World!"); // hi }
산출
main(){printf("Hello, World!");}
-
입력
#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));}
-
입력
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));}
-
입력
x; #include <stdio.h> int main() { puts("hello // there"); }
산출
x; #include<stdio.h> int main(){puts("hello // there");}
-
입력 (실제 예제)
// 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();}}}
이것은 code-golf 이므로 가장 짧은 (바이트 단위) 유효한 답변이 이깁니다.
답변
핍 , 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.r
r
reverse
w
g
w
조금 복잡해서 더 설명하겠습니다. 나는 w
문자열 리터럴이 아니기 때문에 이것이 “//” 인지 확인하기 때문에 이것이 주석이라는 것을 알고 있으므로 나머지 줄을 삭제합니다. 다음으로 head가 문자열 또는 문자 리터럴의 구분 기호인지 확인합니다. 그것이 앞에 붙고 l
문자를 통해 실행 되는 배턴을 통과 n
하면 짝수의 연속 슬래시 가 있었으면 “탈출”상태를 추적합니다 . 때 l
구분 기호를 감지하고 탈출 상태가 아닌 그것의 지휘봉 다시 전달w
하기 때문에 리터럴 후 공백을 제거하기 위해 트리밍, w
예상하는가에 대한 첫 번째 문자 공백 수 없습니다. 언제w
꼬리에서 공백을 찾기 위해 span을 사용하는 구분 기호를 찾지 않습니다. 존재하는 경우 주위의 문자가 접촉 할 수 없는지 확인하고 공백이 있으면 삽입합니다. 그런 다음 공백이 끝난 후에 반복됩니다. 공백이 없으면 공백이 삽입되지 않고 계속 이동합니다.
편집 : 내 프로그램의 버그를 지적하여 실제로 그것을 단축시키는 방법을 이끌어 낸 @DLosc에게 많은 감사드립니다! 패턴 매칭을위한 만세!
EDIT2 : 나는 사양을 읽지 못한 바보입니다! 그것을 지적 해 주셔서 다시 DLosc에게 감사드립니다!
EDIT3 : 그냥 돌아 서서 몇 가지 성가신 타입 감소 것을 발견 e=elem
에 Char->[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 utputR
행 R 로 입력 EADr
V
v 식별자 식별자 문자 를 결정하기 위해 (부터!isalnum('_')
)p
및q
-설명 된대로 I / O 포인터r
– 마지막 문자가 될 수 r에 EADs
– 이야 aved 최근의 공백이 아닌 문자를t
– t의 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'++ -- /*']
편집 : 고정 포함하는 - -
, + +
및/ *