Wc coreutil bileşeninin yeniden düzenlenmesi


27

Bu zorluk bu eskisine benziyor , ancak spekülasyonun belirsiz kısımları dövülmüş ve daha az katı G / Ç gereklilikleri var.


Yalnızca yazdırılabilir ASCII ve yeni satırlardan oluşan bir dizgenin girişi göz önüne alındığında, çeşitli metrikleri (bayt, sözcük, satır sayısı) çıktılar.

Çıkmanız gereken metrikler aşağıdaki gibidir:

  • Bayt sayısı Giriş dizesi ASCII içinde kaldığından, bu aynı zamanda karakter sayımıdır.

  • Sözcük sayısı. Bu, wcbir "kelimenin:" tanımı, boşluk olmayan herhangi bir dizilimdir. Örneğin abc,def"ghi", bir "kelime" dir.

  • Satır sayısı Bu kendi kendini açıklayıcı. Girdi her zaman sonunda yeni bir satır içerecektir, bu da satır sayısının "yeni satır sayımı" ile eşanlamlı olduğu anlamına gelir. Asla tek bir son hattan daha fazlası olmayacak.

Çıktı tam olarak varsayılan wcçıktıyı çoğaltmalıdır (dosya adı hariç):

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

Satır sayısı önce gelir sonra sözcük sayımı ve son olarak bayt sayılır. Ayrıca, her sayım, hepsi aynı genişlikte olacak şekilde boşluklarla bırakılmalıdır. Yukarıdaki örnekte, 55014 basamaklı "en uzun" sayıdır, 165bir boşlukla ve 90iki boşlukla doldurulur . Son olarak, sayıların tümü, her sayı arasında boşluk olan tek bir dizgede birleştirilmelidir.

Bu olduğundan, bayttaki en kısa kod kazanır.

(Oh, ve bu arada ... wccevabınızdaki komutu kullanamazsınız . Açıkçası bu durumda değildi.)

Test durumları ( \nyeni bir satırı temsil eder; isteğe bağlı olarak ayrıca sondaki bir yeni satırı da isteyebilirsiniz):

"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
Eski olanı bunun bir kopyası olarak VTC'ye vereceğim çünkü bu çok daha iyi bir mücadele.
Mego

Boş giriş desteklenmeli mi?
Ton Hospel

Sanmıyorum, tüm girdilerin \ n ile biteceğini söyledi.
Hesap MakinesiFeline

Yanıtlar:


8

Perl, 49 bayt

İçin +3 eklendi -an0

STDIN veya 1 veya daha fazla dosya ismine argüman olarak girin. Olarak çalıştırmakperl -an0 wc.pl

wc.pl:

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

Açıklama:

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

Bu çözüm çok satırlı bir dize kabul eden ve gerekli sayıları stdout'a basan bir Python işlevidir. Bir biçim dizesi oluşturmak için bir biçim dizesi kullandığımı unutmayın (bu %%, ilk biçim yer tutucusundan çıkmak için gereken ).

Düzenleme: Dennis tarafından yapılan baskı optimizasyonları nedeniyle 23 bayt kaydedildi.

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

Minifierden önce şöyle gözüküyor:

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

7

Pyth, 21 bayt

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

Test odası

Pyth'un burada çok hoş bazı yapıları var. [Dize ( @bQ) içindeki yeni satırların bir listesini ( ), dizindeki ( ) kelimeleri cQ)ve dizinin kendisini ( Q) yaparak başlarız . Daha sonra, .[her dizginin ( ld) uzunluğunu boşluklarla ( ;bu bağlamda) karakter sayısının uzunluğuna kadar ( l`lQ) kaydırıyoruz . Son olarak, boşluklara ( jd) katılın .


6

POSIX awk, 79 75 67 65 bayt

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

Düzenleme: POSIX çıplak izin verdiği 4 bayt kaydedilmiş length, çağırma kısmını indirim yaparak 7 bayt kaydedildi ve eklemek için kapı koluna en ucuna iki bayt sayesinde kurtardı d %için d.

Bu başlangıçta GNU awk içindi, ama söyleyebileceğim en iyisi, sadece POSIX awk işlevini kullanıyor.

Daha iyi biçimlendirilmiş:

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 Tamam, bunun için teşekkürler. Sohbet sohbeti gördün mü? Ayrıca mezun gerektiğini soru sss önerdiği için sss .
muru

1
Ah, seni sohbette görmedim; Cevabınız az önce gelen kutumda belirdi: PI bu soruya [SSS önerisi] ekleyen kişiydi, bu yüzden belki de [SSS] 'ye yükseltmeden önce mod odasında kontrol edeceğim.
Doorknob

