Rendre cette explication de code jolie à nouveau


17

introduction

La plupart des golfeurs de code ajoutent ici des explications à leurs soumissions, il est donc plus facile de comprendre ce qui se passe. Habituellement, les lignes de code vont à gauche et l'explication correspondante à droite avec une sorte de séparateur. Pour le rendre joli, les séparateurs sont tous sur la même colonne. De plus, un long texte d'explication est généralement placé sur la ligne suivante, afin que les lecteurs n'aient pas à faire défiler horizontalement pour tout lire.

Cependant, lorsque vous souhaitez modifier cette explication parce que vous avez fait des golfs fous, vous finissez souvent par perdre du temps à rendre votre explication à nouveau jolie. Comme il s'agit d'une tâche très répétitive, vous souhaitez écrire un programme pour cela.

Le défi

Étant donné plusieurs lignes de code avec explication et un séparateur, sortez le code bien formaté avec explication.

Exemple

Contribution

shM-crz1dc4. "ANDBYOROF # z = entrée

     rz1 # convertir l'entrée en majuscules
    entrée cd # split sur les espaces
         c4. "ANDBYOROF # crée une liste de mots à partir d'une chaîne compressée qui doit être ignorée
   - # filtre ces mots
 hM # ne prend que la première lettre de tous les mots
s # les joindre en une seule chaîne

Production

shM-crz1dc4. "ANDBYOROF # z = entrée

     rz1 # convertir l'entrée en majuscules
    entrée cd # split sur les espaces
         c4. "ANDBYOROF # crée une liste de mots à partir d'une chaîne compressée qui doit être
                           # ignoré
   - # filtre ces mots
 hM # ne prend que la première lettre de tous les mots
s # les joindre en une seule chaîne

Un cookie pour le premier qui peut découvrir ce que fait ce code.

L'algorithme de formatage

  • Trouvez la ligne de code la plus longue (à l'exclusion de l'explication et des espaces entre le code et le séparateur).
  • Ajoutez 5 espaces après cette ligne de code et ajoutez le séparateur correspondant avec explication. C'est maintenant la ligne de référence.
  • Ajustez toutes les autres lignes sur cette ligne de référence, de sorte que les séparateurs soient tous dans la même colonne.
  • Enveloppez toutes les lignes de plus de 93 caractères dans une nouvelle ligne de la manière suivante:
    • Trouvez le dernier mot dont la fin se trouve dans la colonne 93 ou moins.
    • Prenez tous les mots après celui-ci et enveloppez-les dans une nouvelle ligne avec le séparateur de tête et l'espacement correct. L'espace entre ces deux mots doit être supprimé, donc la première ligne se termine par un caractère de mot et la deuxième ligne commence par un après le séparateur.
    • Si la ligne résultante est toujours plus longue que 93 caractères, recommencez jusqu'à ce que chaque ligne soit inférieure à 94 caractères.

Remarques

  • Un mot se compose de caractères non blancs. Les mots sont séparés par un seul espace.
  • L'habillage de mots est toujours possible. Cela signifie qu'aucun mot n'est si long que cela rendrait l'emballage impossible.
  • L'entrée ne contiendra que de l'ASCII imprimable et n'aura aucun espace de fin
  • Le séparateur n'apparaîtra qu'une fois par ligne.
  • Alors que l'explication peut avoir une longueur illimitée, le séparateur et le code ne peuvent avoir qu'une longueur maximale combinée de 93 - 5 = 87caractères. Les 5 caractères sont les espaces entre le code et le séparateur. Le code et le séparateur comporteront toujours au moins un caractère.
  • L'entrée peut contenir des lignes vides. Ceux-ci ne contiendront jamais de caractères (sauf un retour à la ligne si vous prenez l'entrée comme chaîne multiligne). Ces lignes vides doivent également être présentes dans la sortie.
  • Chaque ligne aura du code, un séparateur et une explication. Les exceptions sont les lignes vides.
  • Vous pouvez prendre l'entrée dans n'importe quel format raisonnable, tant qu'elle n'est pas prétraitée. Indiquez clairement dans votre réponse laquelle vous utilisez.
  • La sortie peut être une chaîne multiligne ou une liste de chaînes.

Règles

Cas de test

