wc coreutilを再実装します


27

この課題はこの古い課題と似ていますが、仕様のいくつかの不明確な部分が打ち出され、I / O要件が厳しくなっています。


印刷可能なASCIIと改行のみで構成される文字列の入力を指定すると、そのさまざまなメトリック(バイト、ワード、行カウント)を出力します。

出力する必要があるメトリックは次のとおりです。

  • バイト数。入力文字列はASCII内にとどまるため、これは文字数でもあります。

  • 単語数。これはwc、「単語:」の非空白文字のシーケンスの定義です。たとえば、abc,def"ghi"1つの「単語」です。

  • 行数。これは一目瞭然です。入力には常に末尾の改行が含まれます。つまり、行カウントは「改行カウント」と同義です。末尾の改行は1つしかありません。

出力は、デフォルトのwc出力を正確に複製する必要があります(ファイル名を除く)。

llama@llama:~$ cat /dev/urandom | tr -cd 'A-Za-z \n' | head -90 > example.txt
llama@llama:~$ wc example.txt
  90  165 5501 example.txt

行カウントが最初に来て、次にワードカウント、最後にバイトカウントになることに注意してください。さらに、各カウントはすべて同じ幅になるようにスペースで左詰めする必要があります。上記の例で5501は、は4桁の「最長」番号であるため165、1つのスペースと902 つのスペースが埋め込まれます。最後に、数字はすべて、各数字の間にスペースを入れて単一の文字列に結合する必要があります。

これはであるため、バイト単位の最短コードが優先されます。

(ああ、ちなみに... wc答えにコマンドを使用することはできません。それが明らかでない場合は。)

テストケース(\n改行を表します。オプションで追加の末尾改行も必要になる場合があります):

"a b c d\n" -> "1 4 8"
"a b c d e f\n" -> " 1  6 12"
"  a b c d e f  \n" -> " 1  6 16"
"a\nb\nc\nd\n" -> "4 4 8"
"a\n\n\nb\nc\nd\n" -> " 6  4 10"
"abc123{}[]()...\n" -> " 1  1 16
"\n" -> "1 0 1"
"   \n" -> "1 0 4"
"\n\n\n\n\n" -> "5 0 5"
"\n\n\na\nb\n" -> "5 2 7"

2
この1つははるかに優れた課題であるため、私はこの1つをだまして古いものをVTCにするつもりです。
メゴ

空の入力をサポートする必要がありますか?
トンホスペル

私はそうは思わない、彼はすべての入力が\ nで終わると言った。
CalculatorFeline

回答:


8

Perl、49バイト

に+3を追加 -an0

STDINまたは1つ以上のファイル名を引数として入力します。として実行perl -an0 wc.pl

wc.pl

/\z/g;pos=~//;printf"%@+d %@+d $`
",y/
//,~~@F

説明:

-n0      slurps the whole input into $_ and says we will do our own printing
-a       tells perl to split the input on whitespace into array @F
/\z/g    Matches the absolute end of the input. g modifier so the position 
         is remembered in pos which will now contain the input length
pos=~//  An empy regex repeats the last succesful match, so /\z/ again.
         After that $` will contain the the number of input characters and
         the array @+ will contain the length of this number
printf   All preparation is complete, we can go print the result
"%@+d"   will become e.g. %6d if the number of characters is a number of
         length 6, so lines and words will get printed right aligned 
         in a field of length 6.
$`       $` we can directly interpolate since it won't contain a %
y/\n//   Count the number of newlines in $_
~~@F     The array of words @F in scalar context gives the number of words

7

Python 2、100 77バイト

このソリューションは、複数行の文字列を受け入れ、必要なカウントを標準出力に出力するPython関数です。書式文字列を使用して書式文字列を作成することに注意してください(%%最初の書式プレースホルダーをエスケープする必要があります)。

編集:デニスによる印刷の最適化により23バイトを保存しました。

def d(b):c=len(b);a='%%%us'%len(`c`);print a%b.count('\n'),a%len(b.split()),c

ミニファイヤの前は、次のようになっています。

def wc(text) :
    size = len(text);
    numfmt = '%%%us' % len(`size`);
    print numfmt % text.count('\n'), numfmt % len(text.split()), size

7

Pyth、21バイト

jdm.[;l`lQ`ld[@bQcQ)Q

テストスイート

Pythには、非常に便利なビルトインがあります。まず[、文字列の改行(@bQ)、文字列の単語(cQ))、文字列自体(Q)のリスト()を作成します。次に、.[各文字列の長さ(ld)にスペース(;このコンテキスト)を埋め込み、文字数()の長さにしますl`lQ。最後に、スペース(jd)で結合します。


