このコードの説明をもう一度きれいにする


17

前書き

ほとんどのコード愛好家は、提出物に説明を追加するため、何が起こっているのかを理解しやすくなります。通常、コードラインは左側にあり、対応する説明はある種のセパレーターとともに右側にあります。見た目をよくするために、セパレータはすべて同じ列にあります。また、通常、長い説明テキストは次の行に折り返されるため、読者はすべてを読むために水平にスクロールする必要はありません。

しかし、クレイジーなゴルフをしたためにこの説明を編集したい場合、説明をかなりやり直すために時間を費やすことがよくあります。これは非常に反復的なタスクなので、このためのプログラムを作成する必要があります。

チャレンジ

説明とセパレータを含む数行のコードが与えられたら、説明付きのきれいにフォーマットされたコードを出力します。

入力

shM-crz1dc4。 "ANDBYOROF#z =入力

     rz1#入力を大文字に変換します
    cd#スペースで入力を分割
         c4。 "ANDBYOROF#無視されるパックされた文字列から単語のリストを作成します
   -#これらの単語を除外
 hM#すべての単語の最初の文字のみを取得
s#それらを1つの文字列に結合する

出力

shM-crz1dc4。 "ANDBYOROF#z =入力

     rz1#入力を大文字に変換します
    cd#スペースで入力を分割
         c4。 "ANDBYOROF#パックされた文字列から単語のリストを作成します。
                           #無視
   -#これらの単語を除外
 hM#すべての単語の最初の文字のみを取得
s#それらを1つの文字列に結合する

このコードが何をするかを知ることができる最初の人のための1つのクッキー。

フォーマットアルゴリズム

  • 最も長いコード行を見つけます(説明と、コードと区切り文字の間のスペースを除く)。
  • このコード行の後に5つのスペースを追加し、対応するセパレーターに説明を追加します。これが基準線になりました。
  • セパレーターがすべて同じ列になるように、この基準線に1行おきに調整します。
  • 93文字を超えるすべての行を次の方法で新しい行にラップします。
    • 末尾が93列以下である最後の単語を見つけます。
    • この後のすべての単語を取り、先頭の区切り文字と正しい間隔で新しい行にラップします。これらの2つの単語の間のスペースは削除する必要があるため、最初の行は単語文字で終わり、2番目の行は区切り文字の後の1つで始まります。
    • 結果の行がまだ93文字より長い場合は、すべての行が94文字未満になるまで同じ操作を繰り返します。

ノート

  • 単語は非空白文字で構成されます。単語は単一のスペースで区切られます。
  • ワードラッピングは常に可能です。これは、ラッピングが不可能になるほど長い単語がないことを意味します。
  • 入力には印刷可能なASCIIのみが含まれ、末尾の空白は含まれません。
  • セパレータは1行に1回だけ表示されます。
  • 説明の長さには制限がありませんが、セパレータとコードの最大長の合計は93 - 5 = 87charsのみです。5文字は、コードと区切り記号の間のスペースです。コードと区切り記号は常に少なくとも1文字の長さです。
  • 入力には空の行が含まれる場合があります。これらには文字は含まれません(入力を複数行の文字列として使用する場合は改行を除きます)。これらの空の行も出力に存在する必要があります。
  • すべての行には、いくつかのコード、セパレータ、説明があります。例外は空の行です。
  • 前処理されていない限り、妥当な形式で入力を取得できます。どちらを使用するかを回答で明確にしてください。
  • 出力は、複数行の文字列または文字列のリストです。

ルール

  • 機能または完全なプログラムが許可されます。
  • 入出力のデフォルト規則
  • 標準の抜け穴が適用されます。
  • これはなので、バイト数が最も少なくなります。Tiebreakerは以前の提出です。

テストケース

ここでの入力形式は、行を表す文字列のリストと区切り文字の単一の文字列です。両方ともコンマで区切られます。出力は文字列のリストです。