1
Ayar diçin length(c)"d %"değiştirmek izin vermelidir printfiçin "%"d d"d\n"iki bayt kazandırır,.
Doorknob

1
@Doorknob gerçekten, teşekkürler! Sanırım egzotik değil , bayttan tasarruf eden sıradan.
muru

6

Cidden , 39 bayt

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

Çevrimiçi deneyin!

Açıklama (newlines ile değiştirilir \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

Bu dil için herhangi bir belge bulamıyorum, bir bağlantı verebilir misiniz?
JohnEye


3

AppleScript, 253 bayt

Bu, AppleScript'in metin öğesi sınırlayıcılarının boşluğa ayarlandığını varsayar (bu varsayımı zorlamak için öğeleri saymam gerekirse, ekleyeceğim).

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 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

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 bayt

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

Bu bir dizgeyi kabul eden ve bir dize döndüren bir işlevdir.

Aşağıdakileri işlev argümanları olarak kaydederiz:

  • n = endof Dizine eklenebilir bir koleksiyonun son dizinini alan işlev (bu durumda dizenin uzunluğu)
  • l = "$(n(s))enterpolasyon kullanarak bir dizgeye dönüştürülen girişin uzunluğu
  • gDüzenli bir ifadeyi kabul eden ve uzunluğu döndüren bir lambda işlevi - bu regex üzerindeki giriş bölümünün uzunluğunu döndürür - uzunluğu ile eşleşmesi için boşluklarla doldurulur l.

Kullanılan satır g(r"\n")sayısını ve kullanılan sözcük sayısını g(r"\S+")alıyoruz, daha sonra lboşluklarla ayrılmış olanlara katılıyoruz .

Dennis sayesinde 31 bayt kurtarıldı!


2

MATL, 38 bayt

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

Şunları yapabilirsiniz çevrimiçi deneyin! Bu o kadar uzun olmamalıydı ...

Hesaplama için açıklama,

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

Son kısım çıktı biçimlendirmesini yapar

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)

Güzel bitti! Belki de Çevrimiçi dene bağlantısındaki "debug" bayrağını kaldırmalı ?
Luis Mendo

Ahh whoops! Başınız için teşekkürler!
David,

Sana yerini alabilir mi !3Z"vX:!tarafından Z{Zc( cellstrizledi strjoin)
Luis Mendo

1

JavaScript (ES6), 115 bayt

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

Herhangi bir giriş gerektirmez. Biçimlendirme acı vericiydi. Dolgu miktarının üst sınırı olsaydı, (' '.repeat(99)+n)örneğin daha kısa bir şeye indirgeyebilirdim ` ${n}`.


İki byte'ı kurtarmak için /[^]/gonunla değiştirebileceğini düşünüyorum/./g
Patrick Roberts

@PatrickRoberts Hayır, bu yeni satırları atlar, böylece sayım kapanır.
Neil,

Ah, daha önce hiç farketmedim.
Patrick Roberts

1

PowerShell, 140 bayt

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

(netlik için newline kaldı: D)

İlk satır girdi alır $ave sonraki bölüm birer ifadedir. Bazı string'lere $ceşit ayar yapıyoruz . Bu, gerekli dolguyu oluşturacak. Dize içinde hemen bir kod bloğudur , bu yüzden kod değerlendirilmeden önce kod çalıştırılır. .length$(...)

Kod bloğunda, |sortkomut aracılığıyla üç öğe gönderiyoruz ve ardından en büyüğünü alıyoruz (...)[-1]. Bu, sütunları doğru genişliğe almayı garanti ediyoruz. Üç madde $l, satır sayıları, -splityeni satırlarda bulunduğumuz satır sayısı, $wkelime sayımı, -splitboşluktaki yer ve $buzunluk.

İkinci satır ise -foperatörü kullanarak çıktımızdır (ki bu bir sahte kısayol String.Format()) Genişleyen değişkenleri dizgelere eklemenin başka bir yolu. Burada, çıktının tümünün sola doğru doldurulmasını istediğimizi, böylece her sütun $cgeniş olacağını söylüyoruz . Dolgu boşluklar yoluyla yapılır. 0, 1Ve 2için karşılık gelir $l, $wve $bsatır sayısı, kelime sayısı ve bayt sayısı uygun şekilde doldurulur ve çıkış olacak şekilde biçimi operatöre argümanlar vardır.

