Odwrotne wcięcie

63

Słyszałem, że twój kod może działać szybciej, jeśli wcinasz go w odwrotnej kolejności, dzięki czemu kompilator może przetwarzać go jak wzorzec projektu drzewa od samego początku „gałęzi”. Pomaga to, ponieważ grawitacja przyspieszy czas kompilacji kodu, a wydajność struktury danych ulegnie poprawie. Oto przykład ze skryptów 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;
            }

Ale z jakiegoś powodu Notatnik nie ma ustawienia automatycznego robienia tego, więc potrzebuję programu, który by to dla mnie zrobił.

Opis

Zgłoszenia muszą przyjmować fragment kodu jako dane wejściowe, odwracać wcięcia i generować wynikowy kod.

Odbywa się to zgodnie z następującą procedurą:

  • Podziel kod na linie. Każda linia rozpocznie się od zera lub więcej spacji (nie będzie tabulatorów).

  • Znajdź wszystkie unikalne poziomy wcięć w kodzie. Na przykład w powyższym przykładzie byłoby to

    0
    4
    8
    12
    
  • Odwróć kolejność tej listy poziomów wcięć i zamapuj listę odwróconą na oryginalną. Trudno to wytłumaczyć słowami, ale na przykład wyglądałoby to tak

    0  — 12
    4  — 8
    8  — 4
    12 — 0
    
  • Zastosuj to mapowanie do oryginalnego kodu. W tym przykładzie linia z wcięciem 0-przestrzeni zostanie wcięta o 12 spacji, 4 spacje zamieniają się w 8 spacji itp.

Wejście wyjście

Dane wejściowe i wyjściowe można podać w dowolny sposób (STDIN / STDOUT, parametr funkcji / wartość zwracana itp.); jeśli twój język nie obsługuje wprowadzania wielowierszowego (lub po prostu nie chcesz), możesz |zamiast tego użyć znaku do oddzielenia linii.

Dane wejściowe będą się składały tylko z drukowanych znaków ASCII + i nie będą zawierać pustych linii.

Przypadki testowe

Wejście:

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

Dane wyjściowe: powyższy przykładowy kod.

Wejście:

a
  b
  c
d
   e
        f
  g
   h

Wynik:

        a
   b
   c
        d
  e
f
   g
  h

Wejście:

1
 2
  3
 2
1

Wynik:

  1
 2
3
 2
  1

Wejście:

  foo

Wynik:

  foo
Klamka
źródło
21
Jego „JavaScript”, a nie „Java scripting”: /
Optimizer
75
@Optimizer Widzę, że mój cel doprowadzenia do furii jak największej liczby osób dwoma pierwszymi akapitami został osiągnięty. ;)
Klamka
7
1! = Tyle osób, ile to możliwe.
Optymalizator
23
@JanDvorak Ci sami, którzy wymyślili cytaty w stylu MLA, uważają, że to dobry pomysł.
Rainbolt,
6
Podobno jest szybszy. Przydzielmy mu komitet i poczekajmy kilka lat, aż zapomnimy o tym celu.
Conor O'Brien,

Odpowiedzi:

10

CJam, 43 39 36 35 bajtów

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

To wygląda na zbyt długo. Jestem pewien, że nie optymalizuję wystarczająco!

Jak to działa:

Podstawową ideą jest podzielenie danych wejściowych na nowy wiersz, obliczenie liczby wiodących spacji w każdej linii, sortowanie i uzyskiwanie unikalnych liczb, kopiowanie tej tablicy i odwracanie kopii, transliteracja oryginalnych liczb w kolejności za pomocą tych dwóch tablic, a następnie ostatecznie utworzenie ostatni ciąg przy użyciu tych informacji.

Najdłuższą częścią jest ustalenie, ile wiodących spacji jest w każdej linii, ponieważ CJam nie ma łatwego sposobu na zrobienie tego.

Rozszerzenie kodu:

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

I w duchu pytania. Prawdziwe rozszerzenie kodu:

                                          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 bajtów zaoszczędzonych dzięki Martinowi i 1 bajt dzięki Dennisowi

Wypróbuj online tutaj

Optymalizator
źródło
1. {}#ma błąd: zwraca liczbę całkowitą, ale powinien zwrócić wartość Long. Jak na ironię, i(rzut na liczbę całkowitą) to rozwiązuje. 2. Ponieważ ""#nie ma tego samego błędu, _Sm0=#jest o jeden bajt krótszy.
Dennis,
@Dennis Tak, błąd jest dziwny. Dzięki za obejście!
Optymalizator
2
to wcięcie w rozszerzeniu jest tak łatwe do odczytania! Powinieneś to odwrócić!
DLeh,
13