6

POSIX awk、79 75 67 65バイト

{w+=NF;c+=length+1}END{d=length(c)"d %";printf"%"d d"d\n",NR,w,c}

編集:POSIXではlength呼び出し部分を割り引くことで7バイトを節約でき、Doorknobのに追加d %するためのヒントのおかげで2バイトを節約できるため、4バイトを節約しましたd

これはもともとGNU awk用でしたが、私が知る限り、POSIX awk機能のみを使用しています。

より良いフォーマット:

gawk '{
  w += NF
  c += length($0) + 1  # length($0) misses the newline
}
END {
  d = length(c) # GNU awk's length returns the length of string representation of number
  printf "%"d"d %"d"d %d\n", NR, w, c
}'

@Doorknob OK、ありがとう。チャットの会話を見たと思いますか?また、その質問は卒業すべきであるFAQ-提案よくある質問
ムル

1
ああ、私はチャットであ​​なたを見ませんでした。あなたの答えが私の受信トレイに表示されました:PIはその質問に[faq-proposed]を追加した人でした。
ドアノブ

1
に設定dするlength(c)"d %"と、toを変更できるようにprintfなり"%"d d"d\n"、2バイト節約されます。
ドアノブ

1
@Doorknob確かに、ありがとう!それはエキゾチックではなく、バイトを節約するありふれたものだと思います。
ムル

6

真剣に、39バイト

"
 "╩╜l;$l╝@╜sl'
╜ck`#╛#"{:>%d}"%f`M' j

オンラインでお試しください!

説明(改行はに置き換えられます\n):

