Indentation inversée


63

J'ai entendu dire que votre code peut fonctionner plus rapidement si vous l'indenter en sens inverse, de sorte que le compilateur puisse le traiter comme un motif de conception d'arborescence à partir du sommet des "branches". Cela aide car la gravité accélère le temps nécessaire à la compilation de votre code et améliore l'efficacité de la structure de données. Voici un exemple de 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;
            }

Mais pour une raison quelconque, Notepad n’a pas de paramètre permettant de le faire automatiquement; j’ai donc besoin d’un programme pour le faire à ma place.

La description

Les soumissions doivent prendre un extrait de code en entrée, inverser l'indentation et générer le code obtenu.

Ceci est fait par la procédure suivante:

  • Divisez le code en lignes. Chaque ligne commencera par zéro ou plusieurs espaces (il n'y aura pas de tabulations).

  • Trouvez tous les niveaux d'indentation uniques dans le code. Par exemple, pour l'exemple ci-dessus, ce serait

    0
    4
    8
    12
    
  • Inversez l'ordre de cette liste de niveaux d'indentation et mappez la liste inversée à la liste d'origine. C'est difficile à expliquer avec des mots, mais pour l'exemple, cela ressemblerait à

    0  — 12
    4  — 8
    8  — 4
    12 — 0
    
  • Appliquez ce mappage au code d'origine. Dans l'exemple, une ligne avec une indentation de 0 espace deviendrait indentée de 12 espaces, 4 espaces deviendraient 8 espaces, etc.

Entrée sortie

L'entrée et la sortie peuvent être fournies comme vous le souhaitez (STDIN / STDOUT, paramètre de fonction / valeur de retour, etc.); Si votre langue ne prend pas en charge la saisie multiligne (ou si vous ne le souhaitez pas), vous pouvez utiliser le |caractère pour séparer les lignes.

L'entrée consistera uniquement en nouvelles lignes ASCII + imprimables et ne contiendra pas de lignes vides.

Cas de test

Contribution:

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

Sortie: l'exemple de code ci-dessus.

Contribution:

a
  b
  c
d
   e
        f
  g
   h

Sortie:

        a
   b
   c
        d
  e
f
   g
  h

Contribution:

1
 2
  3
 2
1

Sortie:

  1
 2
3
 2
  1

Contribution:

  foo

Sortie:

  foo

21
Son "JavaScript" n'est pas "un script Java": /
Optimiseur

75
@Optimizer, je constate que mon objectif de provoquer le plus de gens possible avec les deux premiers paragraphes a été atteint. ;)
Bouton de porte

7
1! = Autant de personnes que possible.
Optimiseur

23
@ JanDvorak Les mêmes personnes qui ont inventé les citations de style MLA pensent que c'est une bonne idée.
Rainbolt

6
Soi-disant, c'est plus rapide. Affectons un comité à cette question et attendons quelques années pendant que nous en oublions le but.
Conor O'Brien

Réponses:


10

CJam, 43 39 36 35 octets

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

Cela semble trop long. Je suis sûr que je ne suis pas l' optimisation assez!

Comment ça fonctionne:

L’idée de base est de scinder l’entrée sur la nouvelle ligne, de calculer le nombre d’espaces en début de ligne, de trier et d’obtenir des nombres uniques, de copier ce tableau et de l’inverser, de translittérer les numéros originaux dans l’ordre avec ces deux tableaux, puis de former le chaîne finale en utilisant cette information.

La partie la plus longue consiste à déterminer le nombre d'espaces de début dans chaque ligne, car CJam n'a pas de moyen facile de le faire.

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

Et dans l'esprit de la question. Une véritable expansion du 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 octets économisés grâce à Martin et 1 octet grâce à Dennis

Essayez-le en ligne ici


1. {}#a un bug: il retourne un entier, mais il devrait retourner un long. Ironiquement, i(cast to integer) corrige ce problème. 2. Depuis ""#n'a pas le même bug, _Sm0=#est un octet plus court.
Dennis

@ Dennis Oui, le bug est bizarre. Merci pour la solution de contournement!
Optimiseur

2
cette empreinte dans l'extension est si facile à lire! Vous devriez l'inverser!
DLeh

13

Python 2 - 137 131 octets

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

Prend entrée avec |au lieu de \n.

Explication

Les trois premières lignes sont assez simples. Dressez une liste de toutes les lignes de l'entrée, définissez une fonction qui vous indique le nombre d'espaces d'une chaîne, et créez une liste triée de valeurs que la fonction crache pour chaque ligne d'entrée.

La dernière ligne est bien plus amusante.

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

1
Tout cela semble bien en python 3, ce qui devrait vous faire économiser 2 octets (payez 2 pour ()économiser 4 raw_

1
f(s)for s in idevrait être map(f,i).
Feersum

1
Un morceau de magie: d=[];d+=set(L)est une version plus courte de d=sorted(set(L)).
xnor

7

JavaScript, ES6, 113 103 101 octets

Je suis presque sûr que cela peut être joué au moins un peu plus loin, mais voilà.

Je n'aurais jamais pensé qu'il y aurait une solution JS de 101 octets, battant 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]))

Cela crée une méthode nommée fqui peut être appelée avec la chaîne d'entrée. Si vous êtes dans un Firefox récent, vous avez des modèles de chaînes et vous pouvez appeler la méthode comme

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

Sinon, vous pouvez aussi l'appeler comme

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

ou essayez l'extrait ci-dessous:

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>


Vous pouvez enregistrer des octets de coupes en stockant l'expression rationnelle sous forme de variable, telle qu'elle est utilisée deux fois (vous devriez pouvoir le remplacer \spar un caractère d'espacement), et en supprimant les parenthèses xdans la fonction de remplacement.
NinjaBearMonkey

@hsl gee, merci! Je ne sais même pas pourquoi j'ai écrit (x): /
Optimizer

Vous n'avez pas besoin des deux bet cvous? Ils se réfèrent simplement au même tableau de toute façon.
Neil

5

Ruby, 63 octets

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

Ceci définit une fonction non nommée qui prend et retourne une chaîne. Vous pouvez l'appeler en ajoutant ["string here"]ou en l'attribuant à une variable, puis en appelant cette variable.

Fonctionnement: s.scan(r=/^ */)donne une liste de tous les espaces et magasins principaux qui contiennent des expressions rationnelles rpour une utilisation ultérieure. uniqélimine les doublons. sort... tris.

Maintenant, passez à la fin, l.zip(l.reverse)donne un tableau de paires que nous voulons substituer. to_htransforme cela en un hachage, interprétant les paires comme des paires clé-valeur.

A présent, s.gsubremplacez toutes les correspondances de l'expression rationnelle (tous les espaces de début) en utilisant ce hachage comme table de consultation pour trouver le remplacement.



2

Japt -R , 27 octets

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

Essayez-le en ligne!

Déballé et comment ça marche

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

Comment ça marche vraiment

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

Il ajoutera une nouvelle ligne à la fin. Si je n'ai pas eu à préserver des espaces en bout de ligne, je peux le faire en 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 octets

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

Essayez-le en ligne!

Moins joué au 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 octets

Le code non optimisé doit être stocké dans la $vvariable:

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

Voici la version non-golfée et commentée:

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

Je n'ai probablement jamais écrit quelque chose d'aussi sale. J'ai honte.


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

Version non-golfée:

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

Essai


0

Perl 5, 112

111 + 1 pour -n( -Egratuit)

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

Je suis sûr que cela peut être fait en moins de coups, mais je ne vois pas comment pour le moment.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.