Implementasikan kembali core core wc

27

Tantangan ini mirip dengan yang lama ini , tetapi dengan beberapa bagian spesifikasi yang tidak jelas dipalu dan persyaratan I / O yang kurang ketat.


Diberikan input dari string yang hanya terdiri dari ASCII dan baris baru yang dapat dicetak, menampilkan berbagai metriknya (byte, kata, jumlah baris).

Metrik yang harus Anda keluarkan adalah sebagai berikut:

  • Hitungan Byte. Karena string input tetap berada dalam ASCII, ini juga merupakan jumlah karakter.

  • Jumlah kata. Ini adalah wcdefinisi dari "kata:" setiap urutan bukan spasi. Misalnya, abc,def"ghi"adalah satu "kata."

  • Jumlah baris. Ini cukup jelas. Input akan selalu berisi baris baru tambahan, yang berarti jumlah baris sama dengan "jumlah baris baru." Tidak akan ada lebih dari satu baris baru.

Output harus benar-benar mereplikasi wcoutput default (kecuali untuk nama file):

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

Perhatikan bahwa jumlah baris lebih dulu, kemudian jumlah kata, dan akhirnya jumlah byte. Selanjutnya, setiap hitungan harus dibiarkan berlapis dengan spasi sedemikian sehingga semuanya memiliki lebar yang sama. Dalam contoh di atas, 5501adalah angka "terpanjang" dengan 4 digit, jadi 165diisi dengan satu spasi dan 90dengan dua. Akhirnya, semua angka harus digabungkan menjadi satu string dengan spasi di antara setiap angka.

Karena ini adalah , kode terpendek dalam byte akan menang.

(Oh, dan omong-omong ... Anda tidak dapat menggunakan wcperintah dalam jawaban Anda. Seandainya itu belum jelas.)

Kasing uji ( \nmewakili baris baru; Anda juga dapat juga memerlukan baris tambahan tambahan):

"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"
Gagang pintu
sumber
2
Aku akan VTC yang lama sebagai penipu yang satu ini karena yang ini adalah tantangan yang jauh lebih baik.
Mego
Haruskah input kosong didukung?
Ton Hospel
Saya kira tidak, katanya semua input diakhiri dengan \ n.
CalculatorFeline

Jawaban:

8

Perl, 49 byte

Menambahkan +3 untuk -an0

Masukan pada STDIN atau 1 nama file atau lebih sebagai argumen. Jalankan sebagaiperl -an0 wc.pl

wc.pl:

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

Penjelasan:

-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
Ton Hospel
sumber
7

Python 2, 100 77 byte

Solusi ini adalah fungsi Python yang menerima string multi-line dan mencetak jumlah yang diperlukan untuk stdout. Perhatikan bahwa saya menggunakan string format untuk membangun string format (yang mengharuskan %%untuk keluar dari placeholder format pertama).

Sunting: Disimpan 23 byte karena optimisasi cetak oleh Dennis.

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

Sebelum minifier, tampilannya seperti ini:

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

Pyth, 21 byte

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

Suite uji

