将大括号转换为右手括号(Sad Brace)


26

右括号是一种代码括弧式,其中花括号和分号都对齐到文件右侧的单个点。

示例图片去这里

通常,出于多种原因,这被认为是不好的做法。

挑战

通过任何方法获取多行字符串,并将其花括号样式转换为Right Hand Brace。

对于这个挑战,您只需要它就可以在Java代码上工作,但是,从理论上讲,它应该可以在使用花括号和分号的任何代码上工作。

您必须{};连续抓取所有字符,它们之间必须有任意空格。例如。}}; } }\n\t\t}和,并通过使用空格将它们排列在文件的右侧。

例如:

a {
b;
{c

应该成为

a {
b ;{
c

或者,更抽象地说,将所有空格从所有字符的左侧推{};到右侧。

线的缩进应另作保留。字符移动后仅包含空格的行{};可以有选择地删除。

例如:

a{
    b{
        c;
    }
}
d;

可能成为

a        {
    b    {
        c;}}
d        ;

要么

a        {
    b    {
        c;}}


d        ;

向右推是指所有{};字符对齐到不短于最长行的点。之后的任何空间都可以接受。

因此,以下所有内容都是可以接受的:

a {
bc;

a  {
bc ;

a   {
bc  ;

等等...

任何代码中{};的行都可能在其他非空白字符之间包含字符,这种情况下没有必要进行处理,尽管如果您愿意,则应将它们保留在原处。行也可能根本不包含任何{};字符,因此应正确处理。如下图所示。

a {
b ;
c
d }

因为我们不希望Code Review看到我们正在做的可怕的事情,所以您需要使代码尽可能的小。

例子/测试用例

通用Java

public class HelloWorld{
       public static void main(String[] args){
           System.out.println("Hello, World!");
       }
}

变成...

public class HelloWorld                        {
    public static void main(String[] args)     {
        System.out.println("Hello, World!")    ;}}

图片本身

public class Permuter{
    private static void permute(int n, char[] a){
        if (n == 0){
            System.out.println(String.valueOf(a));
        }else{
            for (int i=0; i<= n; i++){
                permute(n-1, a);
                swap(a, n % 2 == 0 ? i : 0, n);
            }
        }
    }
    private static void swap(char[] a, int i, int j){
        char saved = a[i];
        a[i] = a[j];
        a[j] = saved;
    }
}

变成...

public class Permuter                                {
    private static void permute(int n, char[] a)     {
        if (n == 0)                                  {
            System.out.println(String.valueOf(a))    ;}
        else                                         {
            for (int i=0; i<= n; i++)                {
                permute(n-1, a)                      ;
                swap(a, n % 2 == 0 ? i : 0, n)       ;}}}
    private static void swap(char[] a, int i, int j) {
        char saved = a[i]                            ;
        a[i] = a[j]                                  ;
        a[j] = saved                                 ;}}

不太完美的通用Python

为了对比

def Main():
    print("Hello, World!");

Main();

变成...

def Main():
    print("Hello, World!")    ;
Main()                        ;

笔记

  • 适用标准漏洞
  • 适用标准IO
  • 这是,所以最短的程序以字节为单位!
  • 我不对与右手括号样式编程相关的损害负责
  • 玩得开心!

编辑笔记

我改写了挑战细节,希望我不会破坏任何人对规则的看法,向您保证这不是故意的。这应该是一个更清晰,更少冲突的规范。


带有多个分号的行的结论是什么?像int a=0;System.out.println(a);
价值墨水

2
如果我们不需要像示例图像中那样处理循环,那可能不是挑战的最佳图像?
丹尼斯

1
看起来问题中的图像来自此示例此后续操作具有更复杂的示例
Ray Toal

2
可以更清楚地表明;{},如果字符位于单独的行中,则希望它们被收集起来(仅从示例中可以清楚地看到,而不是从规则中可以看出,实际上,如果一行包含\t}保留缩进,则意味着}向上移动)上一行的内容)
Chris H

2
天哪,请告诉我,实际上没有人实际上对像Java ._这样的冗长语言执行此操作。
魔术章鱼缸

Answers:


5

V + Bash实用程序,64 62 61 60 62字节

@DJMcMayhem将ex命令放在一起节省了1个字节

:se ve=all|%!wc -L
y$uò/^ *<93>[{};]
xk$pòò/<84> {};][{};]«$
lDî^R0|p

^R<C-r>0x12)和<84>is 0x84<94>is 的字符文字0x94

wc -L可在大多数基于* nix的系统上运行,但不适用于macOS。对于macOS,gwc -L 如果还没有使用brew,则必须在获取coreutils之后执行。

在线尝试!(Java)

在线尝试!(蟒蛇)

在线尝试!(再次Java)

这将保留所有空白行,并且不处理制表符,仅处理空格。

十六进制转储:

00000000: 3a73 6520 7665 3d61 6c6c 7c25 2177 6320  :se ve=all|%!wc 
00000010: 2d4c 0a79 2475 f22f 5e20 2a93 5b7b 7d3b  -L.y$u./^ *.[{};
00000020: 5d0a 786b 2470 f2f2 2f84 207b 7d3b 5d5b  ].xk$p../. {};][
00000030: 7b7d 3b5d ab24 0a6c 44ee 1230 7c70       {};].$.lD..0|p

说明

首先,我们需要能够将光标移动到缓冲区中的任何位置,因此我们使用

:se ve=all|...

我们使用另一个ex命令将其链接 |

我们需要获取输入中最长线的长度。这可以通过shell命令来完成wc -L

       ...|%!wc -L

这会用的结果覆盖当前缓冲区(包含输入)wc -L。它给出类似以下内容的输出:

            42

和光标的土地上442。然后,我们使用y$以下命令复制此数字:将光标位置的文本拖到行尾。这可以方便地将该编号存储在寄存器中0。但是稍后会更多。输入已替换为该数字,因此要还原,我们使用undo。

现在说输入看起来像这样:

public class HelloWorld{
    public static void main(String[] args){
        System.out.println("Hello, World!");
    }
}

我们需要将大括号}从缓冲区的末尾移动到println语句之后。

