Обратный отступ


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

Но по какой-то причине в Notepad нет настройки, позволяющей делать это автоматически, поэтому мне нужна программа, которая сделает это за меня.

Описание

Представления должны принимать фрагмент кода в качестве входных данных, изменять отступ и выводить полученный код.

Это делается с помощью следующей процедуры:

  • Разделите код на строки. Каждая строка будет начинаться с нуля или более пробелов (вкладок не будет).

  • Найти все уникальные уровни отступа в коде. Например, для приведенного выше примера это будет

    0
    4
    8
    12
    
  • Измените порядок в этом списке уровней отступов и сопоставьте перевернутый список с исходным списком. Это сложно объяснить словами, но для примера это будет выглядеть

    0  — 12
    4  — 8
    8  — 4
    12 — 0
    
  • Примените это сопоставление к исходному коду. В этом примере строка с 0-пробелом будет иметь отступ в 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-скриптинг»: /
Оптимизатор

75
@ Оптимизатор Я вижу, что моя цель в ярости как можно большего количества людей с первыми двумя параграфами была достигнута. ;)
Ручка двери

7
1! = Столько людей, сколько возможно.
Оптимизатор

23
@JanDvorak Те же парни, которые изобрели цитаты в стиле MLA, считают, что это хорошая идея.
Rainbolt

6
Предположительно, это быстрее. Давайте назначим в него комитет и подождем несколько лет, пока мы забудем его назначение.
Конор О'Брайен

Ответы:


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

7 байтов сэкономлено благодаря Мартину и 1 байт благодаря Деннису

Попробуйте это онлайн здесь


1. {}#имеет ошибку: возвращает целое число, но должно возвращать длинное. Как ни странно, i(приведение к целому числу) исправляет это. 2. Так ""#как не имеет ту же ошибку, _Sm0=#на один байт короче.
Деннис

@ Денис Да, ошибка странная. Спасибо за обходной путь!
Оптимизатор

2
этот отступ в расширении так легко читается! Вы должны полностью изменить это!
DLeh

13

Python 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 спасибо :)
подземный

1
Все это выглядит хорошо в Python 3, который должен сэкономить 2 байта (заплатить 2 за ()сохранение 4 за raw_)
FryAmTheEggman

1
f(s)for s in iдолжно быть map(f,i).
feersum

1
Часть волшебства: d=[];d+=set(L)это более короткая версия d=sorted(set(L)).
xnor

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в функции замены.
NinjaBearMonkey

@hsl Джи, спасибо! Я даже не знаю, почему я написал (x): /
Оптимизатор

Вам не нужны оба, bи cвы? В любом случае они просто ссылаются на один и тот же массив.
Нейл

5

Рубин, 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'}}

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

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

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

Я уверен, что это может быть сделано за меньшее количество ударов, но я не вижу, как в данный момент.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.