"\n "╩╜l;$l╝@╜sl'\n╜ck`#╛#"{:>%d}"%f`M' j
"\n "                                      push a string containing a newline and a space
     ╩                                     push input to register 0 (we'll call it s)
      ╜l;                                  push two copies of len(s) (byte count)
         $l╝                               push len(str(len(s))) to register 1
                                            (this will serve as the field width in the output)
            @╜sl                           push word count by getting the length of the list formed by
                                            splitting s on spaces and newlines
                '\n╜c                      count newlines in input
                     k                     push stack to list
                      `#╛#"{:>%d}"%f`M     map:
                       #                     listify
                        ╛#                   push reg 1 (field width), listify
                          "{:>%d}"           push that string
                                  %          do old-style string formatting for field width
                                   f         do new-style string formatting to pad the field appropriately
                                      ' j  join on spaces

この言語のドキュメントを見つけることができません。リンクを提供できますか?
ジョンアイ

2
@ JohnEye、github.com
Mego

3

AppleScript、253バイト

これは、AppleScriptのテキスト項目区切り文字がスペースに設定されていることを前提としています(その前提を強制するためにものを数える必要がある場合は、追加します)。

set w to(display dialog""default answer"")'s text returned
set x to b(w)
set y to w's text item's number
set z to w's paragraph's number
a(x,z)&z&a(x,y)&y&" "&x
on a(x,n)
set o to" "
repeat b(x)-b(n)
set o to o&" "
end
o
end
on b(n)
count(n as text)
end

3

CJam、31 26バイト

q_)/_S*S%@_]:,:s),f{Se[}S*

オンラインでお試しください!

使い方

q_                         e# Read all input from STDIN and push two copies.
  )                        e# Pop the last character (linefeed) of the second copy.
   /                       e# Split the remaining string at linefeeds.
    _                      e# Push a copy.
     S*                    e# Join the copy, separating by spaces.
       S%                  e# Split at runs of spaces.
         @_                e# Rotate the original input on top and push a copy.
           ]               e# Wrap all four items in an array.
            :,             e# Get the length of each item.
              :s           e# Cast the lengths (integers) to strings.
                )          e# Pop the last length (byte count).
                 ,         e# Get the number of digits.
                  f{Se[}   e# Left-pad all three length with spaces to that length.
                        S* e# Join, separating by spaces.

3

ジュリア、112 81バイト

f(s,n=endof,l="$(n(s))",g=r->lpad(n(split(s,r))-1,n(l)))=g(r"\n")" "g(r"\S+")" "l

これは、文字列を受け入れて文字列を返す関数です。

以下を関数の引数として保存します。

  • n = endof インデックス可能なコレクションの最後のインデックスを取得する関数(この場合、文字列の長さ)
  • l = "$(n(s))、補間を使用して文字列に変換された入力の長さ
  • g正規表現を受け入れ、その正規表現の入力分割の長さ-1を返すラムダ関数l

を使用g(r"\n")して行数とを使用して単語数を取得し、g(r"\S+")それらをlスペースで区切って結合します。

デニスのおかげで31バイト節約されました!


2

MATL、38バイト

'\n'32cZtttnGnw-wPZvPYbnqbnvvV!3Z"vX:!

オンラインで試すことができます! これはそれほど長くないはずです...

説明、計算について、

'\n'32cZt  %// Takes implicit input and replaces any \n with a space
tt         %// Duplicate that string twice
nGnw-w     %// Length of the string with \n's minus length with spaces to give number of \n's
PZvPYbnq   %// Take string with spaces, flip it, remove leading spaces, flip it again,
           %// split on spaces, find length and decrement for number of words
bn         %// get length of string with spaces, the number of characters

最後の部分は出力フォーマットを行います

vvV!       %// concatenate the 3 numbers to a column vector, convert to string and transpose
3Z"v       %// make string '   ' and concatenate on the bottom of previous string
X:!        %// linearise and transpose to get correct output (impicitly printed)

よくできました!「オンラインで試す」リンクの「デバッグ」フラグを削除しますか?
ルイスメンドー

ああ!ヘッドアップをありがとう!
デビッド

私はあなたが交換することができると思い!3Z"vX:!によってZ{Zccellstr続くstrjoin
ルイス・Mendo

1

JavaScript(ES6)、115バイト

s=>[/\n\/g,/\S+/g,/[^]/g].map(r=>l=(s.match(r)||[]).length).map(n=>(' '.repeat(99)+n).slice(-`${l}`.length)).join` `

入力は不要です。フォーマットは苦痛でした。パディングの量に上限があった場合、(' '.repeat(99)+n)例えば、より短いものに減らすことができました` ${n}`


私はあなたが交換することができると思う/[^]/g/./g、2バイト節約するために
パトリック・ロバーツ

@PatrickRobertsいいえ、改行をスキップするため、カウントはオフになります。
ニール

ああ、以前は気づかなかった。
パトリックロバーツ

1

PowerShell、140バイト

param($a)$c="$((($l=($a-split"`n").Count-1),($w=($a-split"\S+").Count-1),($b=$a.length)|sort)[-1])".Length;
"{0,$c} {1,$c} {2,$c}"-f$l,$w,$b

(明確にするために改行を残しました:D)

最初の行はinputを取り$a、次の部分はすべて1つのステートメントです。some-string'sに$c等しく設定しています。これにより、必要なパディングが形成されます。文字列内には即時コードブロックがあり、文字列に評価される前にコードが実行されます。 .length$(...)

コードブロックでは、|sortコマンドを介して3つのアイテムを送信し、最大のアイテムを取得してい(...)[-1]ます。これは、列を正しい幅にすることを保証している場所です。3つの項目は$l、行数、-split改行、$w単語数、-split空白、および$b長さです。

2行目は、-f演算子を使用した出力です(これはの略記ですString.Format())。これは、展開された変数を文字列に挿入する別の方法です。ここでは、各列の$c幅が広くなるように、すべての出力を左にパディングする必要があると言っています。パディングはスペースを介して行われます。01および2対応する$l$wおよび$bその行数、ワード数、およびバイトカウントを適切パディングと出力されるように、フォーマットオペレータへの引数です。

これには、文字列に既に展開された改行が必要であることに注意してください(たとえば、Get-Contentテキストファイルまたは何かに対してaを実行し、それを変数にパイピングまたは保存し、その入力でこのコードを呼び出す)、またはPowerShell-バックティック付きのスタイル付きエスケープ文字(の`n代わりに\n)。

PS C:\Tools\Scripts\golfing> .\reimplement-wc.ps1 "This line`nis broken`ninto three lines.`n"
 3  7 38


0

ルビー、108バイト