Pyth memiliki beberapa built-in yang sangat bagus di sini. Kita mulai dengan membuat daftar ( [) baris baru dalam string ( @bQ), kata-kata dalam string ( cQ)) dan string itu sendiri ( Q). Kemudian, kita pad ( .[) panjang setiap string ( ld) dengan spasi ( ;dalam konteks ini) hingga panjang jumlah karakter ( l`lQ). Akhirnya, bergabunglah dengan spasi ( jd).

isaacg
sumber
6

POSIX awk, 79 75 67 65 bytes

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

Edit: disimpan 4 bytes sejak POSIX memungkinkan telanjang length, diselamatkan 7 byte dengan mendiskontokan bagian doa, dan menyelamatkan dua byte berkat ujung Doorknob untuk menambahkan d %ke d.

Ini awalnya untuk GNU awk, tapi yang terbaik yang bisa saya katakan, ini hanya menggunakan fungsionalitas awk POSIX.

Lebih baik diformat:

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
}'
muru
sumber
@ Doorknob OK, terima kasih untuk itu. Kira Anda melihat percakapan obrolan? Juga, pertanyaan itu harus lulus dari faq yang diusulkan ke faq .
muru
1
Oh, saya tidak melihat Anda dalam obrolan; jawaban Anda baru saja muncul di kotak masuk saya: PI adalah orang yang menambahkan [faq-usulan] untuk pertanyaan itu, jadi mungkin saya akan memeriksa di ruang mod sebelum memutakhirkannya ke [faq].
Gagang Pintu
1
Pengaturan dke length(c)"d %"seharusnya memungkinkan Anda untuk mengubah printfke "%"d d"d\n", yang menghemat dua byte.
Gagang Pintu
1
@Doorknob memang, terima kasih! Kira itu bukan yang eksotis , tetapi duniawi yang menyimpan byte.
muru
6

Serius , 39 byte

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

Cobalah online!

Penjelasan (baris baru diganti dengan \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
Mego
sumber
Saya tidak dapat menemukan dokumentasi untuk bahasa ini, dapatkah Anda memberikan tautan?
JohnEye
2
@JohnEye, github.com/Mego/Serius
awesoon
3

AppleScript, 253 byte

Ini mengasumsikan bahwa pembatas item teks AppleScript diatur ke spasi (jika saya perlu menghitung hal-hal untuk memaksa asumsi itu, saya akan menambahkannya).

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
Addison Crump
sumber
3

CJam, 31 26 byte

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

Cobalah online!

Bagaimana itu bekerja

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.
Dennis
sumber
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

Ini adalah fungsi yang menerima string dan mengembalikan string.

Kami menyimpan yang berikut sebagai argumen fungsi:

  • n = endof fungsi, yang mendapatkan indeks terakhir dari koleksi yang dapat diindeks (dalam hal ini adalah panjang string)
  • l = "$(n(s)), panjang input dikonversi ke string menggunakan interpolasi
  • Fungsi lambda gyang menerima ekspresi reguler dan mengembalikan panjang - 1 dari input split pada regex itu, dibiarkan empuk dengan spasi untuk mencocokkan panjang l.

Kami mendapatkan jumlah baris menggunakan g(r"\n")dan jumlah kata menggunakan g(r"\S+"), kemudian kami bergabung dengan mereka bersama dengan ldibatasi oleh spasi.

Disimpan 31 byte berkat Dennis!

Alex A.
sumber
2

MATL, 38 byte

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

Anda dapat mencobanya secara online! Ini seharusnya tidak terlalu lama ...

Penjelasan, untuk perhitungan,

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

Bagian terakhir melakukan pemformatan output

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)
David
sumber
Bagus sekali! Mungkin menghapus bendera "debug" di tautan Coba online ?
Luis Mendo
Ahh ups! Terimakasih atas peringatannya!
David
Saya pikir Anda dapat mengganti !3Z"vX:!dengan Z{Zc( cellstrdiikuti oleh 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` `

Tidak memerlukan input apa pun. Memformat itu menyakitkan. Jika ada batas atas jumlah padding saya bisa menguranginya (' '.repeat(99)+n)menjadi sesuatu yang lebih pendek mis ` ${n}`.

Neil
sumber
Saya pikir Anda dapat mengganti /[^]/gdengan /./guntuk menyimpan dua byte
Patrick Roberts
@ PatrickRoberts Tidak, itu melompati baris baru, jadi hitungan saya tidak aktif.
Neil
Ah, tidak pernah memperhatikan itu sebelumnya.
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

(baris baru tersisa untuk kejelasan: D)

Baris pertama mengambil input $a, dan kemudian bagian selanjutnya adalah semua pernyataan. Kami menetapkan $csama dengan beberapa-string .length . Ini akan membentuk padding yang kami butuhkan. Di dalam string adalah blok kode langsung $(...), sehingga kode itu akan dieksekusi sebelum dievaluasi ke dalam string.

Di blok kode, kami mengirim tiga item melalui |sortperintah, dan kemudian mengambil yang terbesar (...)[-1]. Di sinilah kami memastikan untuk mendapatkan kolom dengan lebar yang benar. Tiga item adalah $ljumlah baris, di mana kita berada -splitdi baris baru, jumlah $wkata, di mana kita berada -splitdi spasi, dan $bpanjangnya.

Baris kedua adalah output kami menggunakan -foperator (yang merupakan singkatan semu untuk String.Format()). Ini cara lain untuk memasukkan variabel yang diperluas ke string. Di sini, kami mengatakan bahwa kami ingin semua output diisi ke kiri sehingga setiap kolom $clebar. Padding dilakukan melalui spasi. The 0, 1dan 2bersesuaian dengan $l, $w, dan $byang argumen untuk operator Format, sehingga jumlah baris, jumlah kata, dan jumlah byte yang empuk dan output tepat.

Perhatikan bahwa ini mengharuskan string untuk memiliki baris baru yang sudah diperluas (mis. Melakukan a Get-Contentpada file teks atau sesuatu, dan kemudian memipangkan atau menyimpannya ke suatu variabel, kemudian memanggil kode ini pada input itu), atau menggunakan PowerShell- karakter melarikan diri bergaya dengan backticks (artinya `nbukannya \n).

Contoh

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

Jelly , 14 byte

»⁶Ḳ¹ƇLṭċ⁷$;LWG

Cobalah online!

-1 terima kasih kepada Dennis .

Erik the Outgolfer
sumber
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}*" "}
bersemangat
sumber
0

