Implementasikan "tac": Mencetak baris dari file secara terbalik


30

Antara pertanyaan kucing dan melihat pertanyaan ini di U&L tentang sedsihir, bagaimana dengan penerapannya tac?


Objektif

Menerapkan program yang akan membalikkan dan mencetak garis dalam file.


Memasukkan

File, disediakan sebagai nama atau melalui input standar


Keluaran

Garis, dibalik, ke standar keluar.


Mencetak gol

Byte kode sumber.


9
tacagak aneh ketika datang untuk mengikuti linefeeds. Ini mengubah a\nb\n(trailing linefeed) menjadi b\na\ndan a\nb(tidak ada trafeed linefeed) menjadi ba\n. Apakah ini bagaimana seharusnya kode kita berperilaku?
Dennis


10
Juga, jika kita harus meniru perilaku tac, jawaban Bash 3 byte yang dijalankan tachanya masalah waktu ...
Dennis

1
@Dennis pada titik ini mungkin lebih baik untuk tidak terdefinisi.
Nick T

1
@ Dennis Masuk akal bagi saya. Visualisasikan garis-garis file sebagai baris horizontal, semua diakhiri dengan \n. tacmembalik urutan baris ini. Jika suatu \ndihapus dari tengah file, baris yang diakhiri bergabung ke baris berikutnya, tetapi dalam kasus baris terakhir, tidak ada baris berikutnya untuk bergabung.
Blacklight Shining

Jawaban:


15

GS2, 3 byte

* +

Tiga byte adalah, secara berurutan, membagi garis, mundur, dan bergabung dengan garis.


9

Perl, 11 byte