Le format d'entrée est ici une liste de chaînes représentant les lignes et une seule chaîne pour le séparateur. Les deux sont séparés par une virgule. La sortie est une liste de chaînes.

['shM-crz1dc4. "ANDBYOROF # z = entrée', '', 'rz1 # convertit l'entrée en majuscule', 'cd # entrée fractionnée sur les espaces', 'c4." ANDBYOROF # crée une liste des mots à partir d'un paquet chaîne qui doit être ignorée ',' - # filtre ces mots ',' hM # ne prend que la première lettre de tous les mots ',' # les joint en une seule chaîne '], "#" -> [' shM-crz1dc4 . "ANDBYOROF # z = entrée ',' ',' rz1 # convertit l'entrée en majuscules ',' cd # entrée fractionnée sur les espaces ',' c4." ANDBYOROF # crée une liste des mots d'une chaîne compressée qui doit être ' , '# ignoré', '- # filtre ces mots ',' hM # ne prend que la première lettre de tous les mots ',' # les joint en une seule chaîne ']
['codecodecode e # Explication', 'sdf dsf sdf e # A Très très très très très très très très long long long long long long long long long long long long explication et ça ne cesse de s'allonger' ',' ',' certains plus de codee # et quelques explications supplémentaires '], "e #" -> [' codecodecode e # Explication ',' sdf dsf sdf e # A Très très très très très très très très très très long long long long long ',' e # long longue longue longue longue longue explication et ça ne cesse de s'allonger ',' e # et plus long ',' ',' un peu plus de code e # et encore plus d'explication ']

Codage heureux!


1
@Matt Tous les séparateurs sont toujours en colonne length of the longest code-line + 5. Cela s'appliquait également aux lignes qui ne contiennent qu'une explication, car elles étaient encapsulées.
Denker

Oh mon dieu, je fais ça mal depuis 3 heures. J'essayais d'envelopper le code long et de laisser les explications longues ..... Bien recommencer. Au moins, maintenant, c'est plus facile. Merci. Vous l'avez bien formulé ... Je suis juste idiot.
Matt

Envelopper toutes les lignes de plus de 93 caractères Cela signifie-t-il que le code, y compris les espaces de début, ne dépassera jamais 87 caractères?
Matt

@Matt Le code et le séparateur ensemble ne dépasseront jamais 87 caractères car nous avons besoin de 5 espaces entre le code et le séparateur et un caractère pour l'explication.
Denker

1
Le code Pyth trouve l'abréviation d'une chaîne donnée. Je le saurais parce que c'était une réponse à ma question.
Aplet123

Réponses:


3

Rubis, 245 237 220 216 212 209 205 205 octets

Fonction anonyme. Approche assez basique (trouver la longueur maximale, ajouter 5, puis effectuer le traitement sur chaque ligne, avec récursivité pour gérer le wrapping) et il pourrait y avoir une autre approche qui économise plus d'octets.

J'ai supprimé la réponse plus tôt qui ne remplissait pas toutes les conditions; Je ne voulais pas avoir un code à demi-réponse comme réponse (il recevait aussi des downvotes pour être incomplet) mais il devrait faire tout ce que la question demande, maintenant.

->x,d{l,S=0," "
s=->n{m,q=n.size,94-l-d.size
m>q ?(i=n.rindex(S,q)
n[0,i]+"
"+S*l+d+s[n[i+1,m]]):n}
x.map{|n|c,t=n.split d
c=(c||S).rstrip
l=[l,5+c.size].max
[c,t]}.map{|c,t|c+S*(l-c.size)+d+s[t]if t}*"
"}

Journal des modifications:

  • Enregistré quelques octets en exploitant certaines des promesses dans l'entrée, en particulier la promesse que toutes les lignes non vides ont le caractère séparateur et une explication.
  • Géré un peu plus au golf en enregistrant les chaînes séparées du premier mapappel et en supprimant certaines stripfonctions inutiles basées sur la promesse que les mots dans l'explication ont toujours exactement un espace entre eux. En outre, " "est affecté à une constante maintenant, car je l'utilise beaucoup.
  • Enchaînez les deux mapappels ensemble en tirant parti de la puissance des fonctions d'ordre supérieur, ce qui signifie que le premier appel de mappage définira lcorrectement la variable de longueur même si elle est appelée après la déclaration de la fonction d'assistance s. -4 octets.
  • Chaînes multilignes abusées à remplacer \npar des sauts de ligne réels, plus une petite astuce utilisant des ifopérateurs ternaires (quand joinest appelé sur un tableau avec des nilvaleurs, elles deviennent des chaînes vides)
  • .joinpeut apparemment être remplacé par un *.

Je pense que cela devrait être corrigé maintenant?
Value Ink

comment cela se termine à 94?
Ven

Très bien, maintenant que j'avais plus de temps pour travailler sur le code, il s'enroule correctement.
Value Ink

"Alors que l'explication peut avoir une longueur illimitée, le séparateur et le code ne peuvent avoir qu'une longueur maximale combinée de 93 - 5 = 87caractères. Les 5 caractères sont les espaces entre le code et le séparateur. Le code et le séparateur auront toujours au moins un caractère." Votre section de code est bien au-delà de la limite, avec 97 caractères, donc le programme a un comportement indéfini.
Value Ink

ah, bien repéré, c'est logique!
Ven

9

LiveScript, 243 236 233 228 219 225 octets

f = (x,k,m+5)->l=(.length);x.=map(->it/"#k"=>..0-=/ +$/;m>?=5+l ..0);i=0;[..0&&..0+' '*(m- l ..0)+k+..1 for x]=>while i<(l ..),++i=>j=(s=..[i])lastIndexOf ' ' 93;(..splice i+1 0 ' '*m+k+s[j to]*'';s.=substr 0 j) if 94<l s;..[i]=s

Comment ça marche: surtout comme le code Java. Commencez par aliaser la longueur (LiveScript permet de créer une fonction à partir d'opérateurs en utilisant des parenthèses). .=est a = a.b- que nous utilisons ici pour cartographier.

=> blabla ..est la construction en cascade Smalltalk-ish: le côté gauche de =>est accessible comme ..pour le reste du bloc; et sera retourné. Ici, c'est l'élément divisé sur k. Remarque: j'utilise une interpolation de chaîne, car cela /signifie uniquement «fractionner» avec une chaîne littérale.

LS nous permet également d'utiliser a-=/regexp/dans ce lambda (fonctionne également avec les littéraux de chaîne): c'est juste du sucre pour un .replaceappel.

Enfin, >?=est l' >?opérateur combinatoire -assin, qui renvoie le plus grand des deux opérandes.

LS a un style Python / Haskell pour les compréhensions, sans rien d'extraordinaire, sauf les "string * times" pour répéter l'espace assez longtemps.

Ceci pour la compréhension sert de sujet (voir le bloc sur les cascades anove).

Nous bouclons ensuite dans chaque élément du tableau (celui que nous venons de construire avec la compréhension), et si une ligne est plus grande que 93chars, nous trouvons le dernier index de, divisé là-bas, et poussons la ligne séparée juste après l'itération actuelle ( ... Pour que la prochaine itération se divise à nouveau si la ligne est trop grande).

Seule la dernière fantaisie chose a[j to]est une gamme (de j à la fin), mais étant donné qu'il utilise des méthodes Array nous devons rejoindre en une chaîne, que nous n'utilisant débordés *: *''.

exemple

s = """this is kod # Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
d # y

efgh # z"""

f = (x,k,m=5)->l=(.length);x.=map(->it/"#k"=>..0-=/ +$/;m>?=5+l ..0);i=0;[..0&&..0+' '*(m- l ..0)+k+..1 for x]=>while i<(l ..),++i=>j=(s=..[i])lastIndexOf ' ' 93;(..splice i+1 0 ' '*m+k+s[j to]*'';s.=substr 0 j) if 94<l s;..[i]=s

console.log (f s / '\n', '#') * \\n

production:

this is kod     # Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
                # tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
                # veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
                # commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
                # velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
                # cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
                # est laborum.
d               # y

efgh            # z

1
à celui qui a voté: la réponse est fixe.
Ven

2
Lorsqu'une explication déborde, vous avez besoin de la ou des nouvelles lignes pour aligner leurs caractères de séparation avec les autres, IIRC.
Value Ink

@KevinLau bien repéré, corrigé!
Ven

Pouvez-vous également mettre à jour votre exemple de sortie?
Value Ink

@KevinLau fait.
Ven

6

Java, 347 + 19 = 366 octets

A besoin

import java.util.*;

Ainsi les +19 octets.

(c,s)->{int p=0,i=0,t;String l;for(;i<c.size();i++){l=c.get(i);l=l.replaceAll(" *"+s,s);p=Math.max(l.indexOf(s),p);c.set(i,l);}p+=5;for(i=0;i<c.size();i++){l=c.get(i);t=l.indexOf(s);while(t>-1&t<p)l=l.substring(0,t)+" "+l.substring(t++);t=93;if(l.length()>t){while(l.charAt(t)!=' ')t--;c.add(i+1,s+l.substring(t));l=l.substring(0,t);}c.set(i,l);}}

Prend au format f.accept(List<String> code, String seperator). Formats en place. Une version qui crée et renvoie une nouvelle List<String>serait triviale à implémenter mais coûterait quelques octets.

Utilisation en retrait + exemple:

static BiConsumer<List<String>, String> prettify = (code, seperator) -> {
    int space = 0, i=0, t;
    String line;
    for (; i<code.size(); i++) { // for each line
        line = code.get(i); // get line
        line = line.replaceAll(" *" + seperator, seperator); // strip space before seperator
        space = Math.max(line.indexOf(seperator), space); // save biggest space until seperator
        code.set(i, line); // save line
    }
    space += 5;
    for (i=0; i<code.size(); i++) { // for each line
        line = code.get(i); // get line
        t = line.indexOf(seperator); // get index of seperator
        while (t>-1&t<space) // while the seperator exists and is further left than desired
            line = line.substring(0,t) + " " + line.substring(t++); // move it right by adding a space before it
        t = 93; // get desired line length
        if (line.length()>t) { // if the line is longer than that
            while (line.charAt(t)!=' ') t--; // scan backwards for a space
            code.add(i+1, seperator + line.substring(t)); // add a line after this one with seperator and the rest of the line
                                                          // the next pass will space it correctly
            line = line.substring(0,t); // cut off this line at that point
        }
        code.set(i, line); // save edited line back to List
    }
};

public static void main(String[] args) {
    List<String> code = new ArrayList<>();
    code.add("shM-crz1dc4.\"ANDBYOROF  # z = input");
    code.add("");
    code.add("     rz1      # convert input to uppercase");
    code.add("    c   d        # split input on spaces");
    code.add("         c4.\"ANDBYOROF        # create a list of the words from a packed string which shall be ignored");
    code.add("   -          # filter those words out");
    code.add(" hM                # only take the first letter of all words");
    code.add("s                   # join them into one string");
    prettify.accept(code, "#");
    code.stream().forEach(System.out::println);
}

... Je devrais probablement passer par lui-même: P


Si quelqu'un peut comprendre pourquoi replace(" *"+s)ne fonctionne pas mais replaceAll(" *"+s)que j'aimerais l'entendre - je ne peux pas le comprendre.
CAD97

<badguess> replaceutilise des chaînes mais replaceAllutilise des expressions rationnelles. </badguess>
CalculatorFeline

@CatsAreFluffy bien, vous avez raison ! Je ne sais pas comment je ne l'ai pas réalisé: P
CAD97

Vous ne pouvez pas supprimer la nouvelle ligne?
CalculatorFeline

Eh bien, la nouvelle ligne peut être supprimée en raison des semi: s requis (qui devraient être .s mais peu importe)
CalculatorFeline

2

PowerShell, 224 217 235 octets

param($d,$s)$d=$d-split"`r`n";$p="\s+\$([char[]]$s-join"\")\s";$m=($d|%{($_-split$p)[0].Length}|sort)[-1];$d|%{$l,$c=$_-split$p;$c=if($c){"$s "+(("$c "-split"(.{1,$(87-$m)})\s"|?{$_})-join"`n$(" "*($m+5))$s ")}$l.PadRight($m+5," ")+$c}

Mise à jour de la logique pour déterminer la longueur maximale de chaîne de code. Mis à jour pour autoriser plusieurs séparateurs qui incluent des méta caractères regex.


Petite explication

Cela prend toute une chaîne délimitée par des sauts de ligne pour l'entrée.

param($d,$s)
# $d is a newline delimited string. $s is the separator.
# Take the string and turn it into a string array. Stored as $d
$d=$d-split"`r`n"
# Save a regex pattern as it is used more than once
$p="\s+\$([char[]]$s-join"\")\s"
# Get the longest string of code's length
$m=($d|%{($_-split$p)[0].Length}|sort)[-1]
# Split each line again into code and comment. Write out each line with formatted explanations based on separator column position $m
$d|%{
# Split the line
$l,$c=$_-split$p
# Build the comment string assuming there is one.
$c=if($c){"$s "+(("$c "-split"(.{1,$(87-$m)})\s"|?{$_})-join"`n$(" "*($m+5))$s ")}
# Pad the right amount of space on the code and add the comment string.
$l.PadRight($m+5," ")+$c
}

Exemple de sortie avec du Lorem Ipsum

shM-crz1dc4."ANDBYOROF     # z = input

     rz1                   # convert input to uppercase
    c   d                  # split input on spaces
         c4."ANDBYOROF     # But I must explain to you how all this mistaken idea of
                           # denouncing pleasure and praising pain was born and I will give
                           # you a complete account of the system, and expound the actual
                           # teachings of the great explorer
   -                       # filter those words out
 hM                        # only take the first letter of all words
s                          # join them into one string

@nimi Espérons que les mises à jour apportent désormais une meilleure solution.
Matt

@nimi Autre chose que vous remarquez mal? Apparemment, j'ai des problèmes de lecture ces derniers jours.
Matt

Maintenant, vous avez un +1.
nimi

1

MATLAB, 270 265 262 octets

function d=f(I,s);S=@sprintf;R=@regexprep;m=regexp(I,['\s*\',s]);L=max([m{:}])+4;a=@(x)S('%-*s%s',L,x,s);b=@(x)R(R(x,S('(.{1,%d}(\\s+|$))',93-L),S('$1\n%*s ',L+1,s)),['\n\s*\',s,' $'],'');c=R(I,['(.*?)\s*\',s,'\s*(.*$)'],'${a($1)} ${b($2)}');d=S('%s\n',c{:});end

Le programme accepte l'entrée Isous la forme d'un tableau de cellules de chaînes où chaque élément du tableau de cellules est une ligne distincte de l'entrée. Il accepte également une deuxième entrée qui indique quel est le caractère de commentaire (c'est-à-dire #). La fonction renvoie une chaîne de plusieurs lignes correctement formatée.

Brève explication

function d = f(I,s)
    %// Setup some shortcuts for commonly-used functions
    S = @sprintf;
    R = @regexprep;

    %// Find the location of the space AFTER each code block but before a comment
    m = regexp(I, ['\s*\',s]);

    %// Compute the maximum column location of the code and add 4 (5 - 1)
    L = max([m{:}]) + 4;

    %// This is a callback for when we detect code
    %// It left justifies and pads the string to L width
    a = @(x)S('%-*s%s', L, x, s);

    %// This is a callback for when we detect a comment.
    b = @(x)R(...
            R(x, ...
                S('(.{1,%d}(\\s|$))', 93 - L), ... Regex for wrapping text to desired width
                S('$1\n%*s ', L+1, s)), ... Append a newline and padding for next line 
            ['\n\s*\',s,' $'], ''); ... Remove the trailing newline (to be improved)

    %// Perform replacement of everything.
    c = R(I, ...
            ['(.*?)\s*\',s,'\s*(.*$)'], ... Match "code comment_char comment"
            '${a($1)} ${b($2)}');   ... Replace using the output of the callbacks

    %// Concatenate all of the strings together with a newline in between
    d=S('%s\n',c{:});
end

Exemple d'entrée

I = {
    'shM-crz1dc4."ANDBYOROF  # z = input'
    ''
    '     rz1      # convert input to uppercase'
    '    c   d        # split input on spaces'
    '         c4."ANDBYOROF        # create a list of the words from a packed string which shall be ignored'
    '   -          # filter those words out'
    ' hM                # only take the first letter of all words'
    's                   # join them into one string'
};

disp(f(I,'#'));

Exemple de sortie

shM-crz1dc4."ANDBYOROF     # z = input

     rz1                   # convert input to uppercase
    c   d                  # split input on spaces
         c4."ANDBYOROF     # create a list of the words from a packed string which shall be
                           # ignored
   -                       # filter those words out
 hM                        # only take the first letter of all words
s                          # join them into one string
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.