Reimplementa il coreutil del wc


27

Questa sfida è simile a questa vecchia , ma con alcune parti poco chiare delle specifiche eliminate e requisiti di I / O meno rigidi.


Dato un input di una stringa composta solo da ASCII e newline stampabili, emette le sue varie metriche (byte, word, line count).

Le metriche che devi produrre sono le seguenti:

  • Conteggio byte. Poiché la stringa di input rimane all'interno di ASCII, questo è anche il conteggio dei caratteri.

  • Conteggio parole. Questa è wcla definizione di "parola:" qualsiasi sequenza di spazi non bianchi. Ad esempio, abc,def"ghi"è una "parola".

  • Conteggio righe. Questo si spiega da sé. L'input conterrà sempre una nuova riga finale, il che significa che il conteggio delle linee è sinonimo di "conteggio nuove righe". Non ci sarà mai più di una sola nuova riga finale.

L'output deve replicare esattamente l' wcoutput predefinito (ad eccezione del nome del 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

Si noti che il conteggio delle righe viene prima, quindi conteggio delle parole e infine conteggio dei byte. Inoltre, ogni conteggio deve essere imbottito a sinistra con spazi tali da avere tutti la stessa larghezza. Nell'esempio sopra, 5501è il numero "più lungo" con 4 cifre, quindi 165è riempito con uno spazio e 90con due. Infine, tutti i numeri devono essere uniti in un'unica stringa con uno spazio tra ciascun numero.

Dato che si tratta di , vincerà il codice più breve in byte.

(Oh, e comunque ... non puoi usare il wccomando nella tua risposta. Nel caso non fosse già ovvio.)

Casi di test ( \nrappresenta una nuova riga; potresti facoltativamente richiedere anche una nuova riga finale):

"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
Vado il vecchio VTC come un duplicato di questo perché questo è una sfida molto migliore.
Mego,

L'input vuoto dovrebbe essere supportato?
Ton Hospel,

Non credo, ha detto che tutti gli input finiscono con \ n.
Calcolatrice

Risposte:


8

Perl, 49 byte

Aggiunto +3 per -an0

Immettere su STDIN o 1 o più nomi di file come argomenti. Correre comeperl -an0 wc.pl

wc.pl:

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

Spiegazione:

-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

Questa soluzione è una funzione Python che accetta una stringa multilinea e stampa i conteggi richiesti su stdout. Si noti che utilizzo una stringa di formato per creare una stringa di formato (che richiede a %%per evitare il primo segnaposto di formato).

Modifica: salvato 23 byte grazie alle ottimizzazioni di stampa di Dennis.

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

Prima del minificatore, è simile al seguente:

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

7

Pyth, 21 byte

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

Suite di test

Pyth ha alcuni built-in molto belli qui. Iniziamo creando un elenco ( [) delle nuove righe nella stringa ( @bQ), le parole nella stringa ( cQ)) e la stringa stessa ( Q). Quindi, pad ( .[) la lunghezza di ogni stringa ( ld) con spazi ( ;in questo contesto) fino alla lunghezza del numero di caratteri ( l`lQ). Infine, unisciti a spazi ( 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}

Modifica: salvato 4 byte poiché POSIX consente length7 byte vuoti , salvati scontando la parte di chiamata, e salvati due byte grazie al suggerimento di Doorknob per l'aggiunta d %a d.

Questo era originariamente per GNU awk, ma la cosa migliore che posso dire, utilizza solo la funzionalità POSIX awk.

Meglio formattato:

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, grazie per quello. Immagina di aver visto la conversazione in chat? Inoltre, tale domanda dovrebbe passare dalle domande frequenti alle domande frequenti .
Muru,

1
Oh, non ti ho visto in chat; la tua risposta è appena arrivata nella mia casella di posta: PI è stato colui che ha aggiunto [faq-proposta] a quella domanda, quindi forse controllerò la mod room prima di aggiornarla a [faq].
Maniglia della porta

1
L'impostazione dsu length(c)"d %"dovrebbe consentire di modificare printfin "%"d d"d\n", che consente di risparmiare due byte.
Maniglia della porta

1
@Doorknob davvero, grazie! Immagino che non sia l'esotico , ma il banale che salva i byte.
Muru,

6

Scherzi a parte , 39 byte

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

Provalo online!

Spiegazione (le nuove righe vengono sostituite con \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

Non riesco a consultare alcuna documentazione per questa lingua, puoi fornire un link?
JohnEye,


3

AppleScript, 253 byte

Ciò presuppone che i delimitatori degli elementi di testo di AppleScript siano impostati sullo spazio (se devo contare le cose per forzare tale presupposto, lo aggiungerò).

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*

Provalo online!

Come funziona

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

Questa è una funzione che accetta una stringa e restituisce una stringa.

Salviamo quanto segue come argomenti di funzione:

  • n = endof funzione, che ottiene l'ultimo indice di una raccolta indicizzabile (in questo caso è la lunghezza della stringa)
  • l = "$(n(s)), la lunghezza dell'input convertita in una stringa mediante l'interpolazione
  • Una funzione lambda gche accetta un'espressione regolare e restituisce la lunghezza - 1 della suddivisione in input su quella regex, a sinistra riempita con spazi corrispondenti alla lunghezza di l.

Otteniamo il numero di linee usando g(r"\n")e il numero di parole usando g(r"\S+"), quindi uniamo quelli insieme con ldelimitati da spazi.

Risparmiato 31 byte grazie a Dennis!


2

MATL, 38 byte

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

Puoi provarlo online! Non dovrebbe essere così lungo però ...

Spiegazione, per il calcolo,

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

L'ultima parte esegue la formattazione dell'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)

Ben fatto! Forse rimuovere il flag "debug" nel collegamento Provalo online ?
Luis Mendo,

Ah! Grazie per il testa a testa!
David,

Penso che si possa sostituire !3Z"vX:!da Z{Zc( cellstrseguito da 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` `

Non richiede alcun input. La formattazione è stata dolorosa. Se ci fosse un limite superiore alla quantità di imbottitura, potrei ridurre (' '.repeat(99)+n)a qualcosa di più corto, ad es ` ${n}`.


Penso che puoi sostituire /[^]/gcon /./gper salvare due byte
Patrick Roberts,

@PatrickRoberts No, questo salta le righe, quindi il mio conteggio sarebbe disattivato.
Neil,

Ah, non l'avevo mai notato prima.
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

(newline lasciato per chiarezza: D)

La prima riga accetta input $a, quindi la parte successiva è tutta un'istruzione. Stiamo impostando $cuguale a quello di alcune stringhe .length . Questo formerà la nostra imbottitura necessaria. All'interno della stringa è presente un blocco di codice immediato $(...), pertanto tale codice verrà eseguito prima di essere valutato nella stringa.

Nel blocco di codice, stiamo inviando tre elementi tramite il |sortcomando, quindi prendiamo quello più grande (...)[-1]. Qui è dove stiamo assicurando che le colonne abbiano la larghezza corretta. I tre elementi sono $lil conteggio delle righe, dove siamo -splitsu newline, il $wconteggio delle parole, dove siamo-split negli spazi bianchi e $bla lunghezza.

La seconda riga è il nostro output usando l' -foperatore (che è una pseudo-scorciatoia per String.Format()). È un altro modo di inserire variabili espanse nelle stringhe. Qui, stiamo dicendo che vogliamo che tutto l'output sia riempito a sinistra in modo che ogni colonna sia $clarga. L'imbottitura avviene tramite spazi. La 0, 1e 2corrispondono alla $l, $we$b che sono argomenti l'operatore di formato, quindi la linea conteggio, conteggio di parola, e il conteggio di byte sono imbottiti e dell'uscita in modo appropriato.

Si noti che ciò richiede che la stringa abbia linee già espanse (ad esempio, eseguendo un Get-Contentfile di testo o qualcosa del genere, quindi eseguendo il piping o salvandolo in una variabile, quindi chiamando questo codice su quell'input) oppure utilizzare PowerShell- personaggi in stile escape con backtick (che significa `ninvece di \n).

Esempio

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


0

Rubino, 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

include +1 per -n

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

ha commentato:

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
  • Salva un altro byte, ancora una volta grazie a @TonHospel.
  • Risparmia 9 byte grazie a @TonHospel che mi mostra alcuni trucchi del trade!

Alcuni trucchi del mestiere: utilizzare y///ccome una lunghezza inferiore di $_. split$"nel contesto scalare indica il numero di parole in $_. Usando una variabile di punteggiatura come al $;posto di $Wpuoi inserire un dpoco dopo l'interpolazione nella stringa di formato. Quindi è possibile rilasciare din $We rilasciare la parentesi. E -pnon guadagna nulla -n, lascia che printffaccia la stampa (aggiungi una nuova riga a piacere)
Ton Hospel,

Fantastico, lo apprezzo!
Kenney,

Una catena di calcolo come di $a=foo;$b=bar$asolito può essere scritta come $b=bar($a=foo), salvando un byte. Applicabile qui a $;e $b. Non ti importa se $;viene ricalcolato ogni volta
Ton Hospel,

Grazie! L'ho trascurato perché ci sono due blocchi ...
Kenney,

0

Lua, 74 66 byte

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

Riceve input tramite argomenti della riga di comando.

Rinominiamo il primo argomento ( arg[1]) per salvare i byte. string.gsubrestituisce il numero di sostituzioni così come la stringa modificata, quindi stiamo usando quello per contare prima '\n'(newline), quindi '%S+'(istanze di uno o più caratteri non bianchi, quante più possibili, cioè parole). Possiamo usare tutto ciò che vogliamo per la stringa di sostituzione, quindi usiamo la stringa vuota ( '') per salvare i byte. Quindi usiamo solo string.lenper trovare la lunghezza della stringa, cioè il numero di byte. Quindi, infine, stampiamo tutto.


Non vedo nessuna imbottitura a sinistra delle righe e dei valori delle parole, però
Ton Hospel,

0

Retina, 65

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

Provalo online!

Il primo stadio è l'attuale programma WC, il resto è per il riempimento. Il asegnaposto probabilmente non è necessario e alcuni gruppi possono essere semplificati un po '.


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

La versione non modificata è di seguito, con nomi di funzioni e variabili espansi:

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

Questa è una funzione che accetta una stringa e restituisce una stringa. Usa solo le Preludefunzioni words(resp. lines) Per ottenere il numero di parole (resp. Righe) dato che sembrano usare la stessa definizione di wc, quindi ottiene il valore più lungo (come stringa) tra i conteggi e usa il formato printf prendendo la larghezza tra i suoi argomenti per la formattazione.


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


0

05AB1E , 24 23 byte

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

jè attualmente corretto, quindi avrebbe potuto essere di 21 byte senza il §e J..

Provalo online o verifica tutti i casi di test .

Spiegazione:

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

Prende la stringa multilinea come argomento della riga di comando. Provalo online!

Grazie a risposta CJam di Dennis per avermi fatto capire che il numero più lungo è sempre il conteggio dei personaggi.

Spiegazione

                           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)

Ecco una soluzione a 29 byte con flag -rsche accetta input da stdin:

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

Provalo online!


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

Script di prova:

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

Produzione:

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

Spiegazione:

  • $args|% t*y suddivide le stringhe degli oggetti in caratteri
  • switch -r($args|% t*y)valutare tutti i casi corrispondenti
    • '\s' caso per qualsiasi spazio bianco
    • '\S' caso per qualsiasi spazio non bianco
    • '(?s).' custodia per qualsiasi carattere (newline inclusa)
    • '\n' caso per newline char (newline si rappresenta)
  • $c="$b".Lengthcalcola una lunghezza di numero di byte. $ b è sempre massimo ($ l, $ w, $ b) in base alla progettazione
  • "{0,$c} {1,$c} $b"-f$l,+$wformattare i numeri con la stessa lunghezza. La variabile $ w converte in int. Ha bisogno di stringhe senza parole. Altre variabili formattano "come è" perché "L'input conterrà sempre una nuova riga finale" e $ l e $ b non possono essere 0.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.