ò                  " recursively do this until a breaking error:
 /^ *<93>[{};]     "   this compressed regex becomes /^ *\zs[{};]
                   "   this finds any character from `{};` after leading spaces
                   "   the cursor then goes to the `{};`

x                  "   delete character
 k$                "   go to the end of the line above
   p               "   and paste
    ò

如果找不到正则表达式,则会发生中断错误并中断由引起的递归ò

现在是该程序的主要部分,按照问题中的说明移动所有花括号和分号并对齐它们。

ò                  " starts recursion
 /<84> {};][{};]«$ "   compressed form of [^ {};][{};]\+$
                   "   finds a sequence of `{};`s at the end of the line with a non-`{};` char to preceding it
 l                 "   move the cursor 1 to the right (since we were on the non-`{};` char now)
  D                "   delete everything from this position to the end of line
                   "   the deleted text contains `{};`
   î               "   execute as normal commands:
    ^R0            "   contains what's in register `0`, ie the length of the longest line
       |           "   now go to the column specified by that number
        p          "   and paste the contents 
                   " implicit ending `ò`

同样,由于在缓冲区中找不到正则表达式时引起的中断错误,此递归将停止。

编辑

  • 使用D而不是d$(我什至不知道为什么我首先错过了它)
  • 压缩[^(在正则表达式中)为<84>
  • 通过使用\zs(将其压缩为<93>)并删除了$in 来修复错误$xk$pò
  • 删除了无用的换行符
  • 更改了正则表达式以使提交符合新规则并获得了2个字节

如果将您的ex命令一起加入,则可以节省一个字节:se ve=all|%!wc -L
DJMcMayhem

@DJMcMayhem谢谢,蒂尔
Kritixi Lithos

4

红宝石,100 114 108个字节

读取文件名作为命令行参数。如果没有提供文件名,它将从STDIN读取。不处理标签。

在线尝试!

f=$<.read.gsub(/[\s;{}]*$/){$&.tr"
 ",''}
$><<f.gsub(/(.*?)([;{}]+)$/){$1.ljust(f.lines.map(&:size).max)+$2}



不适用于此功能
Pavel

@Pavel感谢您让我知道。在放入文件后,我看到的两个问题是A.缩进catch语句和B.在代码的最长行上缩进太多的分号。我想我只知道我需要解决的问题,请给我几秒钟。(此外,我更新了规范以提及它不能处理选项卡,并且您的文件具有选项卡。)
Value Ink

有标签吗?我只是找到并替换了它,所以做了0处更改。
帕维尔

3

Perl,90个字节

88个字节的代码+ -p0标志。

\@a[y///c]for/.*/g;s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gme;1while s/ *
 *([{};]+)$/$1/m

在线尝试!

简短说明:
\@a[y///c]for/.*/g;计算最长行的长度:对于每行,它定义数组index处的元素y///c(即行的大小)@a。最后,最大索引@a(即的大小@a)是最长行的大小。
s/(.*?)\K[{};]$/$"x(@a-$1=~y%%%c).$&/gme{};字符放在行尾。
1while s/ *\n *([{};]+)$/$1/mmake使空行上的括号在上面的行上。

由于@primo从我所部分“偷”我的代码开始从这里算最长行的长度。


如果括号之前只有空格,则括号必须回到上面的行,此答案
无法解决

@KritixiLithos确实,在改写挑战之前看起来还不错(从我从挑战和评论中都可以理解)。无论如何,现在它已修复(我已经在答案中写了代码,以防您不注意)。
达达

1

Python 2:228字节

import re
g=re.search
def b(a):
    s,l="",a.split('\n')
    r=max([len(k)for k in l]) 
    for k in l:
        n,m=g('[;}{]',k),g('[\w]',k)
        if n:n=n.start()
        if m:m=m.start()
        if n>m and m!=None:s+="\n"+k[:n]+" "*(r-n)
        s+=k[n:]
    print s

太长了。当我意识到;{}需要在上一行的结尾处加上lone时,我可能应该从头开始。
克里斯·H

1

堆积,133字节

'\s+([;{}])' '$1'repl lines{!n'[\s;{}]+$'match''join:n\'$'+del\,}"!tr:$size"!$MAXmap@k{e i:e[' 'k i#rpad]"!}map tr[' 'join]map'
'join

在线尝试!我可能会对此深思熟虑...但是。我明天再看。一些不错的提示:

  1. "!通常可以用来代替map,节省一个或两个字节,这取决于下一个标记是否以单词开头。但是,只能在要映射数组的每个原子时使用它。它类似于一张深地图。
  2. 带引号的函数后不需要空格,所以$MAXmap等价于$MAX map,而后者又等价于[MAX] map。(将每个数组映射到其最大元素。)

1

JavaScript(ES提案),139 121字节

f=
s=>s.replace(/^(.*?)\s*(([;{}]\s*)+)$/gm,(_,t,u)=>t.padEnd(Math.max(...s.split`
`.map(s=>s.length)))+u.replace(/\s/g,``))
<textarea rows=10 cols=40 oninput=o.textContent=f(this.value)></textarea><pre id=o>

需要Firefox 48 / Chrome 57 / Opera 44 / Safari 10 / Edge 15 padEnd。编辑:由于@ValueInk,节省了18个字节。


s.replace(r,`$1`)计算线长时,您真的需要运行吗?任何数量的合理右填充都应足够,因此分号和括号来计算行长度应该很好。
价值墨水

0

PHP,201个 194 185 172 167字节

foreach($f=file(f)as$s)$x=max($x,strlen($a[]=rtrim($s,"{} ;
")));foreach($a as$i=>$c)echo str_pad($c,""<$c|!$i?$x:0),trim(substr($f[$i],strlen($c))),"
"[""==$a[$i+1]];

从文件f获取输入;假定单字节换行符且没有制表符;保留空白行。

  • +2个字节用于分隔空格:附加+1到第二个str_pad参数。
  • 如果保证没有代码行包含单个字节,则为-6个字节0
    删除""<并替换""==!

分解

foreach($f=file(f)as$s)             // loop through file
    $x=max($x,strlen(                   // 3. set $x to maximum code length
        $a[]=                           // 2. append to array $a
            rtrim($s,"{} ;\n")          // 1. strip trailing whitespace and braces
    ));
foreach($a as$i=>$c)echo            // loop through $a
    str_pad($c,                         // 1. print code:
        !$i|""<$c                       // if first line or not empty
        ?$x                             // then padded to length $x
        :0                              // else unpadded (= print nothing)
    ),
    trim(substr($f[$i],strlen($c))),    // 2. print braces
    "\n"[""==$a[$i+1]]                  // 3. if next line has code, print newline
;

您确定需要{}在正则表达式中使用大括号吗?
Kritixi Lithos'2

@KritixiLithos可能不是;但无论如何,我发现了一种更短的方法。
泰特斯(Titus),

0

爪哇8,312个 305字节

s->{String t="([;{}]+)",z[],r="",a;s=s.replaceAll(t+"[\\s\\n]*","$1").replaceAll(t,"$1\n");int m=0,l;for(String q:s.split("\n"))m=m>(l=q.length())?m:l;for(String q:s.split("\n")){z=q.split("((?<="+t+")|(?="+t+"))",2);for(a="",l=0;l++<m-z[0].length();a+=" ");r+=z[0]+a+(z.length>1?z[1]:"")+"\n";}return r;}

说明:

在这里尝试。

s->{                                  // Method with String parameter and String return-type
  String t="([;{}]+)",                //  Temp regex-String we use multiple times
    z[],a,                            //  Temp String-array and temp String
    r="";                             //  Result-String
  s=s.replaceAll(t+"[\\s\\n]*","$1")  //  We replace all ;{} in the input with zero or more whitespaces/newlines to just ;{}
     .replaceAll(t,"$1\n");           //  and then add a single newline after each group of ;{}
  int m=0,l;                          //  Two temp integers
  for(String q:s.split("\n"))         //  Loop (1) over the lines
    m=m>(l=q.length())?m:l;           //   To determine the longest line
                                      //  End of loop (1)
  for(String q:s.split("\n")){        //  Loop (2) over the lines again
    z=q.split("((?<="+t+")|(?="+t+"))",2);
                                      //   Split on groups of ;{}, but keep them in the array
    for(a="",l=0;l++<m-z[0].length();a+=" "); 
                                      //   Amount of spaces we should add
    r+=z[0]+a+(z.length>1?z[1]:"")+"\n"; 
                                      //   Append this line to the result-String
  }                                   //  End of loop (2)
  return r;                           //  Return the result-String
}                                     // End of method

嘿,我正在评论这个答案,但它适用于您的许多其他答案。 目前,我们需要lambda参数在Java中具有类型
内森·梅里尔

1
@NathanMerrill担心审判的日子会到来。Jk,从现在开始将其添加,我已经编辑了答案,谢谢。;)
Kevin Cruijssen
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.