Bunun, dize genişletilmiş yeni satırlara sahip olmasını gerektirir (örneğin, Get-Contentbir metin dosyasında veya başka bir şeyde bir işlem yapmak ve daha sonra bunları bir değişkene pipetlemek veya kaydetmek, daha sonra bu kodu o girişte çağırmak) veya PowerShell- backticks ile tarz kaçış karakterleri ( `nyerine \n).

Örnek

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


0

Ruby, 108 bayt

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 bayt

için +1 içerir -n

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

Yorumlananlar:

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 sayesinde bir başka baytı tekrar kaydedin.
  • @TonHospel sayesinde bana ticaretin birkaç püf noktasını gösteren 9 bayt kazandır!

Ticaretin birkaç püf noktası: Daha y///ckısa bir uzunluk olarak kullanın $_. split$"skaler bağlamda içindeki kelimelerin sayısını verir $_. Bunun $;yerine bir noktalama değişkeni kullanarak , biçim dizesindeki enterpolasyondan hemen sonra $Wkoyabilirsiniz d. Sonra bırakın din $Wve parantezi bırakın. Ve -phiçbir şey -nprintf
kazanmaz

Müthiş, minnettarım!
Kenney

Gibi bir hesaplama zinciri $a=foo;$b=bar$agenellikle $b=bar($a=foo)bir bayt tasarrufu olarak yazılabilir . Burada $;ve ile uygulanabilir $b. $;Her seferinde yeniden hesaplanması umrunda değil
Ton Hospel

Teşekkürler! Göz ardı ettim çünkü iki blok var ...
Kenney

0

Lua, 74 66 bayt

golfed:

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

Ungolfed:

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

Komut satırı argümanları üzerinden girdi alır.

Baytları arg[1]kurtarmak için ilk argümanı ( ) yeniden adlandırıyoruz . string.gsubdeğiştirilen dizenin yanı sıra değiştirmelerin sayısını döndürür, bu yüzden bunu önce saymak için kullanırız '\n'(yeni satırlar), sonra '%S+'(bir veya daha fazla beyaz olmayan karakter, örneğin, olabildiğince fazla). Değiştirme dizesi için istediğimiz her şeyi kullanabiliriz, bu nedenle ''baytları kaydetmek için boş dizeyi ( ) kullanırız. Sonra sadece string.lendize uzunluğunu, yani bayt sayısını bulmak için kullanırız . Sonra nihayet hepsini basarız.


Yine de satırların ve kelimelerin sol dolgusunu göremiyorum
Ton Hospel

0

Retina, 65

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

Çevrimiçi Deneyin!

İlk aşama gerçek wc programıdır, geri kalanı dolgu için. Yer atutucu şey muhtemelen gereksizdir ve gruplardan bazıları muhtemelen biraz basitleştirilebilir.


0

Haskell, 140 bayt

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

Ungolfed versiyonu genişletilmiş değişken ve fonksiyon adlarıyla aşağıdadır:

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

Bu bir dizgeyi kabul eden ve bir dize döndüren bir işlevdir. Aynı Preludeişlevleri kullandıkları düşünüldüğünde, sadece sözcük sayısını (satır başına) almak için işlevleri words(sırasıyla lines) kullanır wc, ardından sayılar arasında en uzun değeri (bir dize olarak alır) ve printf biçimini kullanır. biçimlendirme argümanlarının arasındaki genişlik.


0

C, 180 178 bayt

#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

05AB1E , 24 23 bayt

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

jşu anda bugged, bu yüzden §ve olmadan J.. 1 byte olabilirdi

Çevrimiçi deneyin veya tüm test durumlarını doğrulayın .

Açıklama:

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

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

Çok satırlı dizeyi komut satırı argümanı olarak alır. Çevrimiçi deneyin!

Sayesinde Dennis'in CJam cevap bana en uzun sayının her zaman karakter sayımı olduğunun farkına .

açıklama

                           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)

İşte -rsstdin'den girdi alan bayraklara sahip 29 baytlık bir çözüm :

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

Çevrimiçi deneyin!


0

Powershell, 123 115 bayt

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

Test komut dosyası:

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

Çıktı:

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

Açıklama:

  • $args|% t*y argü dizgilerini karakterlere böler
  • switch -r($args|% t*y)tüm eşleşmiş durumları değerlendir
    • '\s' Herhangi bir boşluk için durum
    • '\S' boşluksuz herhangi bir durum için dava
    • '(?s).' Herhangi bir char için durum (newline dahil)
    • '\n' newline char için durum (newline kendisini temsil eder)
  • $c="$b".Lengthbayt sayısının uzunluğunu hesaplar. $ b her zaman maksimum ($ l, $ w, $ b) tasarımına göredir
  • "{0,$c} {1,$c} $b"-f$l,+$wsayıları aynı uzunlukta biçimlendirin. $ W değişkeni int'ye dönüştürülür. Kelimesi olmayan dizgelere ihtiyaç duyar. Diğer değişkenler biçimleri 'olduğu gibi' çünkü 'Girdi her zaman sonunda bir satırsonu içerecektir' ve $ l ve $ b 0 olamaz.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.