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