Perl, 71 62 61 byte

termasuk +1 untuk -n

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

Berkomentar:

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
  • Simpan byte lain, sekali lagi terima kasih kepada @TonHospel.
  • Hemat 9 byte berkat @TonHospel yang menunjukkan kepada saya beberapa trik perdagangan!
Kenney
sumber
Beberapa trik perdagangan: Gunakan y///csebagai panjang yang lebih pendek $_. split$"dalam konteks skalar memberikan jumlah kata dalam $_. Dengan menggunakan variabel tanda baca seperti $;bukannya $WAnda dapat menempatkan dsetelah interpolasi dalam format string. Kemudian Anda bisa drop ddi $Wdan drop kurung. Dan -ptidak ada yang berhasil -n, biarkan printfpencetakannya (tambahkan baris baru secukupnya)
Ton Hospel
Luar biasa, saya menghargainya!
Kenney
Rantai perhitungan seperti $a=foo;$b=bar$abiasanya dapat ditulis sebagai $b=bar($a=foo), menghemat satu byte. Berlaku di sini untuk $;dan $b. Anda tidak peduli jika $;dihitung ulang setiap saat
Ton Hospel
Terima kasih! Saya mengabaikan hal itu karena ada dua blok ...
Kenney
0

Lua, 74 66 byte

Golf:

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

Tidak Disatukan:

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

Menerima input melalui argumen baris perintah.

Kami mengganti nama argumen pertama ( arg[1]) untuk menyimpan byte. string.gsubmengembalikan jumlah penggantian serta string yang dimodifikasi, jadi kami menggunakannya untuk menghitung terlebih dahulu '\n'(baris baru), kemudian '%S+'(contoh dari satu atau lebih karakter non-spasi, sebanyak mungkin, yaitu kata-kata). Kita dapat menggunakan apapun yang kita inginkan untuk string pengganti, jadi kita menggunakan string kosong ( '') untuk menyimpan byte. Kemudian kita gunakan saja string.lenuntuk mencari panjang string, yaitu jumlah byte. Lalu, akhirnya, kami cetak semuanya.

Jesse Paroz
sumber
Saya tidak melihat padding kiri nilai garis dan kata-kata
Ton Hospel
0

Retina, 65

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

Cobalah secara Online!

Tahap pertama adalah program wc yang sebenarnya, sisanya untuk padding. The aplaceholder hal yang mungkin tidak perlu, dan beberapa kelompok mungkin dapat disederhanakan sedikit.

FryAmTheEggman
sumber
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

Versi ungolfed ada di bawah ini, dengan nama variabel dan fungsi diperluas:

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

Ini adalah fungsi yang menerima string dan mengembalikan string. Itu hanya menggunakan Preludefungsi words(resp. lines) Untuk mendapatkan jumlah kata (resp. Lines) mengingat bahwa mereka tampaknya menggunakan definisi yang sama seperti wc, kemudian mendapatkan nilai terpanjang (sebagai string) di antara jumlah dan menggunakan format printf mengambil lebar di antara argumennya untuk pemformatan.

arjanen
sumber
0

C, 180 178 byte

#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);}
pengguna2064000
sumber
111 bytes
ceilingcat
0

05AB1E , 24 23 byte

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

jsaat ini disadap, jadi bisa jadi 21 byte tanpa §dan J..

Cobalah secara online atau verifikasi semua kasus uji .

Penjelasan:

¨          # 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)
Kevin Cruijssen
sumber
0

Pip -s , 25 byte

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

Mengambil string multiline sebagai argumen baris perintah. Cobalah online!

Terima kasih atas jawaban CJam Dennis yang membuat saya sadar bahwa angka terpanjang adalah jumlah karakter.

Penjelasan

                           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)

Inilah solusi 29-byte dengan flag -rsyang mengambil input dari stdin:

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

Cobalah online!

DLosc
sumber
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

Skrip uji:

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

Keluaran:

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

Penjelasan:

  • $args|% t*y membagi string arument menjadi karakter
  • switch -r($args|% t*y)mengevaluasi semua kasus yang cocok
    • '\s' kasus untuk spasi putih
    • '\S' kasus untuk non-spasi putih
    • '(?s).' case untuk char apa saja (termasuk baris baru)
    • '\n' case untuk baris newline (baris baru mewakili dirinya sendiri)
  • $c="$b".Lengthmenghitung panjang nomor byte. $ b selalu maks ($ l, $ w, $ b) menurut desain
  • "{0,$c} {1,$c} $b"-f$l,+$wformat angka dengan panjang yang sama. Variabel $ w dikonversi ke int. Perlu untuk string tanpa kata-kata. Variabel lain memformat 'sebagaimana adanya' karena 'Input akan selalu berisi baris baru' dan $ l dan $ b tidak boleh 0.
mazzy
sumber