反向缩进


63

我听说,如果反向缩进代码,则代码可以更快地运行,以便编译器可以从“分支”的顶部开始像树设计模式一样对其进行处理。这会有所帮助,因为重力会加快编译代码所需的时间,并且会提高数据结构的效率。这是一个Java脚本编写示例:

            function fib(n) {
        var a = 1, b = 1;
        while (--n > 0) {
    var tmp = a;
    a = b;
    b += tmp;
    if (a === Infinity) {
return "Error!";
    }
        }
        return a;
            }

但是由于某些原因,记事本没有设置可以自动执行此操作,因此我需要一个程序来为我执行此操作。

描述

提交的内容必须以代码段作为输入,缩进缩进并输出结果代码。

这是通过以下过程完成的:

  • 将代码分成几行。每行将以零个或多个空格开头(将没有制表符)。

  • 在代码中找到所有唯一的缩进级别。例如,对于上面的示例,这将是

    0
    4
    8
    12
    
  • 反转此缩进级别列表的顺序,然后将反转的列表映射到原始列表。这很难用语言解释,但是对于示例来说,它看起来像

    0  — 12
    4  — 8
    8  — 4
    12 — 0
    
  • 将此映射应用于原始代码。在示例中,具有0-space-indentation的行将缩进12个空格,将4个空格变为8个空格,依此类推。

输入输出

可以根据需要提供输入和输出(STDIN / STDOUT,功能参数/返回值等);如果您的语言不支持多行输入(或者您只是不想这样做),则可以使用|字符来分隔行。

输入将仅包含可打印的ASCII +换行符,并且将不包含空行。

测试用例

输入:

function fib(n) {
    var a = 1, b = 1;
        while (--n > 0) {
            var tmp = a;
            a = b;
            b += tmp;
            if (a === Infinity) {
                return "Error!";
            }
        }
    return a;
}

输出:上面的示例代码。

输入:

a
  b
  c
d
   e
        f
  g
   h

输出:

        a
   b
   c
        d
  e
f
   g
  h

输入:

1
 2
  3
 2
1

输出:

  1
 2
3
 2
  1

输入:

  foo

输出:

  foo

21
其“ JavaScript”而不是“ Java脚本”:/
Optimizer

75
@Optimizer我发现我的目标是使前两段中的尽可能多的人激怒。;)
门把手

7
1!=尽可能多的人。
Optimizer

23
@JanDvorak发明了MLA风格引文的人认为这是个好主意。
Rainbolt 2014年

6
据称,它更快。让我们为其分配一个委员会,等待几年,直到我们忘记它的目的。
科纳·奥布莱恩2014年

Answers:


10

CJam,43 39 36 35字节

qN/_{_Sm0=#}%___&$_W%er]z{~S*@+>N}%

这看起来太久了。我确定我的优化不够!

这个怎么运作:

基本思想是在换行符上拆分输入,计算每行中前导空格的数量,排序并获得唯一的数字,复制该数组并反向复制,用这两个数组对原始有序数字进行音译,最后形成使用此信息的最终字符串。

最冗长的部分是弄清楚每行中有多少前导空格,因为CJam没有做到这一点的简便方法。

代码扩展:

qN/_                                      "Split the string on newline and take copy";
    {_Sm0=#}%                             "Map this code block on the copy";
     _Sm                                  "Copy the string and remove spaces from the copy";
        0=                                "Get first non space character";
          #                               "Gets its index in original string";
             ___                          "Get 3 copies of the above array";
                &$_W%                     "Get unique elements, sort, copy and reverse";
                     er                   "Transliterate unique sorted elements with";
                                          "the unique reverse sorted in the copy";
                       ]z                 "Get array of [row,
                                          " original number of leading spaces,
                                          " required number of leading spaces]";
                         {~S*@+>N}%       "For each above combination";
                          ~S*             " unwrap and get leading space string";
                             @+           " prepend to the row";
                               >          " remove original spaces";
                                N         " put newline";

并且本着问题的精神。代码的真正扩展:

                                          qN/_                                      "Split the string on newline and take copy";
                                {_Sm0=#}%                             "Map this code block on the copy";
                               _Sm                                  "Copy the string and remove spaces from the copy";
                             0=                                "Get first non space character";
                          #                               "Gets its index in original string";
                         ___                          "Get 3 copies of the above array";
                       &$_W%                     "Get unique elements, sort, copy and reverse";
                     er                   "Transliterate unique sorted elements with";
"the unique reverse sorted in the copy";
                ]z                 "Get array of [row,
" original number of leading spaces,
" required number of leading spaces]";
             {~S*@+>N}%       "For each above combination";
          ~S*             " unwrap and get leading space string";
        @+           " prepend to the row";
     >          " remove original spaces";
    N         " put newline";

感谢Martin,节省了7个字节,感谢Dennis,节省了1个字节

在这里在线尝试


1. {}#有一个错误:它返回一个整数,但是应该返回一个Long。具有讽刺意味的是,i(强制转换为整数)可以解决此问题。2.由于""#没有相同的错误,因此_Sm0=#要少一个字节。
丹尼斯2014年

@Dennis是的,该错误很奇怪。感谢您的解决方法!
Optimizer

2
扩展中的这个缩进非常容易阅读!你应该扭转它!
DLeh 2014年

13

蟒2 - 137个 131字节

i=raw_input().split('|')
f=lambda s:len(s)-len(s.lstrip())
d=sorted(set(map(f,i)))
for l in i:print' '*d[~d.index(f(l))]+l.lstrip()

接受输入,|而不是\n

说明

前三行非常简单。列出输入中的所有行,定义一个函数以告诉您字符串具有多少前导空格,并列出该函数的值的排序列表,该值随输入的每一行而出现。

最后一行更有趣。

                                 l               # string with the line
                               f(l)              # amount of leading whitespace
                       d.index(f(l))             # where it is in list of whitespace amounts
                      ~d.index(f(l))             # bitwise NOT (~n == -(n+1))
                    d[~d.index(f(l))]            # index into the list (negative = from end)
           print' '*d[~d.index(f(l))]            # print that many spaces...
           print' '*d[~d.index(f(l))]+l.lstrip() # plus everything after leading whitespace
for l in i:print' '*d[~d.index(f(l))]+l.lstrip() # do the above for every line


@frya谢谢:)
Undergroundmonorail

