行番号-nlを実装する


13

あなたの仕事はnl、GNUコアユーティリティのコマンドラインツールに似たプログラムを実装することです。

標準的な抜け穴は禁止されています。

GNU sedのコマンドnl=コマンドなど、ファイルまたは文字列の行に番号を付けるために、組み込みまたは外部の関数、プログラム、またはユーティリティを使用することはできません。

仕様

入力

プログラムは引数としてファイル名を受け入れます。コードはクロスプラットフォームである必要はありません。コードを実行しているOSのファイル名形式を使用する必要があります。つまり、Windowsを使用している場合、ディレクトリ区切り文字は\または/です。

-指定されている場合を含め、64個の入力ファイルを取得できる必要があります。64を超える場合は、最初の64のみを処理します。

ファイル名のリストで、-標準入力を表します。

ファイル名が指定されている場合は、指定された順序でファイルから読み取り、内容を連結し、各ファイルの間に新しい行を挿入します。1つまたは複数のファイル名から読み取ることができない場合(ファイルが存在しないか、読み取り権限がないため)、無視します。指定されたすべてのファイル名が無効な場合、何も出力しません。

ファイル名が指定されていない場合は、標準入力から読み取ります。ファイル名が指定されていない場合、または指定されている場合にのみ、標準入力から読み取ります-

出力

プログラムは、このように番号が付けられた行で入力を標準出力に出力します(入力に\n\r\nまたは\r行末があると仮定することができます;都合の良い方を選択しますが、どちらかを指定します)。

<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文字のスペースが割り当てられ、これらの文字の最後に挿入されます。残りはスペースになります(たとえば1、先頭に5つのスペースがあり、22先頭に4つのスペースがあります...)。入力が十分に長い場合、最終的にlineの行番号のスペースが不足します999999。999999行目以降は何も出力しないでください。

入力が空の場合、何も出力しません。

終了ステータス

低い番号が優先されます。エラー1および2が発生した場合、ステータス1で終了します。

入力が正常に受信され、行が正常に番号付けされて出力された場合、ステータス0で終了します。

コマンドラインで指定された1つ以上のファイルが見つからないか、読み取ることができなかった場合、ステータス1で終了します。

指定されたファイルが多すぎる(64を超える)場合は、ステータス2で終了します。

入力が長すぎる(999999行を超える)場合は、ステータス3で終了します。\

得点

これはコードゴルフです-最短のプログラムが勝ちます!

ある特定のオプションを実装するために、後でボーナスを追加する場合がnlあります。現時点ではボーナスはありません。


行番号は連続的ですか、それとも個々のファイルごとにそれ自体が「リセット」されますか?
イギリス茶14

@britishtea継続的です

1
jsで何かを送信する場合、nodeを使用する必要がありますか?または、関数の引数を使用したりprompt()、プログラムの引数と標準入力をエミュレートしたりできますか?
DankMemes

1
バイナリファイル?エンコーディング?Unicodeマーカー?
edc65

回答:


6

