タブ対宇宙戦争を終わらせる


24

タブ対宇宙戦争を終わらせる

そのため、タブを使用するかスペースを使用してコードをインデント/フォーマットするかについて、多くの議論がありました。信じられないほどクレイジーな独自の書式設定方法に 進むことで、大学が紛争を解決するのを助けることができますか


あなたの仕事は、すべてのタブを4つのスペースに展開する完全なプログラムまたは機能を作成することです。そして、n個の先行スペースの連続を「/(n-ここに2つの星)/」で置き換えます。任意の妥当な形式で複数行の入力を受け取ります(新しい行ごとに文字列の単一文字列配列。列配列など)。

サンプル入力は恥ずかしく盗まれました。タブはSEでは自動的に4つのスペースに展開されるため、「^」文字として表しますが、タブ(コードポイント0x09)も処理する必要があります。すべての「^」文字は表を表します。

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
    Not zero so multiply by 256 again to get 65536
    [>++++<-]>[<++++++++>-]<[>++++++++<-]
    +>[>
        # Print "32"
        ++++++++++[>+++++<-]>+.-.[-]<
    <[-]<->] <[>>
        # Print "16"
        +++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
    # Print "8"
    ++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
^this is preceded by a tab
^^two tabs
^^^three tabs etcetera! 

サンプル出力

Calculate the value 256 and test if it's zero
If the interpreter errors on overflow this is where it'll happen
++++++++[>++++++++<-]>[<++++>-]
+<[>-<
/**/Not zero so multiply by 256 again to get 65536
/**/[>++++<-]>[<++++++++>-]<[>++++++++<-]
/**/+>[>
/******/# Print "32"
/******/++++++++++[>+++++<-]>+.-.[-]<
/**/<[-]<->] <[>>
/******/# Print "16"
/******/+++++++[>+++++++<-]>.+++++.[-]<
<<-]] >[>
/**/# Print "8"
/**/++++++++[>+++++++<-]>.[-]<
<-]<
# Print " bit cells\n"
+++++++++++[>+++>+++++++++>+++++++++>+<<<<-]>-.>-.+++++++.+++++++++++.<.
>>.++.+++++++..<-.>>-
Clean up used cells.
[[-]<]l
/**/this is preceded by a tab
/******/two tabs
/**********/three tabs etcetera! 

大学にはVimとEmacsの両方をダウンロードするためのスペースが必要なので、コード用のストレージはほとんど許可されません。したがって、これはあり、最短のコードが優先されます。入力が整形式であり、スペースが4つ未満の行(タブの置換後)が未定義の動作を引き起こす可能性があると想定できます。

免責事項

この「優れた」フォーマット戦略はGeobitsの好意によるものであり、彼の許可を得て複製されています。この課題の作成中にプログラマーに害はありませんでした。


1
タブは行の先頭にのみ(つまり、インデントとして)表示されますか?行に混在したインデント(タブ+スペース)を使用できますか?
リン

20
誰かがホワイトスペースで書かれた答えを提出してください。
GuitarPicker

2
で始まる行を考慮する/*必要がありますか、それとも「整形式の入力」ではないと想定できますか?C ++ソースファイルは、複数行コメント/* */が先頭のスペースと最初のスペースの最後をで置き換えるいくつかの答えを破壊し、/その後スペースで埋めることを進めるため、より良いテストでした*
seshoumara

1
戦争は終わった:medium.com/@hoffa/…(Cでプログラミングしているのでなければ、どうやら。)
ビーカー

1
@RohanJhunjhunwalaそれでは、コンパイル可能なコードに関するものではないので、最初の質問をもう一度します。同じ/* */C ++コードを想像してください。ただし、今回は行の先頭にあります。仕様によると、そのままにしておく必要があります。/\** ///の間にあるスペースをアスタリスクで埋めるために使用されるsayのような正規表現は、行をに変えてしまうというトラップがあります/***/。私もこの変換を見てきました/*//*/。両方とも間違っていると思います。
seshoumara

回答:


2

V21、20のバイト

Íô/    
Î^hr/hv0r*r/

オンラインでお試しください!

これは文字通り、私のvimの答えの直接的なポートです。注目すべき違い:

  • Íコマンド(グローバル代替)が自動的に埋める/g2つのバイトを保存フラグ

  • ô と同じです \t

  • Îのニーモニックであり:%norm:%normキーストロークとキーストロークのセットの間の必要なスペースも埋めます。

  • 末尾のキャリッジリターンが暗黙的に追加されます。


27

VIM、37、34、33、 32のバイト

:%s/\t/    /g|%norm ^hr/hv0r*r/

オンラインでお試しください!

これには、オンラインインタープリターではなく、vimで末尾のキャリッジリターン(enter)が必要であることに注意してください。

下位互換性があるため、これはVインタープリターを使用します。非常に簡単なソリューション。

解決策をリアルタイムで確認できるgifを次に示します。これは少し古いバージョンを使用しており、実行速度を遅くするために追加のキーストロークを追加して、何が起こるかを確認できるようにしました。

ここに画像の説明を入力してください

そして、それがどのように機能するかの説明です:

:%s/\t/    /g           "Replace every tab with 4 spaces
|                       "AND
%norm                   "On every line:
      ^                 "  Move to the first non-whitespace char
       h                "  Move one character to the left. If there is none, the command will end here.
         r/             "  Replace it with a slash
           h            "  Move to the left
            v0          "  Visually select everything until the first column
              r*        "  Replace this selection with asterisks
                r/      "  Replace the first character with a slash

使用するために+1するつもりでしたgが、とにかくg:/ +1を使用しないように編集しました:D
Downgoat

@downgoatハハ、ありがとう!:gあまり知られていない機能を悪用しているため、このバージョンがないことを誇りにnorm思ってい^F<space>ます。失敗するとコマンドがキャンセルされます。だから、:%norm ^F<space>foo基本的に同じものである:g/^ /norm foo楽しいVimのハック。:D
DJMcMayhem

ハァッ、^ Fがスクリーンの位置を決めるのに使われたと思った。内部で異なる動作をしますかnormますか?
ダウンゴート

1
@downgoatハハ、いいえ^F<C-f>Silly Vimのキー表記ではありません。この場合、それはで^、最初の非空白文字にジャンプし、F<space>Whichはカーソルの後ろの最初のスペースを見つけます。
DJMcMayhem

ああ、それは今では非常に理にかなっている> _>
Downgoat

11

Perl、41バイト

s,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,

次の-pようにフラグを指定して実行します。

perl -pe 's,␉,    ,g;s,^  ( +),/@{[$1=~y| |*|r]}/,'
#     ↑   └───────────────────┬───────────────────┘
#     1 byte               40 bytes

タブに置き換えます(Bashで、と入力してみてくださいControl-V Tab


1
その方法perlは、その後方参照をその場で置き換えましたsed。私もそれを望んでいました。
seshoumara

7

チェダー60 57 56バイト

@Conor O'Brienのおかげで3バイト節約

@.sub(/\t/g," "*4).sub(/^ +/gm,i->"/"+"*"*(i.len-2)+"/")

チェダーの文字列の書式設定を改善したい

オンラインでお試しください!

説明

これは機能です。@は、機能化されたプロパティ(例:ruby's &:)を表し、次のようなことができます: `ar.map(@。head(-1))

@                      // Input
 .sub( /\t/g, " "*4)   // Replace tabs with four spaces
 .sub(
   /^ +/gm,            // Regex matches leading spaces
   i ->                // i is the matched leading spaces
     "/"+              // The / at the beginning
     "*"*(i.len-2)+    // Repeat *s i-2 times
     "/"                // The / at the end
 )

正規表現に慣れていない場合:

/^ +/gm

これは基本的に、すべての()行()の先頭()で1つ以上の(+)スペース()に一致しました。^gm


リテラルタブはチェダー正規表現で機能しますか?また、/^ +/先頭のスペースの長さは少なくとも4になると想定できるため、正規表現として十分です。
コナーオブライエン

@ ConorO'Brien彼らはそうだと思うが、私はテストしていない
-Downgoat

タブは、変換の前に置き換えられることになっています。
コナーオブライエン

@ ConorO'Brien oh> _>私はもともとそれをそのままにしていて、それから変更しました
-Downgoat

6

Mathematica、97バイト

a=StringReplace;a[a[#,"\t"->"    "],StartOfLine~~b:" "..:>"/"<>Table["*",StringLength@b-2]<>"/"]&

匿名関数。入力として文字列を受け取り、出力として文字列を返します。


5

Python 3、124バイト

古き良き正規表現を使用します。

import re
lambda I:re.sub('^\s*(?m)',lambda m:'/'+'*'*len(m.group()[:-2])+'/',re.sub('\t+',lambda g:' '*4*len(g.group()),I))

できた!


4

Java 210 207バイト

これは、それを単純に実装する参照ソリューションです。

void a(String[]a){for(String s:a){s=s.replaceAll("\t", "    ");String x,y="";int j,i=s.length()-(x=s.replaceAll("^\\s+", "")).length();if(i>3){y="/";for(j=0;j++<i-1;)y+="*";y+="/";}System.out.println(y+x);}}

6
Vim:37バイト、Cheddar:65バイト、JavaScript:75バイト、Javaが210バイトにある:Pなぜ驚かないのか
-Downgoat

1
javaの非常に簡潔なコード:P
Rohan Jhunjhunwala

最後のforループを変更して、1バイトを節約できますfor(int j=0;++j<i-1;)。また、あなたは削除することができますint 前にj、すでに存在int型の後にそれを置く:int i=s.length()-(x=s.replaceAll("^\\s+", "")).length(),j;
ケビンCruijssen

(a)-> {...}を使用してバイトを削るのはラムダにできませんか?
bunyaCloven

少なくともそれはまだ読みやすく、コメントを追加する必要はありません:o)
ルネ

3

JavaScript ES6、75バイト

s=>s.replace(/\t/g,"    ").replace(/^ +/gm,k=>`/${"*".repeat(k.length-2)}/`)

\tコード内のリテラルタブに置き換えます。


3

Javaの、185の 184 167 152バイト

S->S.map(s->{s=s.replace("\t","    ");String t=s.replaceAll("^ +","");int n=s.length()-t.length();if(n>3){s="/";for(;n-->2;)s+="*";s+="/"+t;}return s;})

最初の投稿で与えられた文字列配列の非常に緩やかな定義を考えると、Stream<String>結果としてバイトを節約できるものを使用しました。

同じ目標を達成するために、RIとは異なる手法を使用しました。アルゴリズム自体はかなり同じです。

テストと未使用

import java.util.Arrays;
import java.util.stream.Stream;

public class Main {

  public static void main(String[] args) {
    StringStreamTransformer sst = lines -> lines.map(line -> {
      line = line.replace("\t","    ");
      String trimmed = line.replaceAll("^ +", "");
      int startingSpaces = line.length() - trimmed.length();
      if (startingSpaces > 3) {
        line = "/";
        for(;startingSpaces > 2; startingSpaces--) {
          line += "*";
        }
        line += "/" + trimmed;
      }
      return line;
    });


    Stream<String> lines = Arrays.stream(new String[]{
      "lots of spaces and tabs after\t\t    \t\t         \t\t\t\t\t",
      "no space",
      " 1 space",
      "  2 spaces",
      "   3 spaces",
      "    4 spaces",
      "     5 spaces",
      "      6 spaces",
      "       7 spaces",
      "        8 spaces",
      "\t1 tab",
      "\t\t2 tabs",
      "\t\t\t3 tabs"
    });
    sst.map(lines).map(s -> s.replace(" ", ".").replace("\t","-")).forEach(System.out::println);


  }
}



2

SED(-rの場合は56 + 1)57

s/⇥/    /g;tr;:r;s,^ ( *) ,/\1/,;T;:l;s,^(/\**) ,\1*,;tl

タブはどこですか
1.タブをスペースに置き換えます。
2.最初と最後の先行スペースをに置き換え/ます。
3. /と0+ *sの後の最初のスペースを*、一致するまでaに置き換えます。


sedが指定されているため、他のsed回答から-r ''を削除するのと同じように、コードを単一引用符で囲む必要はありません。スクリプトはで実行するソースファイルに格納されているとみなすことができるためです-f。nやrのように使用される追加のフラグは、それぞれ1バイトとしてカウントする必要があります。したがって、ここでは、2バイトを節約します。
seshoumara

それは私が考えていたことですが、私は確かにしたいです。ありがとう。
ライリー

;tコマンドの後も必要ありません。コード自体については、3番目のsコマンドの先頭に^が必要です。それ以外の場合、この「3/5」のような入力は「3 / * 5」に変換されます。最初のsコマンドでは実際にタブがありますが、正しく表示されず誤解を招く可能性があるため、\ tを使用するか、charがタブであることを指定します。
seshoumara

@seshoumaraありがとう、電話から投稿しようとしています...簡単なことではありません。
ライリー

他のすべてを組み合わせたよりも、この回答の編集に多くの時間を費やしたと思います。助けてくれてありがとう!
ライリー

1

大学は、Emacs Lispのプログラムにもう少しスペースを許可することを検討する必要があります(またはデフォルトでtabifyanduntabify、Javaよりもさらに冗長になる単独のがあります。また、識別サイズが4未満の学生(または教師)や、C言語に似ていない言語でコーディングを行う学生にも注意を払う必要があります。

次のソリューションには206バイトがあります

(lambda (b e)(let((tab-width 4))(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))))))

tab-widthこれを明示的に設定する必要がないと仮定すると、20個保存できます。

(lambda(b e)(untabify b e)(goto-char b)(while(re-search-forward"^ +"e t)(replace-match(format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2))))))))

