タブを展開(expand(1)を実装)


10

今回のタスクは、expand(1)タブをスペースに展開するPOSIX ユーティリティのバリアントを実装することです。

あなたのプログラムが取ることですタブストップ仕様をし、その後に標準の入力を読んで、次のタブストップに到達するためのスペースの適切な量を入力してタブ文字を置き換えます。結果は標準出力に書き込む必要があります。

タブストップ仕様

タブストップ仕様は、単一の番号、またはタブストップのカンマ区切りリストのいずれかから成ります。単一の数値の場合は、その数の倍数がコンマ区切りのリストで発生したかのように繰り返されます(つまり4、として機能します4,8,12,16,20,...)。コンマ区切りリストの各エントリは、オプションで接頭辞が付いた正の整数です++プレフィックスは、コンマ区切りのリスト内の前の値に相対的な差を示しています。リストの最初の値は絶対値(つまり、プレフィックスなし)でなければなりません。タブストップは、次のスペース以外の文字の列(展開されたタブに続く)を指定し、左端の列を番号0と見なします。タブは常に少なくとも1つのスペースに展開する必要があります。

入出力

タブストップの指定は、プログラムの最初のコマンドラインパラメータとして使用するか、または標準の入力から(改行で終了する)入力の最初の行として読み取るかを自由に選択できます。タブストップが読み取られた後、EOFまでの残りの入力(前者の場合はすべての入力)が処理および拡張されます。拡張出力は標準出力に書き込まれます。

すべての展開されたタブストップ、およびすべての入力は、最大80列幅であると想定されます。すべての拡張タブストップは厳密に増加しています。


タブストップの指定4,6,+2,+8はと同等4,6,8,16であり、両方の入力がある

ab<Tab>c
<Tab><Tab>d<Tab>e<Tab>f

に展開されます(スペースを示します)

ab␣␣c
␣␣␣␣␣␣d␣e␣␣␣␣␣␣␣f

01234567890123456   (Ruler for the above, not part of the output)
          1111111

スコアリングは純粋なです。最短のコードが勝ちます。

回答:


2

GolfScript(77 75文字)

n/(','/{'+'/{~t++}*~:t}%81,{t*}%+:T;{[0\{.9={;T{1$>}?(.)@-' '*}*\)}/;]n+}/;

tabspecの構文解析にとても満足しています。

# Split on commas
','/
# For each element:
{
    # Split on '+'
    '+'/
    # We now have either ["val"] or ["" "val"]
    # The clever bit: fold
    # Folding a block over a one-element array gives that element, so ["val"] => "val"
    # Folding a block over a two-element array puts both elements on the stack and executes,
    # so ["" "val"]{~t++}* evaluates as
    #     "" "val" ~t++
    # which evaluates val, adds the previous value, and concatenates with that empty string
    {~t++}*
    # Either way we now have a string containing one value. Eval it and assign to t
    ~:t
}%

次に、80列の最後に到達するのに十分であることが保証されるまで、最後の要素の倍数を追加します。

81,{t*}%+

これにより、タブストップが1つだけ指定された場合に望ましい動作が得られます。それ以外の場合は、仕様で言及されていない場合にのみ関連します。(タブストップのリストが0に戻り、最後に解析された要素が繰り返されることに注意してください。ただし、リストの使用に関しては、現在の位置よりも大きい最初の要素を探すため、これは重要ではありません)。

残りはかなり簡単です。


2

ルビー161 145

入力の最初の行のタブストップ仕様を読み取ります。

i=t=[]
gets.scan(/(\+)?(\d+)/){t<<i=$2.to_i+($1?i:0)}
81.times{|j|t<<j*i}
while gets
$_.sub!$&," "*(t.find{|s|s>i=$`.size}-i)while~/\t/
print
end

編集:最後に読み取ったタブストップを繰り返す2行を追加し、単一の数字のタブストップ仕様も正しく機能するようにしました

i最後に解析されたタブストップを保持するための一時変数です。行tから解析されたタブタブのリストですgets.scan。目安として、最後に解析されたタブストップの81倍数を追加します。while getsループは、これ以上の入力がなくなるまでいっています。入力の各行について、スペースをタブに置き換えます。スペースを追加すると文字列が移動し、正しいタブストップを再計算する必要があるためです。


Rubyはよくわかりませんがx+($1?i:0)、短く書け$1?x+i:xますか?
Timwi、2014年

@Timwi Nope!Rubyは、3項演算子で少し奇妙です。通常、コロン(ので、あなたは、どこかにスペースを入れる必要がある:)もの初めにマークできたシンボルを、しかしシンボルは数字で始めることができないので、:0[OK]をスペースなしです。か何か。それは奇妙だ。括弧も重要なようです。
daniero 2014年

そのタブストップスキャンは私にはバグのように見えます。でt<<x+($1?i:0);i=x最初の文は変更されませんx、それをしませんか?私はあなたがそれを逆にする必要があると思いますi=x+($1?i:0);t<<i
ピーター・テイラー

1
実際、最初の2行を次のように置き換えることで、16を節約できますi=t=[]i最初に必要になることが保証されていないため)。タブストップ解析を{t<<i=$2.to_i+($1?i:0)}に簡略化し、l完全に削除します(iすでにその値を保持しています)。しかし、タブストップ厳密さの増加を気にしませ上の素敵な1:あなたの4つの文字を保存し、私はそれが2救うために借りることができます
ピーター・テイラー

@PeterTaylor入力ありがとうございます!それは直接バギーではなかったが、確かに少し肥大化した。このようなコードに目をつぶるのは簡単すぎると思います。
daniero 2014年

1

C、228文字

これは、物事を始めるためのCソリューションです。ここでやるべきことはまだたくさんあります(ifsとforsとputchars ... をすべて見てください)。例のテストケースと、だけでなく、同じ入力でテストが、4および8タブ仕様のため。

S[99],i;L,C;main(v){for(v=1;v;)v=scanf("+%d",&C),v=v>0?C+=L:scanf("%d",&C),
v&&(S[L=C]=++i,getchar());for(;i==1&&C<80;)S[C+=L]=1;for(C=L=0;C=~getchar();)
if(C+10)putchar(~C),L+=C+11?1:-L;else for(putchar(32);!S[++L];)putchar(32);}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.