$\=$_.$\}{

Berperilaku persis seperti tac. Kode ini membutuhkan -psakelar, yang telah saya hitung sebagai 1 byte.

Tes berjalan

$ 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.

Bagaimana itu bekerja

Seperti dijelaskan di sini , -pswitch pada dasarnya membungkus while (<>) { ... ; print }program, sehingga kode sumbernya setara dengan

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

Untuk setiap baris input, kami menambahkan baris saat ini ( $_) ke $\(awalnya tidak terdefinisi), memperbarui yang terakhir dengan hasilnya.

Setelah semua baris diproses, printcetak nilai variabel lokal $_(tidak ditentukan dalam lingkup ini), diikuti oleh pemisah catatan keluaran ( $\).


Mau jelaskan bagaimana ini bekerja?
xebtl

2
@ xebtl Evilly. Menambahkan -psakelar membungkus kode Anda dalam satu lingkaran yang dimulai while(<>){dan berakhir } continue { print }, yang memungkinkan pemfilteran input hanya dengan memodifikasi $_. $\=$_.$\menambahkan setiap baris input ke terminal catatan keluaran, dan }{ujung-ujung whileblok perl-dipasok secara prematur, sehingga continueblok tidak lagi melekat padanya. Jadi semua baris input ditambahkan ke $\dalam urutan terbalik, kemudian pada continue { print }akhirnya berjalan, mencetak "tidak ada" ( $_akan undef setelah akhir input), tetapi dengan terminator dari $\.
hobbs

@xebtl grr, pemformatan kode dalam komentar tampaknya agak rusak di mana backslash dan backtick saling berdekatan. Mungkin Anda bisa menebak apa yang ingin saya katakan.
hobbs

1
@ primo Contoh pertama menunjukkan apa yang terjadi dalam kasus ini. Outputnya akan aneh, tapi persis seperti tac.
Dennis

1
@Dennis halaman 18 ff buku ini
msh210

8

Pyth, 4 byte

j_.z

.zadalah input yang dipisahkan oleh garis sebagai daftar, _membalikkannya dan jmenggabungkannya dengan karakter, yang secara default adalah \n.



7

Retina , 7 byte

!rm`.*$

Dengan satu regex, Retina berjalan dalam mode Match. Ini biasanya hanya mencetak jumlah kecocokan, tetapi dengan !kami mengkonfigurasinya untuk mencetak kecocokan yang sebenarnya sebagai gantinya (dipisahkan oleh baris baris).

Regex sebenarnya hanyalah .*$. .*cocok dengan baris apa saja (berpotensi kosong), karena .dapat cocok dengan karakter apa pun kecuali umpan baris. Saya akan ke $dalam sebentar lagi.

Bagaimana kita membuatnya mencetak pertandingan secara terbalik? Dengan memanfaatkan mode pencocokan kanan-ke-kiri .NET, diaktifkan dengan r. Ini berarti mesin regex mulai di akhir string ketika mencari yang cocok dan bekerja mundur.

Akhirnya, mbuatlah yang $cocok dengan akhir baris, bukan akhir dari string. Mengapa kita membutuhkan itu? Masalahnya adalah .*menghasilkan kecocokan yang asing. Pertimbangkan substitusi regex

s/a*/$0x/

diterapkan pada input baaababaa. Anda akan berpikir ini akan menghasilkan baaaxbaxbaax, tetapi sebenarnya memberi Anda baaaxxbaxxbaaxx. Mengapa? Karena setelah mencocokkan aaakursor mesin adalah antara adan b. Sekarang tidak dapat lagi cocok dengan as, tetapi a*juga puas dengan string kosong. Ini berarti, setelah setiap pertandingan Anda mendapatkan pertandingan kosong yang lain.

Kami tidak ingin itu ada di sini, karena itu akan memperkenalkan baris kosong tambahan, jadi kami membuang kecocokan yang asing (yang berada di awal garis, karena mode kanan-ke-kiri) dengan mengharuskan kecocokan mencakup akhir garis.


6

Haskell, 34 byte

main=interact$concat.reverse.lines

[sunting]

Disimpan satu byte dengan mengganti unlinesdengan concat.


4

CJam, 7 byte

qN/W%N*

Membaca stdin, mencetak ke stdout.

Penjelasan:

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


4

Befunge-93, 17 byte

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

Tidak ada yang mewah di sini; cukup letakkan semuanya di tumpukan, lalu lepas.


4

Bash Murni (tidak ada utilitas eksternal), 56

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

Ini adalah salah satu dari sedikit jawaban untuk melakukan tacpersaingan yang tepat , seperti yang ditanyakan dalam komentar Dennis :

$ 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.
$ 

Bagus dan menginspirasi .
manatwork


4

JavaScript (SpiderMonkey Shell), 38 byte

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

Cukup mudah


read() membaca file

readline() membaca string dari STDIN

[...str]akan membagi str menjadi array karakter

reverse() akan membalikkan array

join`` akan collpase array menjadi string


4

Python 2, 52 byte

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

1
Tidakkah input () membaca satu baris dari stdin?
Lynn

@Mauris Diedit itu
Beta Decay

Bagaimana dengan import sys;print sys.stdin.read()[::-1]?
diet

@dieter Yang membalikkan setiap karakter, tantangannya hanya meminta garis untuk dibalik
Beta Decay

ok my bad - Tidak membacanya dengan cermat, maaf
dieter

4

C #, 179 171 byte

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

Membaca baris, menempatkannya di tumpukan, dan kemudian menulisnya mundur. Saya akan menggunakan Mathematica untuk ini, tetapi tidak memiliki arti EOF.


3

sed, 9 byte

1!G;h;$!d

Tidak ingin upvote, ini adalah sed-liner terkenal.


10
Jika ini bukan karya Anda sendiri, saya sarankan Anda membuat komunitas wiki jawaban.
lirtosiast


3

Powershell, 41 byte

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

Menyimpan konten file baris demi baris a, membalikkan adan akhirnya mencetaknya.



3

Burlesque , 6 byte

ln<-uN

lnmemisahkan garis, <-membalikkan, uNmenggabungkan garis dan format untuk keluaran mentah.


3

Bash, 48 43 karakter

(Terinspirasi oleh Digital Trauma 's Bash jawaban . Upvotes untuk ide harus pergi ke dia.)

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

Contoh dijalankan:

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.

Saya pikir Anda bisa melakukan mapfile -c1 -Cfbukan mapfile -c1 -Cf a.
Trauma Digital

Benar. Sementara itu, saya juga menemukannya, hanya mencoba sesuatu yang rumit -Cdulu.
manatwork

3

GNU Awk, 27 karakter

(Terinspirasi oleh Ed Morton 's GNU AWK jawaban . CW karena saya tidak dimaksudkan untuk membajak solusinya.)

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

Perhatikan bahwa dengan mengubah RTRSini menjadi Awk standar portabel tetapi kehilangan kemampuan untuk mempertahankan ketiadaan baris baru final.

Contoh dijalankan:

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.

Anda dapat menghapus "% s"
ninjalj

@ninjalj, hanya jika kita dapat berasumsi bahwa input tidak akan pernah mengandung "%".
manatwork

3

SNOBOL, 42 byte

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

2

Gema, 25 karakter

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

Contoh dijalankan:

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 byte

G;h;$!d

Ini bekerja untuk saya (dan ini solusi terpendek di tempat lain), tetapi saya tidak benar-benar ingin mencari tahu mengapa. Saya hanya bermain-main dengan trik 9-byte yang terkenal sampai saya menemukan ini. Saya kira Gbaris pertama tidak melakukan apa-apa?


2
Sebenarnya melakukan sesuatu: kode Anda menghasilkan baris baru ekstra di akhir output. ( Gmenambahkan baris baru dan konten ruang pegang ke ruang pola. Sementara menambahkan konten ruang pegang kosong memang tidak berbahaya, baris baru masih ditambahkan.)
manatwork

2

JavaScript (Node.js), 91 Bytes

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

Apakah maksud Anda console.log((require('fs').readFileSync(process.argv[2])+"").split(d="\n").reverse().join(d))(92 byte)? Kode Anda saat ini tidak membalikkan garis.
Sikat gigi

2

Bash + utilitas umum, 25

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

Ini ^Gadalah literalBEL karakter . Saya berasumsi inputnya hanya ascii yang bisa dicetak.

Ini transforms seluruh input ke satu baris dengan mengganti baris baru dengan BELs, kemudian reverses baris itu, kemudian transforms kembali ke multiline, kemudian reverses setiap baris lagi, untuk mendapatkan output yang diinginkan.


2

MATLAB, 44

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

Pisahkan string di baris baru, membalik array yang dihasilkan, kemudian bergabung kembali dengan karakter baris baru.


2

Julia, 65 byte

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

Ini mengambil file sebagai argumen baris perintah dan mencetak barisnya dalam urutan terbalik. Baris baru yang tertinggal dipindahkan ke depan, tidak sepertitac , yang sah.

Tidak Disatukan:

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

Pip , 3 + 2 = 5 byte

Menggunakan rdan nbendera; dibaca dari stdin.

RVg

The rbendera membaca stdin dan menyimpannya sebagai daftar baris dalam g(yang biasanya daftar baris perintah ar g s). Kami kemudian membalik daftar itu, dan itu dicetak secara otomatis. The ndaftar penyebab bendera untuk menjadi output dengan baris baru sebagai pemisah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.