1
这一切在python 3中似乎都不错,它应该为您节省2个字节(为2 ()保存4 支付2 raw_
FryAmTheEggman 2014年

1
f(s)for s in i应该是map(f,i)
feersum 2014年

1
魔术:d=[];d+=set(L)是的简化版本d=sorted(set(L))
xnor 2014年

7

的JavaScript,ES6,113个103 101字节

我很确定,这至少可以打得更远一些,但是可以。

从来没有想过会有101字节的JS解决方案,胜过Python!

f=a=>(b=c=[...Set(a.match(r=/^ */gm).sort())],c.map((x,i)=>b[x]=c.slice(~i)[0]),a.replace(r,x=>b[x]))

这将创建一个名为的方法f,可以使用输入字符串进行调用。如果您使用的是最新版的Firefox,则可以使用模板字符串,并且可以调用如下方法

f(`a
  b
  c
d
   e
        f
  g
   h`)

否则,您也可以这样称呼它

f("a\n\
  b\n\
  c\n\
d\n\
   e\n\
        f\n\
  g\n\
   h")

或者,尝试以下代码段:

g=_=>O.textContent=f(D.value)

f=a=>(b=c=[...Set(a.match(r=/^ */gm).sort())],c.map((x,i)=>b[x]=c.slice(~i)[0]),a.replace(r,x=>b[x]))
<textarea id=D></textarea><button id=B onclick=g()>Inverse!</button>
<pre id=O></pre>


您可以通过将正则表达式存储为变量来保存变量的字节,因为正则表达式已被使用两次(您应该可以\s用空格字符进行替换),并x在replace函数中删除括号。
NinjaBearMonkey 2014年

@hsl gee,谢谢!我什至不知道我为什么写(x):/
Optimizer

您不需要两者bc是吗?他们只是引用相同的数组。
尼尔,2016年

5

Ruby,63个字节

->s{l=s.scan(r=/^ */).uniq.sort;s.gsub r,l.zip(l.reverse).to_h}

这定义了一个未命名的函数,该函数接受并返回一个字符串。您可以通过附加["string here"]变量或将其分配给变量,然后调用该变量来调用它。

工作原理:s.scan(r=/^ */)给出所有前导空格的列表,并存储正则表达式r供以后使用。uniq消除重复。sort...排序。

现在跳到最后,l.zip(l.reverse)给出我们要替换的成对数组。to_h将其转换为哈希,将对解释为键值对。

现在s.gsub,使用该哈希作为查找表来查找正则表达式,从而替换了正则表达式的所有匹配项(所有前导空格)。



2

Japt -R,27个字节

·
mâ\S
Vâ n
Ëx2 iSpWg~WbVgE

在线尝试!

开箱及其工作方式

Input: U = multiline string

qR    Split by newline and implicit assign to U

mâ\S
m     Map over U...
 â\S    .search(/\S/); first index of non-whitespace char
      Implicit assign to V (V = array of indentations)

Vâ n  Take unique elements of V, sort, and implicit assign to W

mDEF{Dx2 iSpWg~WbVgE
mDEF{                 Map over U...
     Dx2                Trim left
         iSp            Indent by this many spaces...
                 VgE      Find the current indentation stored in V
               Wb         Find its index on W
            Wg~           Take the opposite element on W

-R    Join with newline

真正如何运作

                 Input: U = multiline string

                 qR    Split by newline and implicit assign to U

                 mâ\S
                 m     Map over U...
               â\S    .search(/\S/); first index of non-whitespace char
         Implicit assign to V (V = array of indentations)

                 Vâ n  Take unique elements of V, sort, and implicit assign to W

                 mDEF{Dx2 iSpWg~WbVgE
                 mDEF{                 Map over U...
            Dx2                Trim left
      iSp            Indent by this many spaces...
VgE      Find the current indentation stored in V
 Wb         Find its index on W
     Wg~           Take the opposite element on W

                 -R    Join with newline

1

斯卡拉,176 171

def g(n:String)={val a=n.split('|').map(a=>a.prefixLength(' '==)->a)
(""/:a){case(s,(l,p))=>val b=a.unzip._1.distinct.sorted
s+" "*b.reverse(b.indexOf(l))+p.drop(l)+'\n'}}

它将在末尾添加一个额外的换行符。如果我不必在行尾保留空格,则可以将其设置为167:

def t(n:String)={val a=n.split('|').map(a=>a.prefixLength(' '==)->a.trim)
(""/:a){(s,l)=>val b=a.unzip._1.distinct.sorted
s+" "*b.reverse(b.indexOf(l._1))+l._2+'\n'}}

取消高尔夫:

      def reverseIndent(inString: String): String = {
    val lines = inString.split('\n')
    val linesByPrefixLength = lines.map { line =>
  line.prefixLength(char => char == ' ') -> line
    }
    val distinctSortedPrefixLengths = linesByPrefixLength.map(_._1).distinct.sorted
    val reversedPrefixes = distinctSortedPrefixLengths.reverse
    linesByPrefixLength.foldLeft("") { case (string, (prefixLength, line)) =>
  val newPrefixLength = reversedPrefixes(distinctSortedPrefixLengths.indexOf(prefixLength))
  val nextLinePrefix = " " * newPrefixLength
  string + nextLinePrefix + line.substring(prefixLength) + '\n'
    }
      }

1

PowerShell,112字节

$x=@($args|sls '(?m)^ *'-a|% m*|% v*|sort -u)
[regex]::Replace($args,'(?m)^ *',{$x[-1-$x.IndexOf($args.Value)]})

在线尝试!

少打高尔夫球:

$xIdents=@($args|select-string '(?m)^ *'-AllMatches|% matches|% value|sort -unique) # get a sorted set of indentations
[regex]::Replace($args,'(?m)^ *',{$xIdents[-1-$xIdents.IndexOf($args.Value)]})    # replace each indentation with opposite one

0

哈斯克尔(116)

import Data.List
f s|l<-map(span(==' '))$lines s=unlines[k++b|(a,b)<-l,(k,r)<-reverse>>=zip$sort$nub$map fst l,r==a]

0

PHP-173字节

未优化的代码应存储在$v变量中:

<?php $f='preg_replace';$f($p='#^ *#me','$i[]='.$s='strlen("$0")',$v);$a=$b=array_unique($i);sort($a);rsort($b);echo$f($p,'str_repeat(" ",array_combine($a,$b)['.$s.'])',$v);

这是取消评论的版本:

<?php
// Get the level of indentation for each line
$preg_replace = 'preg_replace';
$pattern = '#^ *#me';
$strlen = 'strlen("$0")';
$preg_replace($pattern, '$indentationLevelsOldList[] = '. $strlen, $value);

// Create an array associating the old level of indentation with the new expected one
$sortedArray = array_unique($indentationLevelsOldList);
$reverseSortedArray = $sortedArray;

sort($sortedArray);
rsort($reverseSortedArray);

$indentationLevelsNewList = array_combine($sortedArray, $reverseSortedArray);

// Print the correctly indented code
echo $preg_replace($pattern, 'str_repeat(" ", $indentationLevelsNewList['. $strlen .'])', $value);

我可能从未写过这么脏的东西。我很惭愧。


0

JavaScript 351

var i=0;var a=$("#i").html().split("\n");var b=[];for(;i<a.length;i++){j=a[i].match(/\s*/)[0];if(b.indexOf(j)<0){b.push(j);}}b.sort(function(a,b){return a - b;});var c=b.slice().reverse();var d="";for(i=0;i<a.length;i++){d+=a[i].replace(/\s*/,c[b.indexOf(a[i].match(/\s*/)[0])])+"\n";j=a[i].search(/\S/);if(b.indexOf(j)<0){b.push(j);}}$("#i").html(d);

非高尔夫版本:

var i = 0;
var a = $("#i").html().split("\n");
var b = [];
for (; i < a.length; i++) {
  j = a[i].match(/\s*/)[0];
  if (b.indexOf(j) < 0) {
    b.push(j);
  }
}
b.sort(function(a, b) {
  return a - b;
});
var c = b.slice().reverse();
var d = "";
for (i = 0; i < a.length; i++) {
  d += a[i].replace(/\s*/, c[b.indexOf(a[i].match(/\s*/)[0])]) + "\n";
  j = a[i].search(/\S/);
  if (b.indexOf(j) < 0) {
    b.push(j);
  }
}
$("#i").html(d);

测试中


0

Perl 5,112

111 + 1 -n-E免费)

@{$.[$.]}=/( *)(.*)/;++$_{$1}}{map$_{$_[$#_-$_]}=$_[$_],0..(@_=sort keys%_);say$_{$.[$_][0]}.$.[$_][1]for 0..$.

我相信可以用更少的笔触完成操作,但是目前还不知道如何做。

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.