C,308或339个字节
#include <ctype.h>
#define p putchar
f(s,e,c,i,l)char*s,*e,*c;{i=1,l=40;if(*s++==l){p(l);for(c=s;i;i+=*c==l,i-=*c==41,i+*c==45&&p(44),c++);p(41);}for(;s<e;s=c){for(i=0;isdigit(*s);s+=*s==44)for(i&&p(32),i=1;isdigit(*s);s++)p(*s);*s==l&&p(l);for(c=s,i=1;++c,c<=e&&i;i+=*c==l)i-=*c==41;f(s,c-1);*s==l&&p(41);}}
#define g(x) f(x, x+strlen(x))
308或339个字节,具体取决于是否允许将指针传递到输入字符串的末尾;最后一行仅用于允许直接传递字符串文字而不必计算其长度。
说明
一个非常简单的算法。它计算当前深度处的逗号数量,将它们打印为元组构造函数,然后递归地处理元组的参数,然后进行转义(数字之间的空格,括号之间的嵌套元组)。
#include <stdio.h>
#include <ctype.h>
typedef enum { false, true } bool;
void tup2ptsfree(char *s, char *e)
{
int depth;
char *c;
if (*s++ == '(') { /* If we are at the start of a tuple, write tuple function `(,,,)` (Otherwise, we are at a closing bracket or a comma) */
putchar('(');
/* do the search for comma's */
c=s; /* probe without moving the original pointer */
for (depth=1; depth != 0; c++) {
if (*c == '(') depth++;
if (*c == ')') depth--;
if (*c == ',' && depth == 1) putchar(','); /* We have found a comma at the right depth, print it */
}
putchar(')');
}
while (s < e) { /* The last character is always ')', we can ignore it and save a character. */
bool wroteNumber;
for (wroteNumber=false; isdigit(*s); wroteNumber = true) {
if (wroteNumber) p(' '); /* If this is not the first number we are writing, add a space */
while (isdigit(*s)) putchar(*s++); /* Prints the entire number */
if (*s == ',') s++; /* We found a ',' instead of a ')', so there might be more numbers following */
}
/* Add escaping parenthesis if we are expanding a tuple (Using a small if statement instead of a large branch to prevent doing the same thing twice, since the rest of the code is essentially the same for both cases). */
if (*s == '(') putchar('(');
/* Find a matching ')'... */
c=s+1;
for (depth=1; c <= e && depth != 0; c++) {
if (*c == '(') depth++;
if (*c == ')') depth--;
}
/* Found one */
/* Note how we are looking for a matching paren twice, with slightly different parameters. */
/* I couldn't find a way to golf this duplication away, though it might be possible. */
/* Expand the rest of the tuple */
tup2ptsfree(s, c-1);
/* idem */
if (*s == '(') putchar(')');
/* Make the end of the last expansion the new start pointer. */
s=c;
}
}
#define h(x) tup2ptsfree(x, x+strlen(x))
测试用例及应用
#include <stdio.h>
#define ARRAYSIZE(arr) (sizeof(arr)/sizeof(*arr))
static char *examples[] = {
"(1,2)",
"(10,1)",
"(1,2,3)",
"(1,2,3,4)",
"((1,2),3)",
"(1,(2,3))",
"(1,(2,3),4)",
"((1,2),(3,4))",
"((1,(2,3)),4,(5,6))",
"((1,((2,3), 4)),5,(6,7))",
"(42,48)",
"(1,2,3,4,5,6,7)"
};
int main(void)
{
int i;
for (i=0; i < ARRAYSIZE(examples); i++) {
printf("%-32s | \"", examples[i]);
g(examples[i]); /* Test with golfed version */
printf("\"\n");
printf("%-32s | \"", examples[i]);
h(examples[i]); /* Test with original version */
printf("\"\n");
}
}