Rientro inverso


63

Ho sentito che il tuo codice può essere eseguito più velocemente se lo indentrai al contrario, in modo che il compilatore possa elaborarlo come un modello di progettazione dell'albero dalla cima dei "rami" verso il basso. Questo aiuta perché la gravità accelera il tempo necessario per la compilazione del codice e migliora l'efficienza della struttura dei dati. Ecco un esempio, negli script 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;
            }

Ma per qualche motivo il Blocco note non ha un'impostazione per farlo automaticamente, quindi ho bisogno di un programma per farlo per me.

Descrizione

Gli invii devono prendere uno snippet di codice come input, invertire il rientro e generare il codice risultante.

Questo viene fatto con la seguente procedura:

  • Dividi il codice in righe. Ogni riga inizierà con zero o più spazi (non ci saranno schede).

  • Trova tutti i livelli di rientro univoci nel codice. Ad esempio, per l'esempio sopra, questo sarebbe

    0
    4
    8
    12
    
  • Invertire l'ordine di questo elenco di livelli di rientro e mappare l'elenco invertito all'elenco originale. Questo è difficile da spiegare a parole, ma per l'esempio, sembrerebbe

    0  — 12
    4  — 8
    8  — 4
    12 — 0
    
  • Applica questa mappatura al codice originale. Nell'esempio, una linea con rientro dello spazio 0 verrebbe indentata da 12 spazi, 4 spazi diventerebbero 8 spazi, ecc.

Input Output

L'ingresso e l'uscita possono essere forniti come desiderato (STDIN / STDOUT, parametro funzione / valore di ritorno, ecc.); se la tua lingua non supporta input multilinea (o semplicemente non vuoi), puoi usare il |carattere per separare le righe.

L'input consisterà solo di nuove righe ASCII + stampabili e non conterrà righe vuote.

Casi test

Ingresso:

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: il codice di esempio sopra.

Ingresso:

a
  b
  c
d
   e
        f
  g
   h

Produzione:

        a
   b
   c
        d
  e
f
   g
  h

Ingresso:

1
 2
  3
 2
1

Produzione:

  1
 2
3
 2
  1

Ingresso:

  foo

Produzione:

  foo

21
Il suo "JavaScript" non "scripting Java": /
Optimizer il

75
@Optimizer Vedo che il mio obiettivo di infuriare quante più persone possibile con i primi due paragrafi è stato raggiunto. ;)
Maniglia della porta

7
1! = Quante più persone possibile.
Ottimizzatore

23
@JanDvorak Gli stessi ragazzi che hanno inventato le citazioni in stile MLA pensano che questa sia una buona idea.
Rainbolt,

6
Presumibilmente, è più veloce. Assegniamo un comitato ad esso e aspettiamo alcuni anni mentre ne dimentichiamo lo scopo.
Conor O'Brien,

Risposte:


10

CJam, 43 39 36 35 byte

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

Sembra troppo lungo. Sono sicuro di non ottimizzare abbastanza!

Come funziona:

L'idea di base è quella di dividere l'input su newline, calcolare il numero di spazi iniziali in ogni riga, ordinare e ottenere numeri univoci, copiare quell'array e invertire la copia, traslitterare i numeri originali in ordine con questi due array e infine formare il stringa finale usando queste informazioni.

La parte più lunga è capire quanti spazi iniziali ci sono in ogni riga poiché CJam non ha un modo semplice per farlo.

Espansione del codice:

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

E nello spirito della domanda. Una vera espansione del codice:

                                          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 byte salvati grazie a Martin e 1 byte grazie a Dennis

Provalo online qui


1. {}#ha un bug: restituisce un numero intero, ma dovrebbe restituire un valore Long. Ironia della sorte, i(cast to integer) risolve questo problema. 2. Poiché ""#non ha lo stesso bug, _Sm0=#è più breve di un byte.
Dennis,

@Dennis Sì, il bug è strano. Grazie per la soluzione!
Ottimizzatore

2
questa rientranza nell'espansione è così facile da leggere! Dovresti invertirlo!
DLeh,

13

Python 2 - 137 131 byte

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

Accetta input |invece di \n.

Spiegazione

Le prime tre righe sono abbastanza semplici. Crea un elenco di tutte le righe nell'input, definisci una funzione che ti dice quanto spazio bianco iniziale ha una stringa e crea un elenco ordinato di valori che la funzione sputa per ogni riga di input.

L'ultima riga è molto più divertente.

                                 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 thanks :)
undergroundmonorail

1
Tutto questo sembra andare bene in Python 3 che dovrebbe farti risparmiare 2 byte (paghi 2 per ()salvare 4 per raw_)
FryAmTheEggman

1
f(s)for s in idovrebbe essere map(f,i).
febbraio

1
Un pezzo di magia: d=[];d+=set(L)è una versione più breve di d=sorted(set(L)).
xnor

7

JavaScript, ES6, 113 103 101 byte

Sono abbastanza sicuro che questo possa essere giocato a golf almeno un po 'più avanti, ma qui va.

Non avrei mai pensato che ci sarebbe stata una soluzione JS da 101 byte, battendo 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]))

Questo crea un metodo chiamato fche può essere chiamato con la stringa di input. Se ti trovi in ​​un ultimo Firefox, hai stringhe di modelli e puoi chiamare il metodo come

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

Altrimenti, puoi anche chiamarlo come

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

oppure prova lo snippet di seguito:

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>


Puoi salvare un byte coupé memorizzando il regex come variabile, poiché viene usato due volte (dovresti essere in grado di sostituire \scon un carattere spazio) e rimuovendo le parentesi xnella funzione di sostituzione.
NinjaBearMonkey

@hsl gee, grazie! Non so nemmeno perché ho scritto (x): /
Optimizer il

Non hai bisogno di entrambi be ctu? Si riferiscono comunque allo stesso array comunque.
Neil,

5

Rubino, 63 byte

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

Questo definisce una funzione senza nome che accetta e restituisce una stringa. È possibile chiamarlo aggiungendo ["string here"]o assegnandolo a una variabile e quindi chiamando quella variabile.

Come funziona: s.scan(r=/^ */)fornisce un elenco di tutti gli spazi principali e i negozi in cui regex rper un uso successivo. uniqelimina i duplicati. sort... specie.

Ora salta alla fine, l.zip(l.reverse)fornisce una matrice di coppie che vogliamo sostituire. to_hlo trasforma in un hash, interpretando le coppie come coppie chiave-valore.

Ora ho s.gsubsostituito tutte le partite della regex (tutti gli spazi iniziali) usando quell'hash come tabella di ricerca per trovare la sostituzione.



2

Japt -R , 27 byte

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

Provalo online!

Disimballato e come funziona

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

Come realmente funziona

                 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

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

Aggiungerà una nuova riga alla fine. Se non dovessi conservare gli spazi alla fine della linea, posso portarlo a 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 byte

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

Provalo online!

Meno golf:

$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

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]

0

PHP - 173 byte

Il codice non ottimizzato deve essere archiviato nella $vvariabile:

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

Ecco la versione ungolf e commentata:

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

Probabilmente non ho mai scritto qualcosa di così sporco. Mi vergogno.


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

Versione non golfata:

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

analisi


0

Perl 5, 112

111 + 1 per -n( -Eè gratuito)

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

Sono sicuro che può essere fatto in meno colpi, ma non vedo come al momento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.