打我的“预高尔夫球” C


12

背景

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

这是,因此最短(以字节为单位)的有效答案将获胜。



Answers:


4

PIP148个 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代码作为单个命令行参数,(在实际命令行上)将需要使用大量转义序列。在线试用要容易得多

略微偏离版本的说明

该代码执行了许多替换操作,并带有一些技巧。

反斜杠继续

我们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 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

就是这样!结果字符串将自动打印。


太好了,我印象深刻(+1)!包括//字符串文字内绝对是一个测试用例是一个好主意,我会添加一个明天。
菲利克斯·帕尔曼

嗯...现在我也在这里发现了一个细微的错误 ...
Felix Palmen

我将在14天(下周结束)之后选择一个赢家,如果您有时间解决此错误,则您的解决方案将是第一个候选人。目前,您的分数是最低的:)
Felix Palmen

1
@FelixPalmen固定!
DLosc

7

Haskell中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.rwhere rreverse)去除空格;从中间删除空格,忽略字符串和字符文字,并删除注释(w); 最后,如果该行以#开头,则在末尾添加一个换行符。将所有行连接在一起后,g查找#个字符,并确保在它们前面加上换行符。

w有点复杂,所以我将进一步解释。首先,我检查“ //”,因为w我知道我不在字符串文字中,我知道这是注释,因此我删除了该行的其余部分。接下来,我检查head是否是字符串或字符文字的定界符。如果它是我的前缀,然后将传递l字符的警棍传递到该字符,则跟踪“转义”状态,n如果连续的斜杠数为偶数,则该状态为true。当l检测到分隔符并且不处于转义状态时,它将警棍传递回w,进行修整以消除文字后的空白,因为w期望第一个字符不是空白。什么时候w找不到分隔符,而是使用span查找尾部的空格。如果有,它将检查周围的字符是否无法接触,如果可以,请插入空格。然后,它在空白结束后再次出现。如果没有空格,则不会插入任何空格,并且空格会继续移动。

编辑:非常感谢@DLosc指出我程序中的错误,该错误实际上导致我也缩短了它!模式匹配的万岁!

EDIT2:我是个白痴,还没看完规格书!再次感谢DLosc指出这一点!

EDIT3:只是注意到一些令人讨厌的类型缩减东西由于某种原因而变成e=elemChar->[Char]->Bool,因此中断了e[a,q]。我必须添加类型签名以强制其正确。有谁知道我该如何解决?我以前在Haskell从未遇到过这个问题。蒂奥

EDIT4:Bug @FelixPalmen的快速修复向我展示了。以后,我可能会尝试打高尔夫球。

EDIT5:-24个字节感谢@Lynn!谢谢!我不知道您可以使用模式匹配在全局范围内分配东西,n:c:z=...这真的很酷!让操作员elem希望的也是一个好主意,我会想到这一点。



2
您正面临可怕的单态性限制 ; 定义e x y=elem x y(甚至e x=elem x)可以解决您的问题。(我将其重命名e为运算符(!)。)
Lynn

3

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对于Ø本安输出
  • R- [R EAD输入到r
  • V来确定v alid标识符字符(因为!isalnum('_')
  • pq-I / O指针如所述
  • r-最后一个字符是- [R EAD
  • s- š AVED近期非空白字符
  • t- 牛逼在预处理指令工作时,股份公司

我们的州是

  • 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)

具有完全不同的含义。测试集中没有这种情况,因此我不会解决。

我怀疑我可以通过多次通过就地转换来制作较短的版本-我下周可以尝试。


您可以通过删除=定义末尾的来节省一个字节,并将O每次调用后的空格更改O=
扎卡里

太棒了;)关于“局限性”,另请参见我对问题本身的评论-检测到会增加太多的复杂性。
菲利克斯·帕尔姆

@Zachary -感谢-我忘了,当我改变了通用代码为ASCII特有的是O'\\'O' '双方取得的空间。
Toby Speight


2

C, 705个   663  640字节

感谢@Zacharý打高尔夫球40个字节,感谢@Nahuel Fouilleul打高尔夫球23个字节!

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

在线尝试!


可以for(;W;C++){}成为for(;W;C++);
扎卡里

从来没有要求过的@Zacharý。这是最后一步的麻烦:删除多余的空格和注释。
菲利克斯·帕尔默

我指的是他的代码,而不是挑战。
扎卡里

@Zacharý哈哈,我看到...当代码和输入是同一语言时很奇怪;)
Felix Palmen

这可以工作665个字节吗?goo.gl/E6tk8V
扎卡里

2

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/./

在线尝试


是的,我只是提出了一个非最佳解决方案。我刚刚添加了tio链接,有时间的时候我会去打高尔夫球。
Nahuel Fouilleul

当在代码之前放置预处理器指令时,就像在测试用例中一样,它们自己一行,但是如果需要,我会添加更改
Nahuel Fouilleul

1
固定请参阅更新
纳乌艾尔乌Fouilleul

0

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

在线尝试!

编辑:固定为包括- -+ +/ *

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.