Thực hiện lại coreutil wc


27

Thử thách này tương tự như thử thách cũ này , nhưng với một số phần không rõ ràng của thông số kỹ thuật được đưa ra và các yêu cầu I / O ít nghiêm ngặt hơn.


Đưa ra một đầu vào của một chuỗi chỉ bao gồm ASCII có thể in và các dòng mới, xuất ra các số liệu khác nhau của nó (byte, từ, số dòng).

Các số liệu mà bạn phải xuất ra như sau:

  • Số byte. Vì chuỗi đầu vào nằm trong ASCII, đây cũng là số ký tự.

  • Số từ. Đây là wcđịnh nghĩa của một "từ:" bất kỳ chuỗi không khoảng trắng nào. Ví dụ: abc,def"ghi"là một "từ".

  • Số dòng. Điều này là tự giải thích. Đầu vào sẽ luôn chứa một dòng mới, có nghĩa là số dòng đồng nghĩa với "số dòng mới". Sẽ không bao giờ có nhiều hơn một dòng mới.

Đầu ra phải sao chép chính xác wcđầu ra mặc định (ngoại trừ tên tệp):

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

Lưu ý rằng số dòng xuất hiện trước, sau đó đếm từ và cuối cùng là đếm byte. Hơn nữa, mỗi số phải được đệm trái với các khoảng trống sao cho chúng có cùng chiều rộng. Trong ví dụ trên, 5501là số "dài nhất" có 4 chữ số, do đó, 165được đệm bằng một khoảng trắng và 90có hai. Cuối cùng, tất cả các số phải được nối thành một chuỗi có khoảng cách giữa mỗi số.

Vì đây là , mã ngắn nhất tính bằng byte sẽ thắng.

(Ồ, và nhân tiện ... bạn không thể sử dụng wclệnh trong câu trả lời của mình. Trong trường hợp điều đó chưa rõ ràng.)

Các trường hợp thử nghiệm ( \nđại diện cho một dòng mới; bạn cũng có thể yêu cầu thêm một dòng mới theo dõi):

"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
Tôi sẽ VTC cái cũ là bản sao của cái này vì cái này là một thử thách tốt hơn nhiều.
Mego

Có nên hỗ trợ đầu vào trống?
TonMedel

Tôi không nghĩ vậy, anh ấy nói tất cả các đầu vào kết thúc bằng \ n.
Máy

Câu trả lời:


8

Perl, 49 byte

Đã thêm +3 cho -an0

Nhập vào STDIN hoặc 1 hoặc nhiều tên tệp làm đối số. Chạy nhưperl -an0 wc.pl

wc.pl:

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

Giải trình:

-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 byte

Giải pháp này là một hàm Python chấp nhận một chuỗi nhiều dòng và in số đếm cần thiết cho thiết bị xuất chuẩn. Lưu ý rằng tôi sử dụng chuỗi định dạng để xây dựng chuỗi định dạng (yêu cầu %%thoát khỏi trình giữ chỗ định dạng đầu tiên).

Chỉnh sửa: Đã lưu 23 byte do tối ưu hóa in bởi Dennis.

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

Trước khi khai thác, nó trông như thế này:

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

7

Bình thường, 21 byte

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

Bộ kiểm tra