['shM-crz1dc4。 "ANDBYOROF#z = input'、 ''、 'rz1#入力を大文字に変換する'、 'cd#スペースで入力を分割する'、 'c4。" ANDBYOROF#パックから単語のリストを作成する無視される文字列 '、'-#それらの単語を除外する '、' hM#すべての単語の最初の文字のみを取得する '、' s#それらを1つの文字列に結合する ']、 "#"-> [' shM-crz1dc4 。 "ANDBYOROF#z = input '、' '、' rz1#入力を大文字に変換する '、' cd#スペースで入力を分割する '、' c4。" ANDBYOROF#必要なパックされた文字列から単語のリストを作成する、「#無視」、「-#それらの単語を除外する」、「hM#すべての単語の最初の文字のみを取得する」、「s#それらを1つの文字列に結合する」]
['codecodecode e#Explanation'、 'sdf dsf sdf e#A非常に非常に非常に非常に非常に非常に非常に長い長い長い長い長い長い長い長い長い長い長い説明とそれはますます長くなり続ける」、' '、「いくつかより多くのcodee#といくつかの詳細な説明 ']、 "e#"-> [' codecodecode e#Explanation '、' sdf dsf sdf e#A非常に非常に非常に非常に非常に非常に非常に非常に非常に長いlong long long '、' e#long長い長い長い長い長い説明とそれは長くなり続けます」、「e#and long」、「」、「いくつかのコードe#といくつかの説明」]

ハッピーコーディング!


1
@Mattすべてのセパレーターは常にcolumnにありますlength of the longest code-line + 5。これは、折り返されているため、説明のみを含む行にも適用されます。
デンカー

なんてこった、これを過去3時間間違えてやっている。長いコードをラップして、説明を長く残そうとしました。少なくとも今は簡単です。ありがとう。あなたはそれをうまく言いました...。
マット

93文字より長いすべての行を折り返すそれは、先行スペースを含むコードが87文字より長くならないことを意味しますか?
マット

@Matt コードとセパレーターの間にスペースが5つ必要であり、説明のために1つの文字が必要なので、コードセパレーターを合わせて87文字より長くなることはありません。
デンカー

1
Pythコードは、任意の文字列の略語を見つけます。それは私の質問への答えだったので、私は知っているでしょう。
Aplet123

回答:


3

ルビー、245の 237 220 216 212 209 205バイト

匿名関数。かなり基本的なアプローチ(最大長を見つけ、5を追加し、各行で処理を行い、折り返しを処理する再帰を使用)と、より多くのバイトを節約する別のアプローチがあります。

すべての要件を満たしていない回答を以前に削除しました。私は答えとして半分答えられたコードを持ちたくありませんでした(それは不完全であるために下票を得ていました)が、今は質問が求めるすべてをする必要があります。

->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}*"
"}

変更ログ:

  • 入力のいくつかの約束、特にすべての空でない行に区切り文字と説明があるという約束を活用することで、いくつかのバイトを節約しました。
  • 最初のmap呼び出しから分割された文字列を保存stripし、説明内の単語の間に必ず1つのスペースがあるという約束に基づいて、いくつかの不要な機能を削除することで、ゴルフをもう少しやり遂げました。また、" "定数を使用するので、今は定数に割り当てられています。
  • map高階関数のパワーを活用して両方の呼び出しを連鎖しました。つまり、最初のマップ呼び出しはl、ヘルパー関数の宣言後に呼び出された場合でも、長さ変数を正しく設定しますs。-4バイト。
  • 複数行の文字列を乱用\nして実際の改行に置き換え、さらにif三項演算子を使用したちょっとしたトリック(値joinを持つ配列で呼び出されると、nil空の文字列になります)
  • .join明らかにに置き換えることができ*ます。

今すぐ修正すべきだと思いますか?
バリューインク

これは94でどのようにラップしますか?
ベン

さて、コードを処理する時間が増えたので、適切にラップしました。
値インク

「説明の長さには制限はありませんが、区切り文字とコードの最大長は93 - 5 = 87charsのみです。5文字は、コードと区切り文字の間のスペースです。コードと区切り文字は、少なくとも1文字以上です。」コードセクションは97文字という制限をはるかに超えているため、プログラムの動作は未定義です。
バリューインク

ああ、よく見分けられます、理にかなっています!
ヴェン

9

LiveScript、243 236 233 228 219 225バイト

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

仕組み:主にJavaコードに似ています。エイリアスの長さから始めます(LiveScriptでは、括弧を使用して演算子から関数を作成できます)。 .=であるa = a.b-私たちはマップするために、ここで使用しています。

=> blabla ..Smalltalk風のカスケード構造です。ブロックの残りの部分について=>は、左側にアクセスできます..。返されます。ここでは、kで分割された要素です。注:文字列補間を使用/しています。これは、リテラル文字列で「分割」するだけだからです。

LSではa-=/regexp/、このラムダでも使用できます(文字列リテラルでも機能します)。これは、.replace呼び出しのための単なるシュガーです。

最後に、>?=>?-assin 組み合わせ演算子であり、2つのオペランドのうち大きい方を返します。

LSには内包表記用のPython / Haskellスタイルがありますが、スペースを十分に長く繰り返す「string * times」を除いて、それらに凝ったものはありません。

理解のためにこれがトピックとして機能します(カスケードについてのブロックを参照してください)。

次に、配列の各要素(内包したばかりの要素)にループし、いずれかの行が93charsより大きい場合、最後のインデックスを見つけ、そこで分割し、この現在の反復の直後に分離した行をプッシュします( ...そのため、行が大きすぎる場合、次の反復が再び分割されます)。

唯一の最後の空想は、a[j to](jから終わりまで)の範囲であるが、それは配列のメソッドを使用していますので、我々は我々が過負荷に使用して行う文字列に戻ってそれに参加する必要があり**''

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

出力:

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
誰にダウン票を投じたとしても、答えは決まっています。
2016年

2
説明がオーバーフローした場合、区切り文字を残りのIIRCに合わせるために新しい行が必要です。
値インク

@KevinLauはよく見つけて修正しました!
ヴェン

サンプル出力も更新できますか?
バリューインク

@KevinLauできました。
2016年

6

Java、347 + 19 = 366バイト

が必要です

import java.util.*;

したがって、+ 19バイト。

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

形式を取りますf.accept(List<String> code, String seperator)。インプレース形式。新しいものを作成して返すバージョンはList<String>実装するのは簡単ですが、数バイトかかります。

インデント+使用例:

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

...おそらくこれを自分自身で実行する必要があります:


なぜ機能しreplace(" *"+s)ていないのかを誰でも理解できるが、replaceAll(" *"+s)それを聞きたいのであれば、それを理解することはできません。
CAD97

<badguess> replaceは文字列を使用しますがreplaceAll、正規表現を使用します。</ badguess>
CalculatorFeline

@CatsAreFluffyまあ、あなたは正しい!どのように私はそれを実現しなかったかわからない:P
CAD97

改行を削除できませんか?
電卓

(.Sことが、何でもべきである)S:まあ改行があるために必要な半を除去することができます
CalculatorFeline

2

PowerShellの、224の 217 235バイト

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}

最大コード文字列の長さを決定するロジックを更新しました。正規表現のメタ文字を含む複数の区切り文字を許可するように更新されました。


少し説明

これは、入力用に改行で区切られた文字列全体を取り込みます。

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
}

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更新がより良い解決に役立つことを願っています。
マット

@nimiあなたが間違っていることに気づいた他に何かありますか?私は最後の数日間の読み取りに問題があるようです。
マット

いいえ。今は+1です。
nimi

1

MATLAB、270 265 262バイト

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

プログラムは、Iセル配列の各要素が入力の個別の行である文字列のセル配列の形式で入力を受け入れます。また、コメント文字が何であるか(つまり#)を示す2番目の入力も受け入れます。この関数は、適切にフォーマットされた複数行の文字列を返します。

簡単な説明

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

入力例

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,'#'));

出力例

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.