Penomoran baris - implement nl

13

Tugas Anda adalah mengimplementasikan program yang mirip dengan nlalat baris perintah dari utilitas inti GNU.

Celah standar dilarang.

Anda tidak boleh menggunakan fungsi, program, atau utilitas internal atau internal apa saja untuk memberi penomoran pada baris file atau string, seperti nlitu sendiri atau =perintah dalam GNU sed.

Spesifikasi

Memasukkan

Program menerima nama file sebagai argumen. Kode Anda tidak harus cross-platform; format nama file OS yang menjalankan kode harus digunakan, yaitu jika Anda kebetulan menggunakan Windows, pemisah direktori bisa \atau /.

Anda harus dapat mengambil 64 file input, termasuk -jika ditentukan. Jika lebih dari 64 diberikan, hanya menangani 64 yang pertama.

Dalam daftar nama file, -merupakan input standar.

Jika nama file diberikan, baca dari file sesuai urutannya dan gabungkan isinya, masukkan baris baru antara masing-masing dan di akhir. Jika Anda tidak dapat membaca dari satu atau beberapa nama file (karena file tersebut tidak ada atau Anda tidak memiliki izin untuk membacanya), abaikan saja. Jika semua nama file yang ditentukan tidak valid, tidak menghasilkan apa-apa.

Jika tidak ada nama file yang diberikan, baca dari input standar. Hanya baca dari input standar jika tidak ada nama file yang diberikan atau jika -diberikan.

Keluaran

Program akan menampilkan, ke keluaran standar, input dengan garis-garis yang diberi nomor demikian (Anda dapat mengasumsikan bahwa input tersebut memiliki \n, \r\natau \rujung garis; pilih mana yang sesuai untuk Anda, tetapi tentukan yang mana):

<5 spaces>1<tab><content of line 1 of input>
<5 spaces>2<tab><content of line 2 of input>
...
<4 spaces>10<tab><content of line 10 of input>
...
<3 spaces>100<tab><content of line 100 of input>
...
...

6 karakter ruang dialokasikan untuk nomor baris, dan itu dimasukkan di akhir karakter ini; sisanya menjadi spasi (mis. 1akan memiliki 5 ruang utama, 22akan memiliki 4 ruang utama, ...). Jika input cukup panjang, Anda pada akhirnya akan kehabisan ruang untuk nomor baris, pada baris 999999. Anda tidak boleh mengeluarkan apa pun setelah baris 999999.

Jika input kosong, tidak menghasilkan apa-apa.

Status keluar

Angka yang lebih rendah diprioritaskan: jika kesalahan 1 dan 2 ditemukan, keluar dengan status 1.

Keluar dengan status 0 jika input berhasil diterima, dan garis-garis berhasil diberi nomor dan keluaran.

Keluar dengan status 1 jika satu atau lebih file yang ditentukan pada baris perintah tidak ditemukan atau tidak dapat dibaca.

Keluar dengan status 2 jika terlalu banyak file (lebih dari 64) diberikan.

Keluar dengan status 3 jika inputnya terlalu panjang (lebih dari 999999 baris). \

Mencetak gol

Ini adalah kode-golf - program menang tercepat!

Saya dapat menambahkan bonus nanti untuk menerapkan opsi tertentu yang nldimiliki. Tidak ada bonus saat ini.


sumber
Apakah penomoran baris terus-menerus atau pendek itu "reset" sendiri untuk setiap file individu?
britishtea
@britishtea Ini kontinu
1
Jadi perlukah menggunakan node jika kita ingin mengirimkan sesuatu di js? Atau bisakah kita menggunakan fungsi args atau prompt()untuk meniru program args dan stdin?
DankMemes
1
File biner? Pengkodean? Penanda unicode?
edc65

Jawaban:

6

Bash, 121