f=->s{a=[s.count($/),s.split(/\S+/).size-1,s.size].map(&:to_s)
a.map{|b|" "*(a.map(&:size).max-b.size)+b}*" "}

0

Perl、71 62 61バイト

+1を含む -n

$;=length($b+=y///c);$w+=split$"}{printf"%$;d %$;d $b",$.,$w

コメント:

while (<>) {                         # implicit because of -n
    $; = length(                     # printf formatting: width
       $b += y///c                   # count characters
    );
    $w += split $"                   # count words
}{                                   # explicit: end while, begin END block
    printf "%$;d %$;d $b", $., $w    #  $. = $INPUT_LINE_NUMBER
}                                    # implicit because of -n
  • もう一度@TonHospelに感謝します。
  • @TonHospelが取引のいくつかのトリックを見せてくれたおかげで9バイト節約できました!

取引のコツ:のy///c長さを短くして使用し$_ます。split$"スカラーコンテキストでは、の単語数を示します$_。以下のような句読点変数を使用することで$;はなく、$Wあなた置くことができるdだけのフォーマット文字列の補間後。次に、ドロップdイン$Wして括弧をドロップします。そして-p何も得られない-n、ただprintf印刷をさせてください(味に改行を追加してください)
トンホスペル

素晴らしい、私はそれを感謝します!
ケニー

のような計算チェーン$a=foo;$b=bar$aは通常、と書くことができ、$b=bar($a=foo)1バイトを節約します。ここで$;とに適用できます$b$;毎回再計算されるかどうかは気にしません
トンホスペル

ありがとう!2つのブロックがあるので見落としていました
...-ケニー

0

Lua、74 66バイト

ゴルフ:

t=arg[1]_,l=t:gsub('\n','')_,w=t:gsub('%S+','')print(l,w,t:len())

ゴルフをしていない:

text = arg[1]
_,lines = text:gsub('\n','')
_,words = text:gsub('%S+','')
print(lines, words, text:len())

コマンドライン引数を介して入力を受け取ります。

arg[1]バイトを節約するために、最初の引数()の名前を変更します。string.gsub置換の数と変更された文字列を返すので、それを使用して最初に'\n'(改行)、次に'%S+'(1つ以上の空白以外の文字のインスタンス、つまり単語)をカウントします。置換文字列には任意のものを使用できるため、空の文字列('')を使用してバイトを保存します。次にstring.len、文字列の長さ、つまりバイト数を見つけるために使用します。そして最後に、すべてを印刷します。


しかし、行と単語の値の左のパディングは表示されません
トンホスペル

0

網膜、65

^((\S+)|(¶)|.)*
$#3 $#2 $.0
+`(\b(.)+ )(?!.*\b(?<-2>.)+$)
a$1
a
<space>

オンラインでお試しください!

最初の段階は実際のwcプログラムで、残りはパディング用です。aプレースホルダの事はおそらく不要であり、グループのいくつかは、おそらくビットを簡略化することができます。


0

Haskell、140バイト

import Text.Printf
w h=let{l=length;s=show.l;c=s h;m=s.words$h;n=s.lines$h;f=maximum$map l[c, m, n];p=printf"%*s"f}in p n++' ':p m++' ':p c

以下に、拡張されていない変数名と関数名を使用したバージョンを示します。

import Text.Printf

wc str =
  let charcount = show.length $ str
      wordcount = show.length.words $ str
      linecount = show.length.lines $ str
      fieldwidth = maximum $ map length [charcount, wordcount, linecount]
      printer = printf "%*s" fieldwidth
  in printer linecount ++ (' ' : printer wordcount ++ (' ' : printer charcount))

これは、文字列を受け入れて文字列を返す関数です。それだけで使用するPrelude関数をwords(。RESP lines彼らは同じ定義を使用するように見えることを考えると言葉(それぞれのライン)の数を取得するために)wcカウントの間で、その後(文字列として)最長の値を取得し、printfのフォーマットの撮影を使用します書式設定のための引数の幅。


0

C、180 178バイト

#include <stdio.h>
#include <ctype.h>
main(b,w,l,c,d){d=' ';b=w=l=0;while((c=fgetc(stdin))!=EOF){if(!isspace(c)&&isspace(d))w++;b++;d=c;if(c==10)l++;}printf("%d %d %d\n",l,w,b);}


0

05AB1E24 23 バイト

¨¶¡¹… 
    S¡õK¹)€g§Zg>jJ¦

j現在はバグがあるため、§and なしで21バイトになる可能性がありJます。

オンラインそれを試してみたり、すべてのテストケースを確認してください

説明:

¨          # Remove the trailing newline of the (implicit) input
 ¶¡        # And split it on newlines
¹… 
    S¡     # Take the first input again, and split it on [" \n\t"]
      õK   # Then remove all empty string items
¹          # And take the first input again as is
)          # Wrap all three value of the stack to a single list
 g        # Take the length of each of the items
   §       # Cast the integers to strings (should have been implicit, but `j` is bugged)
    Z      # Take the max (always the last / amount of bytes) (without popping the list)
     g>    # Take the length + 1 of this max
       j   # Append leading spaces so all items or of this length
        J  # Join them together (should have been done by the `j` already, but it's bugged)
         ¦ # Remove the leading space (and output implicitly to STDOUT)

0

ピップ -s、25バイト

sX##a-#_._M[nNa`\S+`Na#a]

複数行の文字列をコマンドライン引数として受け取ります。オンラインでお試しください!

一番長い数字は常に文字数であると気づかせてくれたデニスのCJamの回答に感謝します。

説明

                           s is space; n is newline; a is 1st cmdline arg (implicit)
           [            ]  Construct a list of three elements:
            nNa             Number of newlines in a
               `\S+`Na      Regex search: number of runs of non-whitespace characters in a
                      #a    Length of a (i.e. number of characters in a)
          M                To each element of that list, map this function:
   #a                       Number of characters in a
  #                         Length of that number
     -#_                    Subtract length of each element
sX                          Construct a string of that many spaces
        ._                  Prepend it to the element
                           The resulting list is autoprinted, space-separated (-s flag)

-rsstdinから入力を受け取るフラグを使用した29バイトのソリューションを次に示します。

[#g`\S+`NST:gY#g+1]MsX#y-#_._

オンラインでお試しください!


0

Powershell、123 115バイト

switch -r($args|% t*y){'\s'{$a=0}'\S'{$w+=!$a;$a=1}'(?s).'{$b++}'
'{$l++}}$c="$b".Length
"{0,$c} {1,$c} $b"-f$l,+$w

テストスクリプト:

$f = {

switch -r($args|% t*y){    # evaluate all matched cases
    '\s'   {$a=0}          # any whitespace (newline not included)
    '\S'   {$w+=!$a;$a=1}  # any not-whitespace (newline not included)
    '(?s).'{$b++}          # any char (newline included!)
    '`n'   {$l++}          # new line char
}
$c="$b".Length
"{0,$c} {1,$c} $b"-f$l,+$w


}

