Lý lịch
Đối với bài nộp mã golf của tôi bằng C, tôi cần một công cụ xử lý. Giống như trong nhiều ngôn ngữ khác, khoảng trắng hầu như không liên quan đến nguồn C (nhưng không phải lúc nào cũng vậy!) - vẫn làm cho mã dễ hiểu hơn nhiều đối với con người. Một chương trình C được đánh gôn hoàn toàn không chứa một khoảng trắng dự phòng thường không thể đọc được.
Do đó, tôi thích viết mã của mình bằng C để gửi mã golf bao gồm cả khoảng trắng và đôi khi là các nhận xét, vì vậy chương trình giữ cấu trúc dễ hiểu trong khi viết. Bước cuối cùng là xóa tất cả các bình luận và khoảng trắng thừa. Đây là một công việc tẻ nhạt và không cần suy nghĩ mà thực sự nên được thực hiện bởi một chương trình máy tính.
Bài tập
Viết chương trình hoặc chức năng loại bỏ các bình luận và khoảng trắng dư thừa từ một số nguồn C "tiền golf" theo các quy tắc sau:
- Một
\
(dấu gạch chéo ngược) là ký tự cuối cùng trong một dòng là một dòng tiếp tục . Nếu bạn tìm thấy điều này, bạn phải coi dòng sau là một phần của cùng một dòng logic (ví dụ bạn có thể loại bỏ hoàn toàn\
và dòng sau\n
(dòng mới) trước khi làm bất cứ điều gì khác) - Nhận xét sẽ chỉ sử dụng định dạng một dòng, bắt đầu bằng
//
. Vì vậy, để loại bỏ chúng, bạn bỏ qua phần còn lại của dòng logic bất cứ nơi nào bạn gặp//
bên ngoài một chuỗi ký tự (xem bên dưới). - Các ký tự khoảng trắng là
(dấu cách),
\t
(tab) và\n
(dòng mới, vì vậy ở đây kết thúc một dòng logic). Khi bạn tìm thấy một chuỗi các khoảng trắng, hãy kiểm tra các ký tự không phải khoảng trắng xung quanh nó. Nếu
- cả hai đều là chữ và số hoặc gạch dưới (phạm vi
[a-zA-Z0-9_]
) hoặc - cả hai đều
+
hoặc - cả hai đều
-
hoặc - cái trước là
/
và cái sau là*
sau đó thay thế chuỗi bằng một
ký tự dấu cách ( ).
Nếu không, loại bỏ hoàn toàn trình tự.
Quy tắc này có một số ngoại lệ :
- Các chỉ thị tiền xử lý phải xuất hiện trên các dòng riêng của chúng trong đầu ra của bạn. Một chỉ thị tiền xử lý là một dòng bắt đầu với
#
. - Bên trong một chuỗi ký tự hoặc ký tự , bạn không nên xóa bất kỳ khoảng trắng nào. Bất kỳ
"
(trích dẫn kép) /'
(trích dẫn đơn) không được đặt trực tiếp trước một số dấu gạch chéo ngược (\
) bắt đầu hoặc kết thúc một chuỗi ký tự / ký tự . Bạn được đảm bảo rằng chuỗi ký tự và ký tự kết thúc trên cùng một dòng họ đã bắt đầu. chuỗi ký tự và ký tự ký tự không thể được lồng nhau, do đó,'
bên trong một chuỗi ký tự , cũng như"
bên trong một ký tự chữ không có bất kỳ ý nghĩa đặc biệt nào.
- cả hai đều là chữ và số hoặc gạch dưới (phạm vi
Đặc tả I / O
Đầu vào và đầu ra phải là chuỗi ký tự (chuỗi) bao gồm các ký tự dòng mới hoặc mảng / danh sách các chuỗi không chứa ký tự dòng mới. Nếu bạn chọn sử dụng mảng / danh sách, mỗi phần tử đại diện cho một dòng, vì vậy các dòng mới sẽ ẩn sau mỗi phần tử.
Bạn có thể giả sử đầu vào là mã nguồn chương trình C hợp lệ. Điều này cũng có nghĩa là nó chỉ chứa các ký tự, tab và dòng mới ASCII có thể in được. Hành vi không xác định trên đầu vào không đúng định dạng được cho phép.
Hàng đầu và dấu khoảng trắng / dòng sản phẩm nào đang không được phép .
Các trường hợp thử nghiệm
đầu vào
main() { printf("Hello, World!"); // hi }
đầu ra
main(){printf("Hello, World!");}
đầu vào
#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)); }
đầu ra
#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));}
đầu vào
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)); }
đầu ra
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));}
đầu vào
x; #include <stdio.h> int main() { puts("hello // there"); }
đầu ra
x; #include<stdio.h> int main(){puts("hello // there");}
đầu vào (một ví dụ thực tế)
// 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(); } } }
đầu ra
#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();}}}
Đây là mã golf , vì vậy câu trả lời hợp lệ ngắn nhất (tính bằng byte) sẽ thắng.