Đánh số dòng - thực hiện nl


13

Nhiệm vụ của bạn là triển khai một chương trình tương tự như nlcông cụ dòng lệnh từ các tiện ích lõi GNU.

Sơ hở tiêu chuẩn bị cấm.

Bạn không được sử dụng bất kỳ chức năng, chương trình hoặc tiện ích tích hợp hoặc bên ngoài nào để đánh số các dòng của tệp hoặc chuỗi, chẳng hạn như nlchính nó hoặc =lệnh trong GNU sed.

Sự chỉ rõ

Đầu vào

Chương trình chấp nhận tên tệp làm đối số. Mã của bạn không phải là đa nền tảng; định dạng tên tệp của HĐH chạy mã nên được sử dụng, tức là nếu bạn tình cờ ở trên Windows, dấu phân cách thư mục có thể \hoặc /.

Bạn phải có thể lấy 64 tệp đầu vào, bao gồm -nếu nó được chỉ định. Nếu trên 64 được đưa ra, chỉ xử lý 64 đầu tiên.

Trong danh sách tên tệp, -thể hiện đầu vào tiêu chuẩn.

Nếu tên tệp được đưa ra, hãy đọc từ các tệp theo thứ tự chúng được cung cấp và nối các nội dung của chúng, chèn một dòng mới giữa mỗi tệp và ở cuối. Nếu bạn không thể đọc từ một hoặc nhiều tên tệp (vì tệp không tồn tại hoặc bạn không có quyền đọc cho nó), hãy bỏ qua chúng. Nếu tất cả tên tệp được chỉ định là không hợp lệ, đầu ra không có gì.

Nếu không có tên tệp nào được đưa ra, hãy đọc từ đầu vào tiêu chuẩn. Chỉ đọc từ đầu vào tiêu chuẩn nếu không có tên tệp nào được đưa ra hoặc nếu -được cung cấp.

Đầu ra

Chương trình sẽ đầu ra, để đầu ra tiêu chuẩn, đầu vào với dòng đánh số như vậy (Bạn có thể giả định rằng các đầu vào có \n, \r\nhoặc \rkết thúc dòng; chọn nào thuận tiện cho bạn, nhưng xác định cái nào):

<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 ký tự của không gian được phân bổ cho số dòng và nó được chèn vào cuối các ký tự này; phần còn lại trở thành không gian (ví dụ: 1sẽ có 5 không gian hàng đầu, 22sẽ có 4 không gian hàng đầu, ...). Nếu đầu vào đủ dài, cuối cùng bạn sẽ hết dung lượng cho số dòng, tại dòng 999999. Bạn không được xuất bất cứ thứ gì sau dòng 999999.

Nếu đầu vào trống, đầu ra không có gì.

Trạng thái thoát

Các số thấp hơn được ưu tiên: nếu gặp lỗi 1 và 2, thoát với trạng thái 1.

Thoát với trạng thái 0 nếu đầu vào được nhận thành công và các dòng được đánh số và đầu ra thành công.

Thoát với trạng thái 1 nếu không tìm thấy một hoặc nhiều tệp được chỉ định trên dòng lệnh hoặc không thể đọc được.

Thoát với trạng thái 2 nếu có quá nhiều tệp (hơn 64) được đưa ra.

Thoát với trạng thái 3 nếu đầu vào quá dài (hơn 999999 dòng). \

Chấm điểm

Đây là mã golf - chương trình chiến thắng ngắn nhất!

Tôi có thể thêm tiền thưởng sau này để thực hiện các tùy chọn nhất định nlcó. Không có tiền thưởng tại thời điểm này.


Việc đánh số dòng liên tục hay ngắn nó tự "thiết lập lại" cho từng tệp riêng lẻ?
Anh

@britishtea Nó liên tục

1
Vì vậy, có cần thiết phải sử dụng nút nếu chúng tôi muốn gửi một cái gì đó trong js? Hoặc chúng ta có thể sử dụng hàm args hoặc prompt()để mô phỏng chương trình args và stdin?
DankMeme

1
Tệp nhị phân? Mã hóa? Đánh dấu Unicode?
edc65

Câu trả lời:


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)}' $@

