# Reverse indentation

I've heard that your code can run faster if you indent it in reverse, so that the compiler can process it like a tree design pattern from the very top of the "branches" down. This helps because gravity will speed up the time it takes for your code to be compiled, and the data structure efficiency is improved. Here's an example, in Java scripting:

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


But for some reason Notepad doesn't have a setting to do this automatically, so I need a program to do it for me.

# Description

Submissions must take a code snippet as input, reverse the indentation, and output the resulting code.

This is done by the following procedure:

• Split the code up into lines. Each line will start with zero or more spaces (there will be no tabs).

• Find all unique indentation levels in the code. For example, for the above example, this would be

0
4
8
12

• Reverse the order of this list of indentation levels, and map the reversed list to the original list. This is hard to explain in words, but for the example, it would look like

0  — 12
4  — 8
8  — 4
12 — 0

• Apply this mapping to the original code. In the example, a line with 0-space-indentation would become indented by 12 spaces, 4 spaces would become 8 spaces, etc.

# Input / Output

The input and output can be provided however you would like (STDIN/STDOUT, function parameter/return value, etc.); if your language does not support multiline input (or you just don't want to), you can use the | character to separate lines instead.

The input will consist of only printable ASCII + newlines, and it will not contain empty lines.

# Test cases

Input:

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


Output: the example code above.

Input:

a
b
c
d
e
f
g
h


Output:

        a
b
c
d
e
f
g
h


Input:

1
2
3
2
1


Output:

  1
2
3
2
1


Input:

  foo


Output:

  foo

• Its "JavaScript" not "Java scripting" :/ Dec 18 '14 at 21:36
• @Optimizer I see that my goal of infuriating as many people as possible with the first two paragraphs has been achieved. ;)
– Doorknob
Dec 18 '14 at 21:42
• 1 != as many people as possible. Dec 18 '14 at 21:44
• @JanDvorak The same guys that invented MLA style citations think this is a good idea. Dec 18 '14 at 21:53
• Supposedly, it's faster. Let's assign a committee to it and wait a few years while we forget the purpose of it. Dec 18 '14 at 23:19

# Python 2 - 137 131 bytes

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


Takes input with | instead of \n.

Explanation

The first three lines are fairly straightforward. Make a list of all the lines in the input, define a function that tells you how much leading whitespace a string has, and make a sorted list of values that function spits out for each line of input.

The last line is way more fun.

                                 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

• Confirmed 137 :) Dec 18 '14 at 21:59
• @frya thanks :) Dec 18 '14 at 22:06
• This all seems fine in python 3 which should save you 2 bytes (pay 2 for () save 4 for raw_) Dec 18 '14 at 23:08
• f(s)for s in i should be map(f,i). Dec 18 '14 at 23:14
• A piece of magic: d=[];d+=set(L) is a shorter version of d=sorted(set(L)).
– xnor
Dec 19 '14 at 6:53

# CJam, 43 39 36 35 bytes

qN/_{_Sm0=#}%___&$_W%er]z{~S*@+>N}%  This looks toooo long. I am sure I am not Optimizing enough! How it works: Basic idea is to split the input on newline, calculate the number of leading spaces in each line, sort and get unique numbers, copy that array and reverse the copy, transliterate the original in-order numbers with this two arrays and then finally form the final string using this information. The lengthiest part is to figure out how many leading spaces are there in each line as CJam does not have an easy way of doing it. Code expansion: 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";


And in the spirit of the question. A real expansion of the code:

                                          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";  7 bytes saved thanks to Martin and 1 byte thanks to Dennis Try it online here • 1. {}# has a bug: it returns an Integer, but it should return a Long. Ironically, i (cast to integer) fixes this. 2. Since ""# doesn't have the same bug, _Sm0=# is one byte shorter. Dec 19 '14 at 3:29 • @Dennis Yeah, the bug is weird. Thanks for the workaround ! Dec 19 '14 at 7:01 • this indentation in the expansion is so easy to read! You should reverse it! – DLeh Dec 19 '14 at 21:08 # JavaScript, ES6, 113 103 101 bytes I am pretty sure this can be golfed at least a little further, but here goes. Never would have thought that there will be a 101 bytes JS solution, beating 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]))  This creates a method named f which can be called with the input string. If you are in a latest Firefox, you have template strings and you can call the method like f(a b c d e f g h)  Otherwise, you can also call it like f("a\n\ b\n\ c\n\ d\n\ e\n\ f\n\ g\n\ h")  or, try the snippet below: 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> • You can save a coupes bytes by storing the regex as a variable, as it is used twice (you should be able to replace \s with a space character), and removing the parentheses around x in the replace function. Dec 19 '14 at 1:57 • @hsl gee, thanks! I don't even know why I wrote (x) :/ Dec 19 '14 at 7:06 • You don't need both b and c do you? They just refer to the same array anyway. – Neil May 11 '16 at 15:00 # Ruby, 63 bytes ->s{l=s.scan(r=/^ */).uniq.sort;s.gsub r,l.zip(l.reverse).to_h}  This defines an unnamed function which takes and returns a string. You can call it by appending ["string here"] or by assigning it to a variable, and then calling that variable. How it works: s.scan(r=/^ */) gives a list of all leading spaces and stores that regex in r for later use. uniq eliminates duplicates. sort... sorts. Now skip to the end, l.zip(l.reverse) gives an array of pairs we want to substitute. to_h turns that into a hash, interpreting the pairs as key-value pairs. Now s.gsub replaced all matches of the regex (all leading spaces) by using that hash as a look up table to find the replacement. ## Pyth 39 L-/bd/rb6dJcz\|KS{mydJFNJ+*d@_KxKyN>NyN  Try it online. Uses the | delimiter option. # Japt-R, 27 bytes · mâ\S Vâ n Ëx2 iSpWg~WbVgE  Try it online! ### Unpacked & How it works 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  ### How it really works  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  # Haskell, 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]  # Scala, 176171 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'}}  It will add an extra newline at the end. If I did not have to preserve spaces at the end of the line, I can get it to 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'}}  Ungolfed:  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' } }  # PowerShell, 112 bytes $x=@($args|sls '(?m)^ *'-a|% m*|% v*|sort -u) [regex]::Replace($args,'(?m)^ *',{$x[-1-$x.IndexOf($args.Value)]})  Try it online! Less golfed: $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  ## PHP - 173 bytes The unoptimized code should be stored in the $v variable:

<?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);


Here is the ungolfed and commented version:

<?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);  I've probably never written something so dirty. I'm ashamed. ## 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);  Ungolfed version: 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);  ### Testing 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); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <pre><code id="i"> 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; } </code></pre> 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); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <pre><code id="i"> a b c d e f g h </code></pre> 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); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <pre><code id="i"> 1 2 3 2 1 </code></pre> 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); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <pre><code id="i"> foo </code></pre> # Perl 5, 112 111 + 1 for -n (-E is free) @{$.[$.]}=/( *)(.*)/;++$_{$1}}{map$_{$_[$#_-$_]}=$_[$_],0..(@_=sort keys%_);say$_{$.[$_][0]}.$.[$_][1]for 0..\$.


I'm sure it can be done in fewer strokes, but I don't see how at the moment.