重新实现wc coreutil


27

这种挑战是相似的这个旧的,但与规范的一些不明之处敲定并不太严格的I / O需求。


给定仅由可打印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的旧版本作为此版本的副本,因为这是一个更好的挑战。
Mego 2016年

是否应该支持空输入?
Ton Hospel '16

我认为不是,他说所有输入都以\ n结尾。
CalculatorFeline

Answers:


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。请注意,我使用格式字符串来构建格式字符串(需要使用a %%来转义第一个格式占位符)。

编辑:由于丹尼斯的打印优化,节省了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 %了,节省了2个字节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好,谢谢。猜猜您看到聊天对话了吗?同样,该问题应从提出常见问题解答变为常见问题
muru

1
哦,我没有在聊天中看到你;您的答案刚刚出现在我的收件箱中:PI是向该问题添加[提出建议的]的人,所以也许我会先检查一下机房,然后再将其升级为[常见问题]。
Doorknob

1
设置dlength(c)"d %"应该可以将更printf改为"%"d d"d\n",这样可以节省两个字节。
Doorknob

1
确实@Doorknob,谢谢!猜测这不是保存字节的平凡之举,而是平凡的事情。
muru

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

2
@ JohnEye,github.com
Mego /

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)),使用插值将输入的长度转换为字符串
  • 一个lambda函数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)

做得很好!也许删除“ 在线试用 ” 链接中的“调试”标志?
Luis Mendo

啊,哎呀!感谢您的注意!
大卫

我认为您可以替换!3Z"vX:!Z{Zccellstr后跟strjoin
Luis 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以节省两个字节
Patrick Roberts

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

第一行使用input $a,然后下一部分是一个语句。我们将其设置为$c等于某些字符串的 .length。这将形成我们必要的填充。字符串内部是一个立即代码块$(...),因此在对字符串求值之前将执行代码。

在代码块中,我们通过|sort命令发送三个项目,然后取最大的一个(...)[-1]。这是我们确保将列设置为正确宽度的地方。这三个项目是$l行数,-split换行符,$w字数,-split空格和$b长度。

第二行是使用-f运算符的输出(这是的伪简写String.Format())。这是将扩展变量插入字符串的另一种方法。在这里,我们要说的是希望将所有输​​出填充到左侧,以便每一列都$c宽。填充是通过空格完成的。的012对应于$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

Ruby,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,保存另一个字节。
  • 通过@TonHospel向我展示了一些交易技巧,节省了9个字节!

交易技巧:y///c用作的较短长度$_split$"在标量上下文中给出的字数$_。通过使用像这样的标点符号变量$;$W您可以d在格式字符串中的插值之后放置一个。然后,您可以d放入$W并删除括号。并-p一无所获-n,只是让它printf来做印刷(在味道上添加换行符)
Ton Hospel

太好了,谢谢!
肯尼

像这样的计算链$a=foo;$b=bar$a通常可以写成$b=bar($a=foo),节省一个字节。适用于$;$b。您不在乎是否$;每次都重新计算
Ton Hospel

谢谢!我忽略了这一点,因为有两个街区...
肯尼

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查找字符串的长度,即字节数。然后,最后,我们将其全部打印出来。


我没有看到行和单词的值的任何左填充
Ton Hospel '16

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(resp。lines)来获取单词数(resp。行)wc,然后获取计数中最长的值(以字符串形式)并使用printf格式格式化参数之间的宽度。


0

C,180个 178字节

#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

05AB1E24 23 字节

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

j目前已被窃听,因此如果不使用§J。,可能是21个字节。

在线尝试验证所有测试用例

说明:

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

将多行字符串作为命令行参数。在线尝试!

感谢Dennis的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,123115字节

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 将arument字符串拆分为char
  • switch -r($args|% t*y)评估所有匹配的案例
    • '\s' 任何空格的情况
    • '\S' 任何非空白的情况
    • '(?s).' 任何字符的情况(包括换行符)
    • '\n' 换行符字符的大小写(换行符表示自身)
  • $c="$b".Length计算字节数的长度。$ b根据设计始终为max($ l,$ w,$ b)
  • "{0,$c} {1,$c} $b"-f$l,+$w格式化具有相同长度的数字。变量$ w转换为int。它需要没有单词的字符串。其他变量的格式为“原样”,因为“输入将始终包含尾随换行符”,并且$ l和$ b不能为0。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.