Pyth có một số tích hợp rất đẹp ở đây. Chúng tôi bắt đầu bằng cách tạo một danh sách ( [) các dòng mới trong chuỗi ( @bQ), các từ trong chuỗi ( cQ)) và chính chuỗi ( Q). Sau đó, chúng tôi đệm ( .[) độ dài của mỗi chuỗi ( ld) với khoảng trắng ( ;trong ngữ cảnh này) cho đến độ dài của số lượng ký tự ( l`lQ). Cuối cùng, tham gia vào khoảng trắng ( jd).


6

POSIX awk, 79 75 67 65 byte

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

Chỉnh sửa: đã lưu 4 byte vì POSIX cho phép trần length, lưu 7 byte bằng cách giảm giá phần gọi và lưu hai byte nhờ mẹo của Doorknob để thêm d %vào d.

Điều này ban đầu dành cho GNU awk, nhưng tốt nhất tôi có thể nói, nó chỉ sử dụng chức năng awk POSIX.

Định dạng tốt hơn:

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, cảm ơn vì điều đó. Đoán bạn đã thấy cuộc trò chuyện? Ngoài ra, câu hỏi đó nên tốt nghiệp từ faq-đề xuất đến faq .
muru

1
Ồ, tôi đã không nhìn thấy bạn trong trò chuyện; câu trả lời của bạn vừa xuất hiện trong hộp thư đến của tôi: PI là người đã thêm [faq-đề xuất] vào câu hỏi đó, vì vậy có lẽ tôi sẽ kiểm tra trong phòng mod trước khi nâng cấp nó lên [faq].
Doorknob

1
Cài đặt dthành length(c)"d %"sẽ cho phép bạn thay đổi printfthành "%"d d"d\n", giúp tiết kiệm hai byte.
Doorknob

1
@Doorknob thực sự, cảm ơn! Đoán nó không phải là kỳ lạ , mà là trần tục tiết kiệm byte.
muru

6

Nghiêm túc , 39 byte

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

Hãy thử trực tuyến!

Giải thích (dòng mới được thay thế bằng \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

Tôi không thể gửi bất kỳ tài liệu nào cho ngôn ngữ này, bạn có thể cung cấp một liên kết không?
JohnEye


3

AppleScript, 253 byte

Điều này giả định rằng các dấu phân cách mục văn bản của AppleScript được đặt thành khoảng trắng (nếu tôi cần đếm nội dung để buộc giả định đó, tôi sẽ thêm nó).

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 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Julia, 112 81 byte

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

Đây là một hàm chấp nhận một chuỗi và trả về một chuỗi.

Chúng tôi lưu các mục sau đây dưới dạng đối số hàm:

  • n = endof Hàm lấy chỉ mục cuối cùng của bộ sưu tập có thể lập chỉ mục (trong trường hợp này là độ dài của chuỗi)
  • l = "$(n(s)), độ dài của đầu vào được chuyển đổi thành một chuỗi bằng phép nội suy
  • Hàm lambda gchấp nhận biểu thức chính quy và trả về độ dài - 1 của phần tách đầu vào trên biểu thức chính đó, phần đệm bên trái có khoảng trắng để khớp với độ dài l.

Chúng tôi nhận được số lượng dòng sử dụng g(r"\n")và số lượng từ sử dụng g(r"\S+"), sau đó chúng tôi kết hợp những dòng đó với nhau bằng ldấu cách.

Đã lưu 31 byte nhờ Dennis!


2

MATL, 38 byte

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

Bạn có thể thử trực tuyến! Điều này không nên quá lâu mặc dù ...

Giải thích, để tính toán,

'\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

Phần cuối cùng định dạng đầu ra

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)

Làm tốt lắm! Có thể xóa cờ "gỡ lỗi" trong liên kết Dùng thử trực tuyến ?
Luis Mendo

Ôi trời ơi! Cảm ơn cho những người đứng đầu lên!
David

Tôi nghĩ bạn có thể thay thế !3Z"vX:!bằng Z{Zc( cellstrtheo sau strjoin)
Luis Mendo

1

JavaScript (ES6), 115 byte

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

Không yêu cầu bất kỳ đầu vào. Định dạng là đau đớn. Nếu có giới hạn trên về số lượng đệm, tôi có thể giảm (' '.repeat(99)+n)xuống một cái gì đó ngắn hơn, vd ` ${n}`.


Tôi nghĩ bạn có thể thay thế /[^]/gbằng /./gđể lưu hai byte
Patrick Roberts

@PatrickRoberts Không, bỏ qua các dòng mới, vì vậy số lượng của tôi sẽ bị tắt.
Neil

Ah, không bao giờ nhận thấy điều đó trước đây.
Patrick Roberts

1

PowerShell, 140 byte

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òng mới để lại cho rõ ràng: D)

Dòng đầu tiên nhận đầu vào $a, và sau đó phần tiếp theo là tất cả một câu lệnh. Chúng tôi đang thiết lập $cbằng với một số chuỗi .length . Điều này sẽ hình thành phần đệm cần thiết của chúng tôi. Bên trong chuỗi là một khối mã ngay lập tức $(...), do đó mã sẽ được thực thi trước khi đánh giá vào chuỗi.

Trong khối mã, chúng tôi sẽ gửi ba mục thông qua |sortlệnh và sau đó lấy mục lớn nhất (...)[-1]. Đây là nơi chúng tôi đảm bảo có được các cột có chiều rộng chính xác. Ba mục là $lsố dòng, trong đó chúng tôi -splittrên dòng mới, số $wtừ, nơi chúng tôi -splittrên khoảng trắng và $bđộ dài.

Dòng thứ hai là đầu ra của chúng tôi bằng cách sử dụng -ftoán tử (là một tốc ký giả choString.Format() ). Đó là một cách khác để chèn các biến mở rộng vào chuỗi. Ở đây, chúng tôi nói rằng chúng tôi muốn tất cả các đầu ra được đệm ở bên trái để mỗi cột $crộng. Các phần đệm được thực hiện thông qua các không gian. Các 0, 12tương ứng với các $l, $w$bđó là lý lẽ để các nhà điều hành định dạng, vì vậy số lượng dòng, số từ, và đếm byte là đệm và đầu ra một cách thích hợp.

Lưu ý rằng điều này yêu cầu chuỗi phải có các dòng mới đã được mở rộng (ví dụ: thực hiện một Get-Contenttệp văn bản hoặc một cái gì đó, sau đó chuyển hoặc lưu chuỗi đó vào một biến, sau đó gọi mã này trên đầu vào đó) hoặc sử dụng PowerShell- ký tự thoát theo kiểu với backticks (có nghĩa là `nthay vì \n).

Thí dụ

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


0

Ruby, 108 byte

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 byte

bao gồm +1 cho -n

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

Đã bình luận:

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
  • Lưu một byte khác, một lần nữa nhờ vào @TonH rửa.
  • Lưu 9 byte nhờ @TonH rửa cho tôi thấy một vài thủ thuật của giao dịch!

Một vài thủ thuật của giao dịch: Sử dụng y///cnhư một chiều dài ngắn hơn $_. split$"trong bối cảnh vô hướng cho số lượng từ trong $_. Bằng cách sử dụng một biến chấm câu như $;thay vì $Wbạn có thể đặt dngay sau phép nội suy trong chuỗi định dạng. Sau đó, bạn có thể thả dvào $Wvà thả dấu ngoặc đơn. Và -pkhông có gì hơn -n, chỉ cần để việc printfin ấn (thêm một dòng mới để nếm thử)
TonMedel

Tuyệt vời, tôi đánh giá cao nó!
Kenney

Một chuỗi tính toán như $a=foo;$b=bar$athường có thể được viết là $b=bar($a=foo), tiết kiệm một byte. Áp dụng ở đây để $;$b. Bạn không quan tâm nếu $;được tính toán lại mỗi lần
TonMedel

Cảm ơn! Tôi đã bỏ qua điều đó bởi vì có hai khối ...
Kenney

0

Lua, 74 66 byte

Chơi gôn

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

Ung dung:

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

Nhận đầu vào thông qua các đối số dòng lệnh.

Chúng tôi đổi tên đối số đầu tiên (arg[1] ) để lưu byte. string.gsubtrả về số lượng thay thế cũng như chuỗi đã sửa đổi, vì vậy chúng tôi đang sử dụng số đó để đếm trước '\n'(dòng mới), sau đó '%S+'(các trường hợp của một hoặc nhiều ký tự không phải khoảng trắng, càng nhiều càng tốt, tức là các từ). Chúng ta có thể sử dụng bất cứ thứ gì chúng ta muốn cho chuỗi thay thế, vì vậy chúng ta sử dụng chuỗi rỗng ( '') để lưu byte. Sau đó, chúng ta chỉ cần sử dụng string.lenđể tìm độ dài của chuỗi, tức là số byte. Sau đó, cuối cùng, chúng tôi in tất cả.


Mặc dù vậy, tôi không thấy bất kỳ phần đệm bên trái nào của các giá trị dòng và từ
TonMedel 27/2/2016

0

Võng mạc, 65

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

Hãy thử trực tuyến!

Giai đoạn đầu tiên là chương trình wc thực tế, phần còn lại dành cho phần đệm. Điều agiữ chỗ có lẽ là không cần thiết, và một số nhóm có thể được đơn giản hóa một chút.


0

Haskell, 140 byte

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

Phiên bản không được đề cập dưới đây, với các tên hàm và biến được mở rộng:

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

Đây là một hàm chấp nhận một chuỗi và trả về một chuỗi. Nó chỉ sử dụng các Preludehàm words(resp. lines) Để lấy số lượng từ (dòng tương ứng) cho rằng chúng dường như sử dụng cùng một định nghĩa wc, sau đó nhận giá trị dài nhất (dưới dạng chuỗi) trong số đếm và sử dụng định dạng printf chiều rộng giữa các đối số của nó để định dạng.



0

05AB1E , 24 23 byte

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

jhiện đang bị lỗi, vì vậy có thể có 21 byte mà không có §J ..

Dùng thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

¨          # 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

Pip -s , 25 byte

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

Lấy chuỗi multiline làm đối số dòng lệnh. Hãy thử trực tuyến!

Cảm ơn câu trả lời của Dennis's CJam khiến tôi nhận ra rằng số dài nhất luôn là số lượng nhân vật.

Giải trình

                           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)

Đây là một giải pháp 29 byte với các cờ -rslấy đầu vào từ stdin:

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

Hãy thử trực tuyến!


0

Powershell, 123 115 byte

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

Kịch bản thử nghiệm:

$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"
}

Đầu ra:

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

Giải trình:

  • $args|% t*y chia chuỗi arument thành chars
  • switch -r($args|% t*y)đánh giá tất cả các trường hợp khớp
    • '\s' trường hợp cho bất kỳ khoảng trắng
    • '\S' trường hợp cho bất kỳ khoảng trắng
    • '(?s).' trường hợp cho bất kỳ char (bao gồm dòng mới)
    • '\n' trường hợp cho char dòng mới (dòng mới đại diện cho chính nó)
  • $c="$b".Lengthtính toán độ dài của số byte. $ b luôn là tối đa ($ l, $ w, $ b) theo thiết kế
  • "{0,$c} {1,$c} $b"-f$l,+$wsố định dạng với cùng độ dài. Biến $ w chuyển đổi thành int. Nó cần cho chuỗi không có từ. Các biến khác định dạng 'như hiện tại' vì 'Đầu vào sẽ luôn chứa một dòng mới theo dõi' và $ l và $ b không thể là 0.
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.