Переопределить 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, которая принимает многострочную строку и выводит требуемые значения в стандартный вывод. Обратите внимание, что я использую строку формата для построения строки формата (которая требует %%экранирования первого заполнителя формата).

Редактировать: Сохранено 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

Тестирование

У Пита есть несколько очень хороших встроенных модулей. Мы начинаем с создания списка ( [) новых строк в строке ( @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 Хорошо, спасибо за это. Думаешь, ты видел разговор в чате? Кроме того, этот вопрос должен перейти от часто задаваемых вопросов к часто задаваемым .
Муру

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)
Луис Mendo

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 байт

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

Получает ввод через аргументы командной строки.

Переименовываем первый аргумент (arg[1] ) для сохранения байтов. string.gsubвозвращает количество замен, а также измененную строку, поэтому мы используем это для подсчета сначала '\n'(новые строки), затем '%S+'(экземпляры одного или нескольких непробельных символов, как можно больше, то есть слов). Мы можем использовать все, что захотим, для строки замены, поэтому мы используем пустую строку ( '') для сохранения байтов. Затем мы просто используем, string.lenчтобы найти длину строки, то есть количество байтов. Затем, наконец, мы печатаем все это.


Хотя я не вижу левого отступа значений строк и слов
Тон Хоспел

0

Сетчатка, 65

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

Попробуйте онлайн!

Первый этап - это действительная wc-программа, остальная часть предназначена для заполнения. 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' case для символа новой строки (символ новой строки представляет себя)
  • $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.