Повторне доповнення wc coreutil


27

Ця проблема схожа на цю стару , але з деякими незрозумілими частинами специфікації забито і менш суворі вимоги вводу / виводу.


З огляду на введення рядка, що складається лише з ASCII для друку та нових рядків, виведіть різні його показники (байт, слово, кількість рядків).

Показники, які потрібно вивести, такі:

  • Кількість байтів Оскільки вхідний рядок залишається в межах ASCII, це також кількість символів.

  • Підрахунок слів. Це wcвизначення "слова:" будь-якої послідовності непробільного простору. Наприклад, abc,def"ghi"це одне «слово».

  • Кількість рядків Це само собою зрозуміло. Вхід завжди буде містити зворотний новий рядок, а це означає, що кількість рядків є синонімом "кількість нових рядків". Ніколи не буде більше одного єдиного нового рядка.

Вихід повинен точно повторити типовий 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прошито одним пробілом і 90двома. Нарешті, всі числа повинні бути об'єднані в один рядок з пробілом між кожним числом.

Оскільки це , найкоротший код у байтах виграє.

(О, і до речі ... ви не можете використовувати 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
Я буду 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, яка приймає багаторядковий рядок і друкує необхідні рахунки для stdout. Зауважте, що я використовую рядок формату для створення рядка формату (для чого потрібно %%уникнути першого заповнювача формату).

Редагувати: Збережено 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}

Редагувати: збережено 4 байти, оскільки POSIX дозволяє голі length , збережені 7 байт, знизивши частину виклику, і зберегли два байти завдяки підказці Doorknob для додавання d %до 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 ОК, спасибі за це. Здогадаєтесь, ви бачили розмову в чаті? Крім того, це питання має закінчитися з запропонованого faq до faq .
муру

1
О, я не бачив вас у чаті; Ваша відповідь щойно вискакувала у моїй вхідній скриньці: PI був тим, хто додав [запропонований faq] до цього питання, тож, можливо, я перевірю в кімнаті мод, перш ніж оновити її до [faq].
Дверна ручка

1
Установка dдля length(c)"d %"дозволить вам змінити , printfщоб "%"d d"d\n", що економить два байта.
Дверна ручка

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

Я не можу знайти жодну документацію для цієї мови, чи можете ви надати посилання?
JohnEye


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{Zc( cellstrза ним strjoin)
Луїс Мендо,

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щоб зберегти два байта
Патрік Робертс

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

Перший рядок займає введення $a, а потім наступна частина - це все одне твердження. Ми встановлюємо $cрівне деяким рядком .length . Це сформує нашу необхідну підкладку. Всередині рядка знаходиться блок негайного коду $(...), так що цей код буде виконуватися перед тим, як оцінити його в рядку.

У блоці коду ми надсилаємо три елементи через |sortкоманду, а потім беремо найбільший (...)[-1]. Ось тут ми гарантуємо наведення стовпців до правильної ширини. Три елементи - $lце кількість рядків, де ми -splitв нових рядках, $wслово рахуємо, де ми-split у пробілі та$b довжина.

Другий рядок - це наш вихід за допомогою -fоператора (для якого це псевдокоротка String.Format()). Це ще один спосіб вставлення розширених змінних у рядки. Тут ми говоримо, що хочемо, щоб весь результат був прокладений ліворуч, щоб кожен стовпчик був $cшироким. Прокладка робиться через пробіли. 0, 1І 2відповідають $l,$w і$b які є аргументи оператора формату, тому кількість рядків, кількість слів, і лічильник байт є підкладкою і виходу відповідно.

Зауважте, що для цього або потрібні рядки мати вже розширені нові рядки (наприклад, робити Get-Contentтекстовий файл чи щось таке, а потім або конфігурувати, або зберігати його до змінної, потім викликати цей код на цьому вході), або використовувати 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.
  • Збережіть 9 байт завдяки @TonHospel, який показав мені кілька хитрощів торгівлі!

Кілька хитрощів торгівлі: використовуйте y///cяк меншу довжину $_. split$"у скалярному контексті дає кількість слів у $_. Використовуючи пунктуаційну змінну типу $;замість $Wвас, ви можете поставити dвідразу після інтерполяції у рядку формату. Після цього ви можете впасти dв системі $Wі падіння дужки. І -pнічого не закінчиться -n, просто дозвольте printfробити друк (додайте нову
лінійку за

Дивовижно, я ціную це!
Кенні

Ланцюг обчислення, як, $a=foo;$b=bar$aзвичайно, може бути записаний як $b=bar($a=foo), зберігаючи один байт. Тут застосовано до $;та $b. Вам байдуже, чи $;перераховується кожен раз
Тон Євангелія

Спасибі! Я пропустив це через те, що є два блоки ...
Кенні

0

Луа, 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+'(екземпляри одного або декількох символів, що не містять пробілів, якомога більше, тобто слів). Ми можемо використовувати все необхідне для рядка заміни, тому використовуємо порожній рядок ( '') для збереження байтів. Тоді ми просто використовуємо string.lenдля пошуку довжини рядка, тобто кількості байтів. Потім, нарешті, ми це все друкуємо.


Я не бачу жодної лівої прокладки значень рядків і слів, хоча
Тон Євангелія,

0

Сітківка, 65

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

Спробуйте в Інтернеті!

Перший етап - це власне програма для туалету, решта - для підкладки. Справа із 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(відповідно lines) для отримання кількості слів (відповідних рядків), враховуючи, що вони, здається, використовують те саме визначення wc, що й тоді, отримує найдовше значення (як рядок) серед підрахунків і використовує формат printf, приймаючи ширина серед його аргументів для форматування.



0

05AB1E , 24 23 байти

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

j на даний момент помилка, тому міг бути 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)

Ось 29-байтне рішення з прапорами, -rsяке приймає дані від stdin:

[#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 розбиває рядки аргументів на символи
  • switch -r($args|% t*y)оцінити всі відповідні випадки
    • '\s' випадку для будь-якого пробілу
    • '\S' випадку для будь-якого простору
    • '(?s).' чохол для будь-якого символу (включений новий рядок)
    • '\n' випадок для нового рядка char (newline представляє себе)
  • $c="$b".Lengthобчислити довжину байтового числа. $ b - це завжди макс ($ l, $ w, $ b) за проектом
  • "{0,$c} {1,$c} $b"-f$l,+$wномери формату однакової довжини. Змінна $ w перетворюється на int. Це потрібно для рядків без слів. Інші формати змінних "як є", оскільки "Вхід завжди буде містити зворотній новий рядок", і $ l і $ b не можуть бути 0.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.