「tac」の実装:ファイルの行を逆順に印刷します


30

子猫の質問からU&Lでsed魔法についてのこの質問を見るまで、実装はtacどうですか?


目的

ファイル内の行を反転して印刷するプログラムを実装します。


入力

名前として、または標準入力を介して提供されるファイル


出力

行を反転し、標準出力にします。


得点

ソースコードのバイト。


9
tac後続の改行については少し奇妙です。これは、変換a\nb\nに(後続の改行)b\na\na\nbに(末尾の改行を) ba\n。これは私たちのコードがどのように動作するはずですか?
デニス


10
また、tacの動作を再現する必要がある場合、実行される3バイトのBash応答tacは時間の問題にすぎません
デニス

1
この時点で@Dennisは未定義のままにしておくのがおそらく最善です。
ニックT

1
@デニスは私にとって理にかなっています。ファイルの行を、すべてがで終わる水平行として視覚化し\nます。tacこれらの行の順序を逆にします。\nファイルの中央からan が削除されると、終了した行は次の行に結合されますが、最後の行の場合、結合する次の行はありません。
ブラックライトシャイニング

回答:


15

GS2、3バイト

* +

3バイトは、順番に、ラインの分割、リバース、およびラインの結合です。


9

Perl、11バイト

$\=$_.$\}{

とまったく同じように動作しtacます。このコードには-pスイッチが必要ですが、1バイトとしてカウントしています。

テスト実行

$ echo -en 'a\nb' | perl -pe'$\=$_.$\}{' | xxd -g 1
0000000: 62 61 0a                                         ba.
$ echo -en 'a\nb\n' | perl -pe'$\=$_.$\}{' | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

使い方

ここで説明したように、-pスイッチは基本的while (<>) { ... ; print }にプログラムをラップするため、ソースコードは

 while(<>)
 {
   $\ = $_ . $\
 }
 print

入力の各行について、現在の行($_)を$\(最初は未定義)に追加し、結果で後者を更新します。

すべての行が処理された後print、ローカル変数の値$_(このスコープでは未定義)を出力し、その後に出力レコード区切り文字($\)を続けます。


これがどのように機能するかを説明することに注意してください?
xebtl

2
@xebtl悪。-pスイッチを追加すると、コードが開始while(<>){および終了するループにラップ} continue { print }され、変更するだけで入力をフィルタリングできます$_$\=$_.$\入力の各行を出力レコードターミネータの先頭に追加し}{、perlが提供するwhileブロックを途中で終了するため、continueブロックはブロックにアタッチされなくなります。したがって、すべての入力行は$\逆の順序で追加され、最後にcontinue { print }最終的に実行され、「なし」($_入力の終了後にundefになります)が出力されますが、ターミネータがあり$\ます。
ホッブズ

@xebtl grr、コメント内のコードの書式設定は、バックスラッシュとバッククォートが互いに近づくと少し壊れているようです。おそらく、私が言おうとしていたことを推測できるでしょう。
ホッブズ

1
@primo最初の例は、この場合に何が起こるかを示しています。出力は奇妙ですが、tacのようになります。
デニス

1
@Dennisはこの本の
msh210

8

Pyth、4バイト

j_.z

.zリストとして行で区切られた入力_であり、それを逆jにして、文字(デフォルトでは)で結合します\n



7

網膜、7バイト

!rm`.*$

単一の正規表現を使用すると、Retinaは一致モードで実行されます。通常、これは単に一致の数!を印刷しますが、実際の一致を代わりに(改行で区切って)印刷するように構成します。

実際の正規表現は単に.*$です。改行以外の任意の文字と一致できる.*ため、任意の行(空の可能性がある)に.一致します。すぐに行きます$

マッチを逆に印刷する方法は?.NETの右から左へのマッチングモードを利用することにより、r。これは、一致を検索するときに正規表現エンジンが文字列の最後から開始し、逆方向に動作することを意味します。

最後に、m作る$試合終了ラインの代わりに、文字列の末尾のを。なぜそれが必要なのでしょうか?問題は、.*無関係な一致を生成することです。正規表現の置換を検討する

s/a*/$0x/

入力に適用されますbaaababaa。あなたはこれがもたらすと思うでしょうbaaaxbaxbaaxが、それは実際にあなたに与えますbaaaxxbaxxbaaxx。どうして?aaaエンジンのカーソルを一致させた後、aとの間にあるためbです。これでa、これ以上sと一致することはできませんa*が、空の文字列でも満足されます。これは、一致するたびに別の空の一致が得られることを意味します。

追加の空行が導入されるため、ここではそのようなことはしたくないので、一致に次の行の終わりを含めることを要求することにより、これらの無関係な一致(右から左へのモードにより行の先頭にある)を破棄しますこの線。


6

Haskell、34バイト

main=interact$concat.reverse.lines

[編集]

に置き換えunlinesて1バイトを保存しましたconcat


4

CJam、7バイト

qN/W%N*

stdinを読み取り、stdoutに出力します。

説明:

q       Get input.
N/      Split at newlines.
W%      Reverse list.
N*      Join with newlines.


4

Befunge-93、17バイト

~:1+!#v_
>:#,_@>$

ここで空想はありません。スタックにすべてを置いて、それをポップします。


4

Pure Bash(外部ユーティリティなし)、56

mapfile a
for((i=${#a[@]};i--;));{
printf %s "${a[i]}"
}

これはtacデニスのコメントで尋ねられているように、正確なエミュレーションを行うための数少ない答えの1つです。

$ echo -en 'a\nb' | ./tacemu.sh | xxd -g 1
0000000: 62 61 0a                                         ba.
$ echo -en 'a\nb\n' | ./tacemu.sh | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.
$ 

素敵で感動的です。
マナトワーク


4

JavaScript(SpiderMonkey Shell)、38バイト

[...read(readline())].reverse().join``

ものすごく単純


read() ファイルを読み取ります

readline() STDINから文字列を読み取ります

[...str]strをcharの配列に分割します

reverse() 配列を逆にします

join`` 配列を文字列に折りたたみます


4

Python 2、52バイト

import sys;print''.join(sys.stdin.readlines()[::-1])

1
input()はstdinから1行を読み取りませんか?
リン

@Maurisが編集
ベータ崩壊

どうimport sys;print sys.stdin.read()[::-1]
ダイエット

@dieterそれは各キャラクターを反転し、チャレンジは反転する行だけを要求します
ベータ崩壊

大丈夫-注意深く読んでいない、ごめんなさい
ディーター

4

C#、179 171バイト

using B=System.Console;class A{static void Main(){var a=new System.Collections.Stack();string b;while((b=B.ReadLine())!=null)a.Push(b);foreach(var c in a)B.WriteLine(c);}}

行を読み取り、スタックに配置してから、逆方向に書き込みます。これにはMathematicaを使用しますが、EOFの意味はありません。


3

sed、9バイト

1!G;h;$!d

賛成票は必要ありません。これは有名なsedワンライナーです。


10
自分の作品でない場合は、回答コミュニティwikiを作成することをお勧めします。
リスト管理者


3

Powershell、41バイト

$a=$args|%{gc $_};[array]::Reverse($a);$a

ファイルの内容を1行ずつ保存しa、逆順にaして最終的に印刷します。




3

Bash、48 43文字

Digital TraumaBashの答えに触発されました。アイデアに対する賛成票は彼に渡されるべきです。)

mapfile -c1 -C's=$2$s;set'
printf %s "$2$s"

サンプル実行:

bash-4.3$ echo -en 'a\nb' | bash tac.sh | xxd -g 1
0000000: 62 61 0a                                         ba.

bash-4.3$ echo -en 'a\nb\n' | bash tac.sh | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

mapfile -c1 -Cf代わりにできると思いますmapfile -c1 -Cf a
デジタル外傷

正しい。また、私はそれを発見しました-C。まずそのトリッキーなものを試しました。
マナトワーク

3

GNU Awk、27文字

(に触発エド・モートンさんGNU awkの答え。CW、私は彼のソリューションをハイジャックすることを意図していないとして。)

{s=$0RT s}END{printf"%s",s}

変更していることに注意してくださいRTRSこれをこれは移植可能な標準のAwkになりますが、最終的な改行がないことを保持する機能が失わ。

サンプル実行:

bash-4.3$ echo -en 'a\nb' | awk '{s=$0RT s}END{printf"%s",s}' | xxd -g 1
0000000: 62 61 0a                                         ba.

bash-4.3$ echo -en 'a\nb\n' | awk '{s=$0RT s}END{printf"%s",s}' | xxd -g 1
0000000: 62 0a 61 0a                                      b.a.

「%s」を削除できます
ninjalj

@ninjalj、入力に「%」が含まれないと想定できる場合のみ。
マナトワーク

3

SNOBOL、42バイト

S S =INPUT CHAR(10) S :S(S)
 OUTPUT =S
END

2

Gema、25文字

*\n=@set{s;$0${s;}}
\Z=$s

サンプル実行:

bash-4.3$ echo -en 'a\nb' | gema '*\n=@set{s;$0${s;}};\Z=$s'
ba

bash-4.3$ echo -en 'a\nb\n' | gema '*\n=@set{s;$0${s;}};\Z=$s'
b
a


2

sed、7バイト

G;h;$!d

これは私にとっては有効です(他の場所では最も短い解決策です)が、その理由を知りたくありません。これを見つけるまで、私は有名な9バイトのトリックをいじりました。私は推測するG最初の行には何もしませんINGの?


2
実際には何かを行います。コードは出力の最後に余分な改行を生成します。(Gパターンスペースに改行とホールドスペースのコンテンツを追加します。空のホールドスペースのコンテンツを追加しても実際には無害ですが、改行は追加されます。)
manatwork

2

JavaScript(Node.js)、91バイト

console.log(require('fs').readFileSync(process.argv[2])+"".split(d="\n").reverse().join(d))

という意味console.log((require('fs').readFileSync(process.argv[2])+"").split(d="\n").reverse().join(d))ですか(92バイト)?現在のコードは行を反転しません。
歯ブラシ

2

Bash +一般的なユーティリティ、25

tr \\n ^G|rev|tr ^G \\n|rev

ここに ^GはリテラルですBEL文字です。入力は印刷可能なアスキーのみであると仮定しています。

これtrは、改行をBELで置き換えることにより入力全体を1行に変換し、revその行をtr削除してから、複数行に戻ってrev変換し、各行を再度削除して、目的の出力を取得します。


2

MATLAB、44

@(x) strjoin(fliplr(strsplit(x,'\n')),'\n');

文字列を改行で分割し、結果の配列を反転して、改行文字で再結合します。


2

ジュリア、65バイト

open(s->print(join(reverse([l for l=readlines(s)]),"")),ARGS[1])

これは、ファイルをコマンドライン引数として受け取り、その行を逆の順序で出力します。とは異なり、末尾の改行は前に移動しますtac、正当とは、ます。

ゴルフをしていない:

function p(s::Stream)
    # Create a vector of the lines of the input stream
    L = [l for l in readlines(s)]

    # Reverse the vector and join it back into a string
    j = join(reverse(L), "")

    # Print the string to STDOUT
    print(j)
end

# Open the file specified in the first command line argument
# and apply the function p to its contents
open(p, ARGS[1])

2

ピップ、3 + 2 = 5バイト

rおよびnフラグを使用します。stdinから読み取ります。

RVg

rフラグの行のリストとしてstdinと記憶読み出しg(通常コマンドラインARのリストであり、G S)。次に、そのリストを逆にすると、自動的に印刷されます。このnフラグにより​​、区切り文字として改行を使用してリストが出力されます。

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