@(
    , ("a b c d`n", "1 4 8")
    , ("a b c d e f`n", " 1  6 12")
    , ("  a b c d e f  `n", " 1  6 16")
    , ("a`nb`nc`nd`n", "4 4 8")
    , ("a`n`n`nb`nc`nd`n", " 6  4 10")
    , ("abc123{}[]()...`n", " 1  1 16")
    , ("`n", "1 0 1")
    , ("   `n", "1 0 4")
    , ("`n`n`n`n`n", "5 0 5")
    , ("`n`n`na`nb`n", "5 2 7")
) | % {
    $s,$e = $_
    $r = &$f $s
    "$($e-eq$r): $r"
}

出力:

True: 1 4 8
True:  1  6 12
True:  1  6 16
True: 4 4 8
True:  6  4 10
True:  1  1 16
True: 1 0 1
True: 1 0 4
True: 5 0 5
True: 5 2 7

説明:

  • $args|% t*y arument文字列をcharsに分割します
  • switch -r($args|% t*y)一致したすべてのケースを評価する
    • '\s' 空白の場合
    • '\S' 空白以外の場合
    • '(?s).' 文字のケース(改行を含む)
    • '\n' 改行文字のケース(改行はそれ自体を表します)
  • $c="$b".Lengthバイト数の長さを計算します。$ bは常に設計上max($ l、$ w、$ b)です
  • "{0,$c} {1,$c} $b"-f$l,+$w同じ長さの数値をフォーマットします。変数$ wはint​​に変換されます。言葉のない文字列が必要です。「入力には常に末尾の改行が含まれる」ため、他の変数の形式は「現状のまま」であり、$ lと$ bを0にすることはできません。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.