そして、無料版は次のようになります

(defun end-tab-war (beg end)
  (let ((tab-width 4))
    (untabify beg end)
    (goto-char beg)
    (while (re-search-forward "^ +" end t)
      (replace-match
       (format
        "/%s/"
        (apply 'concat
               (mapcar (lambda(x) "*")
                       (number-sequence 1
                                        (- (length (match-string 0))
                                           2)))))))))

untabify開始点にジャンプする前に、まず領域を指定します。次に、行の先頭に空白が表示されている間に、その空白と同じ長さのコメントに置き換えます。正確には、挿入されるコメントは次のように構築されます

 (format"/%s/"(apply'concat(mapcar(lambda(x)"*")(number-sequence 1(-(length(match-string 0))2)))))

それ自体は97バイトを占有します。いくつかの文字列をn回コピーするためのより短い解決策が高く評価されています。


1

Ruby、52 47 + 1(pフラグ)= 48バイト

編集:Value Inkのおかげで5バイト全体を保存しました

ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'

1
pフラグを使用して、(g)sub $_が印刷された値を変更し、変更するという事実を利用できますか?ruby -pe 'gsub ?\t," "*4;sub(/^ +/){?/+?**($&.size-2)+?/}'
バリューインク

おかげで、私は(g)sub強打なしで$_ここで変更できることを知りませんでした。
ミッチャウ

1

GNU sed、66 64 + 1(rフラグ)= 65バイト

編集:ライリーの提案のおかげで1バイト少なくなりました。

s/\t/    /g
s,^ ( *) ,/\1\n,
:
s,^(/\**) ( *\n),\1*\2,
t
s,\n,/,

実行: sed -rf formatter.sed input_file

\nその行の残りのテキストから先頭のスペースで区切る理由は、そうしないと、このようなコメントで始まるC ++行が、または4などのより単純な行で/* */変換さ/*****/れるためです。sedは各入力行に対してスクリプトを実行するため、読み取り時にパターンスペースにno が導入されます。s,^(/\**) ,\1*,s,^(/\**) ( */),\1*\2,\n


/を置き換えるまで閉じないでバイトを保存できます\n。これにより、4行目で一致させる必要が
ライリー

@Riley良いキャッチ。コードを更新しました。
seshoumara

\tタブ文字で置き換えることにより、別のものを保存できます。
ライリー

@Rileyそれは本当ですが、ここではタブとして印刷されないので、私は疑っています。バイトカウントがより競争力のある将来のsedの回答のために、これを念頭に置いておきます。
seshoumara
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.