s=$[2*($#>64)]
for f in "$@";{ [ -f $f ]||s=1;}
((s))&&exit $s
awk '{if(NR>=10**6){exit 3}printf("%6d\t%s\n",NR,$0)}' $@
Sammitch
sumber
1
Anda dapat membuat ifekspresi Anda sedikit lebih pendek jika Anda menggunakan ekspresi aritmatika, misalnya(($#>64))&&s=2
Digital Trauma
2
@DigitalTrauma, saya belajar sesuatu!
Sammitch
1
Anda dapat mengganti s=0;(($#>64))&&s=2dengan s=$[2*($#>64)], (($s==0))||dengan ((s))&&dan ifpernyataan dengan [ -f "$f" ]||s=1.
Dennis
2
awkjuga akan digabungkan jika melewati beberapa file, jadi ini secara resmi dianggap sebagai penggunaan cat yang tidak berguna ;-). Sebaliknya saya pikir ini akan berhasil:awk '...' $@
Digital Trauma
2

Ruby, 195

o,l=$*[64]?[2]:[],999999
($*==[]?[?-]:$*).each{|n|f=n==?-?STDIN: open(n)rescue o<<1&&next
s=f.read.lines
s[l]?o<<3:1
puts s[0..l].map.with_index(1){|l,i|i.to_s.rjust(6)+?\t+l}}
exit !o[0]?0:o.min
britishtea
sumber
Saya pikir STDINalias $<.
Martin Ender
Ini adalah alias untuk ARGF, yang akan membaca dari sisa file yang diberikan sebagai argumen juga. Saya pikir ini bisa diturunkan lebih lanjut menggunakan ARGFentah bagaimana (bahkan tampaknya diakui "-"sebagai stdin).
britishtea
britishteanl: 4: di block in <main>': undefined method [] 'untuk # <Enumerator: 0x000006002980c8> (NoMethodError) dari britishteanl: 2: di each' from britishteanl:2:in <main>' - ada apa? Saya menjalankannya sebagairuby britishteanl folder/filename
Saya menduga itu perbedaan dalam versi Ruby. Saya telah menjalankan sampel di Ruby 2.0.0 dan Ruby 2.1.2 tanpa masalah. Versi apa yang Anda gunakan?
britishtea
2

Perl, 84 + 2 ( -pl) = 86 byte

perl -ple'BEGIN{map{-r||exit 1}@ARGV;@ARGV>63&&exit 2}$.>=1e6&&exit 3;$_=printf"%5d\t%s",$.,$_'

Dibatasi:

perl -MO=Deparse -ple'BEGIN{map{-r||exit 1}@ARGV;@ARGV>63&&exit 2}$.>=1e6&&exit 3;$_=printf"%5d\t%s",$.,$_' output.txt; echo $?

BEGIN { $/ = "\n"; $\ = "\n"; }
sub BEGIN {
    map {exit 1 unless -r $_;} @ARGV;
    exit 2 if @ARGV > 63;
}
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    exit 3 if $. >= 1000000;
    $_ = printf("%5d\t%s", $., $_);
}
continue {
    die "-p destination: $!\n" unless print $_;
}
-e syntax OK

Penting untuk diketahui:

  • -pmembungkus program yang diberikan dengan -edi while/ continueloop
  • BEGIN kode akan dieksekusi sebelum bagian utama (implisit)
  • pengujian file -rjuga gagal jika file tidak ada !-edan default untuk pengujian $_, secara implisit diberikan dalammap { ... } @ARGV
  • $. memegang nomor baris saat ini
  • sisanya harus jelas;)
dbr
sumber
Jawaban yang bagus, dan selamat datang di Programming Puzzles and Code Golf! Mungkin Anda bisa mengedit untuk menambahkan penjelasan tentang cara kerja kode Anda.
wizzwizz4
1

python 173

import os,sys
c=0
l=1
for f in sys.argv[1:]:
    if c>64:exit(2)
    if not os.path.isfile(f):exit(1)
    c+=1
    for x in open(f):
        if l>=10**6:exit(3)
        print '%6d\t%s'%(l,x),;l+=1
Sammitch
sumber
Saya pikir kode Anda saat ini hilang -untuk sys.stdin. Solusi yang mungkin adalah sesuatu seperti fh=sys.stdin if f=='-' else open(f)dan kemudian pergi x=fh.readline()?! Sayangnya itu tidak membuatnya lebih pendek. :)
Dave J
1

J (162)

exit(((2*64<#)[exit@3:`(stdout@(,&LF)@;@(,&TAB@(6&":)&.>@>:@i.@#,&.>]))@.(1e6>#)@(<;.2)@(1!:1)@(<`3:@.('-'-:]))&.>@;@{.@(_64&(<\))) ::1:)]`(]&<&'-')@.(0=#)2}.ARGV

Penjelasan:

  • ]`(]&<&'-')@.(0=#)2}.ARGV: Dapatkan argumen baris perintah, dan hapus dua yang pertama (karena itu adalah interpreter dan nama file skrip). Jika daftar yang dihasilkan kosong, kembalikan ['-'](yaitu, seolah-olah pengguna hanya lewat -), jika tidak kembalikan daftar tidak berubah.
  • (... ::1:): jika fungsi dalam gagal, kembali 1, jika tidak, kembalikan apa pun fungsi dalam kembali.
  • ((2*64<#)[... ): mengevaluasi fungsi dalam dan membuang hasilnya. Kemudian, jika panjang daftar yang dilewati tidak lebih tinggi dari 64, kembali 0, jika tidak kembali 2.
  • &.>@;@{.@(_64&(<\)): dapatkan paling banyak 64elemen dari daftar, dan untuk masing-masing menjalankan fungsi berikut:
    • (1!:1)@(<`3:@.('-'-:])): jika elemen itu -, baca isi deskriptor file 3(stdin), jika tidak baca isi file yang dinamai oleh elemen itu. Jika ini gagal (yaitu file tidak ada), kode di atas akan menangkapnya dan kembali 1.
    • exit@3:`(... )@.(1e6>#)@(<;.2): pisahkan string pada ujung garisnya. Jika ada 1.000.000 atau lebih baris, keluar dengan status 3. Jika tidak:
      • ,&TAB@(6&":)&.>@>:@i.@#: menghasilkan angka untuk setiap baris, memformatnya dalam kolom 6 digit, dan menambahkan a TABke akhir setiap string,
      • ,&.>]: tambahkan setiap nomor di bagian depan setiap baris.
      • stdout@(,&LF)@;: kemudian output semuanya, diikuti oleh tambahan LF.
  • exit: keluar dengan nilai pengembalian fungsi itu
marinus
sumber
1

Ruby, 76 byte

Satu byte untuk pbendera. Jalankan dengan ruby -p nl.rb.

BEGIN{x=$*.size-65}
exit 2if$*.size==x
exit 3if$.>999999
$_="%6d"%$.+?\t+$_

argumen stdin atau file ditangani secara otomatis oleh Ruby. Sudah keluar dengan kode 1 jika argumen file tidak ada. $.adalah jumlah baris yang telah dibaca. $*adalah argumen baris perintah, dan file muncul saat file dibaca. The pbendera mengeksekusi BEGINblok dan membungkus sisa program di dalam loop sementara-mendapat-cetak, menggunakan $_sebagai input / output.

daniero
sumber
Spesifikasi mengatakan Anda harus menangani 64 input pertama jika diberikan lebih dari 64, bukan hanya menyerah di awal.
Anders Kaseorg
@AndersKaseorg diperbaiki.
daniero
1

Perl, 125 122 byte

@a=@ARGV;for(@a){$i++>63&&exit 2;($_ eq '-'or-e$_)or next;@ARGV=$_;while(<>){$c>1E6-2&&exit 3;printf"%5d\t%s",++$c,$_}say}
Gowtham
sumber
Ini tidak memenuhi spesifikasi mengenai argumen 64 maksimum dan status keluar.
Anders Kaseorg
@AndersKaseorg Diperbaiki!
Gowtham
0

C, 362 359

Hanya untuk bersenang-senang. ;-) Bekerja dengan LF atau CR / LF linefeeds.

#include<stdio.h>
#define R return
#define P printf(
e,t,l;void*f;r(){P"% 6d\t",++l);for(;(t=fgetc(f))^-1&&l<1000000;){if(ferror(f))R 1;P"%c",t);if(t==10)P"% 6d\t",++l);}P"\n");R l<1000000?0:3;}main(int c,char**v){e=c>65?2:0;for(++v;*v||c<2;++v){t=c<2||!strcmp(*v,"-")?f=stdin,0:!(f=fopen(*v,"rb"));if(t||(t=r()))e=!e|(e>t)?t:e;if(f&&f!=stdin)fclose(f);}R e;}
owacoder
sumber