Python 2 - 137 131 bajtów

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

Pobiera dane wejściowe za pomocą |zamiast \n.

Wyjaśnienie

Pierwsze trzy linie są dość proste. Zrób listę wszystkich linii na wejściu, zdefiniuj funkcję, która mówi, ile ma wiodących białych znaków w ciągu, i ułóż posortowaną listę wartości, które funkcja wydziela dla każdego wiersza na wejściu.

Ostatnia linia jest o wiele przyjemniejsza.

                                 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
podziemny monorail
źródło
Potwierdzono 137 :)
FryAmTheEggman
@frya dzięki :)
undergroundmonorail
1
Wszystko wydaje się w porządku w Pythonie 3, który powinien zaoszczędzić 2 bajty (zapłać 2 za ()save 4 za raw_)
FryAmTheEggman
1
f(s)for s in ipowinno być map(f,i).
feersum
1
Kawałek magii: d=[];d+=set(L)jest krótszą wersją d=sorted(set(L)).
xnor
7

JavaScript, ES6, 113 103 101 bajtów

Jestem prawie pewien, że można grać w golfa przynajmniej trochę dalej, ale proszę bardzo.

Nigdy bym nie pomyślał, że będzie 101-bajtowe rozwiązanie JS, pokonujące Pythona!

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

Tworzy to metodę o nazwie, fktórą można wywołać za pomocą ciągu wejściowego. Jeśli korzystasz z najnowszej przeglądarki Firefox, masz ciągi szablonów i możesz wywołać metodę jak

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

W przeciwnym razie możesz też nazwać to tak

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

lub wypróbuj poniższy fragment:

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>

Optymalizator
źródło
Możesz zapisać bajty coupes, przechowując wyrażenie regularne jako zmienną, ponieważ jest on używany dwa razy (powinieneś być w stanie zastąpić \sznakiem spacji) i usuwając nawiasy wokół xfunkcji replace.
NinjaBearMonkey
@ hsl gee, dzięki! Nie wiem nawet, dlaczego napisałem (x): /
Optimizer
Nie trzeba zarówno bi cco? I tak odnoszą się tylko do tej samej tablicy.
Neil
5

Rubinowy, 63 bajty

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

Definiuje nienazwaną funkcję, która pobiera i zwraca ciąg znaków. Możesz wywołać go przez dodanie ["string here"]lub przypisanie do zmiennej, a następnie wywołanie tej zmiennej.

Jak to działa: s.scan(r=/^ */)zawiera listę wszystkich czołowych miejsc i sklepów, które regex w rcelu późniejszego wykorzystania. uniqeliminuje duplikaty. sort... sortuje.

Teraz przejdź do końca, l.zip(l.reverse)daje tablicę par, które chcemy zastąpić. to_hzamienia to w skrót, interpretując pary jako pary klucz-wartość.

Teraz s.gsub zastąpiono wszystkie dopasowania wyrażenia regularnego (wszystkie wiodące spacje), używając tego skrótu jako tabeli wyszukiwania, aby znaleźć zamiennik.

Martin Ender
źródło
2

Japt -R , 27 bajtów

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

Wypróbuj online!

Rozpakowane i jak to działa

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

Jak to naprawdę działa

                 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
Bubbler
źródło
1

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

Na końcu doda nową linię. Gdybym nie musiał zachowywać spacji na końcu wiersza, mogę uzyskać numer 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'}}

Nie golfowany:

      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'
    }
      }
Chad Retz
źródło
1

PowerShell , 112 bajtów

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

Wypróbuj online!

Mniej golfa:

$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
mazzy
źródło
0

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]
dumny haskeller
źródło
0

PHP - 173 bajtów

Niezoptymalizowany kod powinien być przechowywany w $vzmiennej:

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

Oto nieposkromiona i skomentowana wersja:

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

Prawdopodobnie nigdy nie napisałem czegoś tak brudnego. Wstydzę się.

Czarna dziura
źródło
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);

Wersja bez golfa:

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

Testowanie

Facet z kapeluszem
źródło
0

Perl 5, 112

111 + 1 za -n( -Ejest bezpłatny)

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

Jestem pewien, że można to zrobić za pomocą mniejszej liczby ruchów, ale w tej chwili nie wiem, jak to zrobić.

msh210
źródło