バッシュ、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
if算術式を使用すると、式をかなり短くすることができます。たとえば、(($#>64))&&s=2
Digital Trauma

2
@DigitalTrauma事を学んだ!
Sammitch 14

1
あなたは置き換えることができs=0;(($#>64))&&s=2s=$[2*($#>64)](($s==0))||((s))&&してifとの声明[ -f "$f" ]||s=1
デニス14


2
awk複数のファイルが渡された場合も連結されるため、これは公式にはcatの無駄な使用としてカウントされます ;-)。代わりに、私はこれがうまくいくと思う:awk '...' $@
デジタル外傷14

2

ルビー、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

STDINエイリアスされて$<いると思います。
マーティンエンダー14

これはのエイリアスでARGF、引数として指定された残りのファイルからも読み取ります。私はこれをARGFなんとかしてさらにゴルフダウンできると思います("-"標準入力であると認識しているようです)。
イギリス茶14

britishteanl:4:in block in <main>': undefined method [] 'の#<Enumerator:0x000006002980c8>(NoMethodError)from britishteanl:2:in each' from britishteanl:2:in <main>'-何が問題なのですか?私はそれを実行しましたruby britishteanl folder/filename

Rubyバージョンの違いだと思います。サンプルをRuby 2.0.0とRuby 2.1.2の両方で問題なく実行しました。どのバージョンを使用していますか?
英国茶14年

2

Perl、84 + 2(-pl)= 86バイト

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

分解済み:

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

知っておくべき重要事項:

  • -p/ ループ-eで指定されたプログラムをラップしますwhilecontinue
  • BEGIN コードは(暗黙の)メイン部分の前に実行されます
  • ファイル-rが存在せず!-e、デフォルトでtesting $_に設定されている場合、ファイルテストも失敗しますmap { ... } @ARGV
  • $. 現在の行番号を保持します
  • 残りは自明であるべきです;)

素晴らしい答えです。プログラミングパズルとコードゴルフへようこそ!おそらく編集して、コードの動作の説明を追加できます。
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

現在、あなたのコードには-forがありませんsys.stdin。可能性のある解決策は、次のようなものである可能性がfh=sys.stdin if f=='-' else open(f)ありx=fh.readline()ます。残念ながら、短くなることはありません。:)
デイブJ 14

1

J(162)

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

説明:

  • ]`(]&<&'-')@.(0=#)2}.ARGV:コマンドライン引数を取得し、最初の2つを削除します(これらはインタープリターとスクリプトファイル名であるため)。結果のリストが空の場合は戻ります['-'](つまり、ユーザーがのみを通過したかのように-)。それ以外の場合はリストを変更せずに返します。
  • (... ::1:):内部関数が失敗した場合はreturn 1、そうでない場合は内部関数が返したものをすべて返します。
  • ((2*64<#)[... ):内部関数を評価し、結果を破棄します。次に、渡されたリストの長さがを超えない場合64、return 0、そうでない場合はreturn 2
  • &.>@;@{.@(_64&(<\))64リストから多くても要素を取得し、それぞれに対して次の関数を実行します。
    • (1!:1)@(<`3:@.('-'-:])):要素がの場合、-ファイル記述子3(stdin)の内容を読み取ります。そうでない場合は、その要素で指定されたファイルの内容を読み取ります。これが失敗する(つまり、ファイルが存在しない)場合、上記のコードはそれをキャッチしてを返し1ます。
    • exit@3:`(... )@.(1e6>#)@(<;.2):文字列を行末で分割します。1.000.000行以上ある場合、statusで終了します3。さもないと:
      • ,&TAB@(6&":)&.>@>:@i.@#:各行の数値を生成し、6桁の列にフォーマットし、TAB各文字列の末尾にa を追加します。
      • ,&.>]:各行の先頭に各番号を追加します。
      • stdout@(,&LF)@;:次に、すべてを出力し、その後に余分なLF
  • exit:その関数の戻り値で終了します

1

ルビー、76バイト

pフラグ用の1バイト。で実行しruby -p nl.rbます。

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

標準入力またはファイル引数は、Rubyによって自動的に処理されます。ファイル引数が存在しない場合、コード1で既に終了します。$.読み取られた行の数です。$*はコマンドライン引数であり、ファイルが読み取られるとファイルがポップオフされます。pフラグは、実行BEGINブロックと使用中-取得-printループ、内部プログラムの残りの部分をラップする$_入力/出力として。


仕様では、最初からあきらめるのではなく、64を超える値が与えられた場合、最初の64の入力を処理する必要があるとされています。
アンデルスカセオルグ

@AndersKaseorgが修正されました。
daniero

1

Perl、125 122バイト

@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}

これは、64引数の最大値と終了ステータスに関する仕様を満たしていません。
アンデルスカセオルグ

@AndersKaseorg修正済み!
ゴーサム

0

C、362 359

それの楽しみのためだけに。;-) LFまたは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;}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.