1
Bạn có thể làm cho bạn ifbiểu khá ngắn hơn một chút nếu bạn sử dụng biểu thức số học, ví dụ:(($#>64))&&s=2
Digital Chấn thương

2
@DigitalTrauma Tôi học được một điều!
Sammitch

1
Bạn có thể thay thế s=0;(($#>64))&&s=2bằng s=$[2*($#>64)], (($s==0))||với ((s))&&iftuyên bố với [ -f "$f" ]||s=1.
Dennis


2
awkcũng sẽ ghép nối nếu thông qua nhiều tệp, vì vậy điều này chính thức được tính là việc sử dụng mèo vô dụng ;-). Thay vào đó tôi nghĩ rằng điều này sẽ hoạt động:awk '...' $@
Chấn thương kỹ thuật số

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

Tôi nghĩ STDINlà bí danh $<.
Martin Ender

Đây là một bí danh ARGF, sẽ đọc từ phần còn lại của các tệp được cung cấp dưới dạng đối số. Tôi nghĩ rằng điều này có thể được đánh xuống bằng cách sử dụng ARGFbằng cách nào đó (nó thậm chí dường như nhận ra "-"là stdin).
Anh

britishteanl: 4: in block in <main>': undefined method [] 'cho # <Enumerator: 0x000006002980c8> (NoMethodError) từ britishteanl: 2: in each' from britishteanl:2:in <main>' - có chuyện gì vậy? Tôi đã chạy nó với tư cáchruby britishteanl folder/filename

Tôi nghi ngờ đó là một sự khác biệt trong phiên bản Ruby. Tôi đã chạy mẫu trên cả Ruby 2.0.0 và Ruby 2.1.2 mà không gặp vấn đề gì. Phiên bản nào bạn đang sử dụng?
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",$.,$_'

Đã ký

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

Quan trọng phải biết:

  • -pkết thúc chương trình được cung cấp -etrong vòng lặp while/continue
  • BEGIN mã sẽ được thực thi trước phần chính (ẩn)
  • kiểm tra tệp -rcũng thất bại nếu tệp không tồn tại !-evà mặc định để kiểm tra $_, hoàn toàn được cung cấp trongmap { ... } @ARGV
  • $. giữ số dòng hiện tại
  • phần còn lại nên tự giải thích;)

Câu trả lời tuyệt vời, và chào mừng bạn đến với Câu đố lập trình và Code Golf! Có lẽ bạn có thể chỉnh sửa để thêm một lời giải thích về cách mã của bạn hoạt động.
wizzwizz4

1

trăn 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

Tôi nghĩ rằng mã của bạn hiện đang thiếu -cho sys.stdin. Một giải pháp khả thi có thể là một cái gì đó giống như fh=sys.stdin if f=='-' else open(f)và sau đó đi với x=fh.readline()?! Thật không may, nó không làm cho nó ngắn hơn mặc dù. :)
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

Giải trình:

  • ]`(]&<&'-')@.(0=#)2}.ARGV: Nhận các đối số dòng lệnh và xóa hai đối số đầu tiên (vì đó là các trình thông dịch và tên tệp tập lệnh). Nếu danh sách kết quả trống, hãy trả về ['-'](nghĩa là như người dùng đã vượt qua -), nếu không thì trả lại danh sách không thay đổi.
  • (... ::1:): nếu chức năng bên trong thất bại, hãy trả về 1, nếu không thì trả về bất cứ chức năng bên trong nào được trả về.
  • ((2*64<#)[... ): đánh giá chức năng bên trong và ném kết quả đi. Sau đó, nếu độ dài của danh sách được thông qua không cao hơn 64, hãy trả lại 0, nếu không thì trả lại 2.
  • &.>@;@{.@(_64&(<\)): lấy tối đa các 64phần tử từ danh sách và cho mỗi phần tử chạy hàm sau:
    • (1!:1)@(<`3:@.('-'-:])): nếu phần tử là -, đọc nội dung của bộ mô tả tệp 3(stdin), nếu không thì đọc nội dung của tệp được đặt tên bởi phần tử đó. Nếu điều này không thành công (tức là tệp không tồn tại), đoạn mã trên sẽ bắt nó và trả về 1.
    • exit@3:`(... )@.(1e6>#)@(<;.2): chia chuỗi trên đầu cuối của nó. Nếu có 1.000.000 dòng trở lên, thoát với trạng thái 3. Nếu không thì:
      • ,&TAB@(6&":)&.>@>:@i.@#: tạo số cho mỗi dòng, định dạng chúng trong cột 6 chữ số và thêm a TABvào cuối mỗi chuỗi,
      • ,&.>]: thêm từng số vào phía trước của mỗi dòng.
      • stdout@(,&LF)@;: sau đó xuất toàn bộ, theo sau là thêm LF.
  • exit: thoát với giá trị trả về của hàm đó

1

Ruby, 76 byte

Một byte cho pcờ. Chạy với ruby -p nl.rb.

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

đối số stdin hoặc tệp được xử lý tự động bởi Ruby. Nó đã thoát với mã 1 nếu đối số tệp không tồn tại. $.là số dòng đã được đọc. $*là các đối số dòng lệnh và các tệp được bật ra khi các tệp được đọc. Các pcờ thực thi BEGINkhối và kết thúc tốt đẹp với phần còn lại của chương trình bên trong một vòng lặp while-được-in, sử dụng $_như đầu vào / đầu ra.


Thông số kỹ thuật nói rằng bạn nên xử lý 64 đầu vào đầu tiên nếu được cung cấp nhiều hơn 64, thay vì chỉ bỏ cuộc ngay từ đầu.
Anders Kaseorg

@AndersKaseorg đã sửa.
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}

Điều này không thỏa mãn đặc tả về tối đa 64 đối số và trạng thái thoát.
Anders Kaseorg

@AndersKaseorg Đã sửa!
Gowtham

0

C, 362 359

Chỉ vì niềm vui của nó. ;-) Hoạt động với các nguồn cấp dữ liệu LF hoặc CR / LF.

#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;}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.