字节/字符


28

任务

给定UTF-8字符串(无论如何)答案(无论如何)等效列表,其中每个元素都是用于编码相应输入字符的字节数。

例子

!1

Ciao1 1 1 1

tʃaʊ1 2 1 2

Adám1 1 2 1

ĉaŭ2 1 2(单个字符)

ĉaŭ1 2 1 1 2(使用组合叠加层)

チャオ3 3 3

(空输入)→ (空输出)

!±≡𩸽1 2 3 4

(空字节)→ 1

空字节

如果唯一读取超出空字节的输入的唯一方法是知道总字节数,则可以通过任何方式(甚至用户输入)获取字节数。

如果您的语言根本无法处理空字节,则可以假定输入不包含空字节。


1
如果输入为空,我们可以输出0或另一个假值吗?
Alex A.

2
我可以不分开地打印字节数吗?可能的最大值是6,所以它是明确的。
丹尼斯

3
我们必须支持空字节吗?在某些语言中,这可能是真正的痛苦……
Dennis

3
您应该将其添加到帖子中。我对大多数语言都不了解,不足以判断它是否有所作为,但我认为它至少会使两个答案无效。
丹尼斯

2
@Adám是的。例如,在C语言中,C字符串以NUL字节结尾,因此一旦找到一个,就停止读取。如果知道字符串的长度,则停止读取那么多字节,NUL和所有字节。

Answers:


10

Pyth,9个 7字节

感谢@Maltysen节省了2个字节!

mlc.Bd8

测试套件

将输入的每个字符转换为二进制表示形式,然后将其拆分为长度为8的块。这些块的数量即为对该字符进行编码所需的字节数。


1
您可以通过拆分而不是拆分再删除.E pyth.herokuapp.com/
Maltysen

@Maltysen这很聪明,谢谢!
Denker

1
相同长度的答案依赖于类似的技巧:mlhc8.B
FryAmTheEggman

@LeakyNun然后给出一个失败的测试用例很简单,不是吗?
Lause

要保存另一个字节,而不是分成8个字节,每8个执行一次:(ml%8.B现在d是隐式的)。
Anders Kaseorg '16


11

C,68 65字节

b;main(c){for(;~c;b=c/64^2?b?putchar(b+48)/48:1:b+1)c=getchar();}

感谢@FryAmTheEggman打高尔夫球3个字节!

Ideone上进行测试


11

APL,15个字符

≢¨'UTF-8'∘⎕ucs¨

用英语:将每个字符转换为UTF-8(意思是:字节表示的向量)并得到其提示。


保存一个字节:≢¨'UTF-8'∘⎕ucs¨
亚当

确实@Adám...干杯。
lstefano

一个有趣的(但更长)阵列为基础的方法:+⌿0 7 11 16∘.≤2⍟⎕UCS
亚当

16.0版:0 7 11 16⍸2⍟⎕UCS
亚当

7

GolfScript,16个字节

{64/2=}%1,/{,)}*

在线尝试!

背景

GolfScript不知道Unicode是什么。所有字符串(输入,输出,内部)均由字节组成。尽管这可能很烦人,但对于此挑战而言却是完美的选择。

UTF-8对ASCII和非ASCII字符的编码方式不同:

  • 所有低于128的代码点均编码为0xxxxxxx

  • 所有其他代码点均编码为11xxxxxx 10xxxxxx ... 10xxxxxx

这意味着每个Unicode字符的编码包含一个0xxxxxxx字节或一个11xxxxxx字节以及1到5 10xxxxxx个字节。

通过将输入的所有字节由64,我们把0xxxxxxx0111xxxxxx3,和10xxxxxx2

如果我们将商与2进行比较-将1推为2 ; 和001,和3 -每个字符将被变成0,接着被1至5 1的。

剩下的就是在出现0时拆分所得的字符串,计算这些零之间的1的数量,然后将数量加1。

怎么运行的

{     }%          Map the following over all bytes in the input.
 64/                Divide the byte by 64.
    2=              Compare the quotient with 2, pushing 1 or 0.
        1,        Push range(1), i.e., [0].
          /       Split the array of Booleans around zeroes.
           {  }*  Fold; for each run of ones but the first:
            ,       Push its length.
             )      Increment.

6

PowerShell v4,58个字节

[char[]]$args[0]|%{[Text.Encoding]::UTF8.GetByteCount($_)}

NB

好的,这应该可以工作,并且在几乎所有测试用例中都可以使用𩸽,除了以某种方式计入3,3我的机器上。该字符甚至在我的计算机上显示为7个字节。我怀疑这是由于我在本地运行的Windows或.NET版本中的某种错误,因为@Mego 没有该问题。(编辑:@cat指出这是由于BOM造成的。感谢您解决这个谜团,@cat!

但是,这仍然不能解决所有问题。我想我知道一些问题是从哪里来的。在.NET内部,所有字符串都由UTF-16代码单元(这是System.Char类型)组成。通过PowerShell使用的非常宽松的类型转换,后台类型之间有很多隐式转换和转换。这很可能是导致我们看到的行为的一个因素-例如,[system.text.encoding]::utf8.getchars([System.Text.UTF8Encoding]::UTF8.GetBytes('𩸽'))返回两个不可打印的字符,而不是单个字符。


说明

非常简单的代码。接受输入$args[0]并将其显式转换为char数组,以便我们可以遍历string的每个组成部分|%{...}。每次迭代,我们使用.NET调用[System.Text.Encoding]::UTF8.GetByteCount()System.暗含)来获取当前字符的字节数$_。将其放置在管道上以供以后输出。由于[int]返回的是的集合,因此强制转换为数组是隐式的。

测试运行

PS C:\Tools\Scripts\golfing> .\bytes-per-character.ps1 'tʃaʊ'
1
2
1
2

PS C:\Tools\Scripts\golfing> .\bytes-per-character.ps1 'Adám'
1
1
2
1

PS C:\Tools\Scripts\golfing> .\bytes-per-character.ps1 'ĉaŭ'
2
1
2

PS C:\Tools\Scripts\golfing> .\bytes-per-character.ps1 'ĉaŭ'
1
2
1
1
2

PS C:\Tools\Scripts\golfing> .\bytes-per-character.ps1 'チャオ'
3
3
3

PS C:\Tools\Scripts\golfing> .\bytes-per-character.ps1 '!±≡𩸽'
1
2
3
3
3

编辑为添加如果您从文本文件中提取数据并将其按以下方式进行管道传输,这可以正确说明我最初发布后添加到挑战中的空字节要求:

PS C:\Tools\Scripts\golfing> gc .\z.txt -Encoding UTF8|%{.\bytes-per-character.ps1 $_}
2
1
1
1

z.txt


That character even shows as 7 bytes on my computer.是的,这是因为字节顺序标记是使用UTF-8在Windows上获得的。告诉记事本++来使用UTF-8 without BOM(你应该总是避免BOM,尤其是对于Unicies兼容性),你会发现文件的大小为4个字节,因为BOM是3和4 + 3 = 7

@cat啊,是的,这很有道理。好的,这样可以解决文件大小的差异。但是,这仍然不能解释外壳本身内部的不同行为。例如,将其保存为没有BOM的UTF-8,并且运行get-content -Encoding UTF8 .\z.txt|%{.\bytes-per-character.ps1 $_}仍会返回3,3
AdmBorkBork



6

JavaScript(ES6),54 45 43字节

s=>[...s].map(c=>encodeURI(c).length/3-8&7)

编辑:在@ l4m2的帮助下保存了2个字节。


s=>[...s].map(c=>encodeURI(c).length/3-4&3)
l4m2 '18年

@ l4m2对于非BMP字符,此操作失败,但我能够对其进行修复。
尼尔,


5

Perl 6的 77个69  63字节

put +$0 if $_».base(2).fmt("%8d")~~/^(1)**2..*|^(" ")/ while $_=$*IN.read: 1
put +$0 if $_».fmt("%8b")~~/^(1)**2..*|^(" ")/ while $_=$*IN.read: 1

put 1+$0 if $_».fmt("%8b")~~/^1(1)+|^" "/while $_=$*IN.read: 1
put 1+$0 if $_».fmt("%0.8b")~~/^1(1)+|^0/while $_=$*IN.read: 1

由于Perl 6使用NFG字符串,因此我必须直接提取字节,这回避了该功能。
(NFG类似于NFC,但它还会创建合成的组合代码点)

输出以换行符分隔。

测试:

for text in '!' 'Ciao' 'tʃaʊ' 'Adám' 'ĉaŭ' 'ĉaŭ' 'チャオ' '' '!±≡𩸽' '𩸽\0𩸽';
do
  echo -en $text |
  perl6 -e 'put 1+$0 if $_».fmt("%8b")~~/^1(1)+|^" "/while $_=$*IN.read: 1' |

  # combine all of the lines into a single one for display purposes
  env text=$text perl6 -e 'put qq["%*ENV<text>"], "\t\t", lines.gist'
done
"!"     (1)
"tʃaʊ"      (1 2 1 2)
"Adám"      (1 1 2 1)
"ĉaŭ"       (2 1 2)
"ĉaŭ"     (1 2 1 1 2)
"チャオ"       (3 3 3)
""      ()
"!±≡𩸽"     (1 2 3 4)
"𩸽\0𩸽"        (4 1 4)

说明:

# turns the list in 「$0」 into a count, and adds one
# 「put」 prints that with a trailing newline
put 1+$0 

   # if the following is true
   if

       # format the input byte to base 2 and pad it out to 8 characters
       $_».fmt("%8b")

       ~~ # smart match against

       # check to see if it starts with more than one 1s, or a space
       # ( also sets 「$0」 to a list that is 1 shorter
       # than the number of bytes in this codepoint )
       / ^1 (1)+ | ^" " /

           # for every byte in STDIN
           while
               $_ = $*IN.read: 1

之所以可行,是因为多字节代码点中的第一个字节具有在其内部编码的字节数,而代码点中的其他字节具有最高的位集,但没有第二高位。虽然单字节代码点没有设置最高位。


不能read:1和/或/while$相反?如果可行,if$
暴民埃里克(Erik the Outgolfer)

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀ不,因为这将被解析为不同的东西。我可以先删除空间while
布拉德·吉尔伯特b2gills

您能解释一下NFG的对策吗?
JDługosz

如果我将NUL字节回显到该程序的STDIN,则输出\n1\n1\n,这是故意的吗?基本上,这可以处理NUL个字节吗?

@cat为什么不呢?当我这样做:perl -e 'print "𩸽\0𩸽"' | perl6 -e '...'我得到4␤1␤4就像我期望的那样。(虽然我发布了文章,但还是增加了关于nuls的部分)
Brad Gilbert b2gills

5

Python 3,82个字节

import math
lambda x:[ord(i)<128and 1or int((math.log2(ord(i))-1)//5+1)for i in x]

这比其他Python答案和其他大多数答案要长得多,但是使用的方法涉及我尚未见过的对数。

一个匿名函数,它通过参数将输入作为字符串并返回一个列表。

在Ideone上尝试

怎么运行的

此方法依赖于UTF-8对字符的代码点进行编码的方式。如果代码点小于128,则字符按ASCII编码:

0xxxxxxx

其中x代表代码点的位。但是,对于大于或等于128的代码点,第一个字节将填充与1总字节数相同的s数,随后的字节开始10。然后输入代码点的位,以给出尽可能短的多字节序列,其余的位变为0

No. of bytes  Format
1             0xxxxxxx
2             110xxxxx 10xxxxxx
3             1110xxxx 10xxxxxx 10xxxxxx
4             11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
...           ...

等等。

现在可以注意到,对于每个字节n数,代码点位数的上限由给出(-n+7)+6(n-1) = 5n+1。因此,c每个的上限代码点n均以十进制表示c= 2^(5n+1)。重新排列此给出n = (log2(c)-1)/5。因此,对于任何代码点,可以通过评估上面的表达式然后求出上限来找到字节数。

但是,这不适用于该范围内的代码点64 <= c <= 127,因为1由于对1个字节字符进行类似ASCII的编码而导致缺少填充,这意味着预测了错误的上限,并且log2未定义上限c = 0,如果空字节出现输入中存在。因此,如果c <= 1271则返回n 的值。

这正是代码的作用。对于i字符串中的每个字符,x使用ord函数找到代码点,并通过使用整数而不是浮点除以5然后加来找到表达式的上限1。由于Python的float类型始终将整数表示为x.0,即使在整数除后,结果也会传递给int函数以删除尾随的零。如果为ord(i) <= 127,则表示逻辑短路,1而是返回该逻辑短路。每个字符的字节数作为元素存储在列表中,并返回此列表。


5

Java 10、100 96 95 67 61字节

a->{for(var c:a)System.out.print(c.getBytes("utf8").length);}

-4字节删除空格,因为注释中允许 将其从7-1
字节更改UTF-8utf8
-28字节(从Java 7改为8)(a->{...}而不是void c(char[]i)throws Exception{...}
-3字节(将输入作为字符串数组而不是字符数组),以及
-3字节从Java 8到10(var而不是String

说明:

在线尝试。

a->{                      // Method with String-array parameter and no return-type
  for(var c:a)            //  Loop over the input-array
    System.out.print(     //   Print:
      c.getBytes("utf8")  //    The bytes as array in UTF-8 of the current item,
       .length);}         //    and print the amount of bytes in this array

它对空字节有效吗?

@cat稍后添加了空字节测试用例。但是,是的,它也适用于空字节,并且我已经添加了测试用例。
凯文·克鲁伊森

3

朱莉娅,34个字节

s->s>""?map(sizeof,split(s,"")):[]

这是一个匿名函数,它接受一个字符串并返回一个整数数组。要调用它,请将其分配给变量。

该方法非常简单:如果输入为空,则输出为空。否则,我们sizeof会将对字符串中的字节数进行计数的函数映射到每个一个字符的子字符串。

在线尝试!(包括所有测试用例)


s->[sizeof("$c")for c=s]保存一些字节。
丹尼斯

奇; 不split("","")返回[]?(JavaScript "".split("")确实如此。)
Neil

@Neil split("","")似乎给出了""(不同于Python中的给出一个例外),但我对julia []和and 的兼容性一无所知""

@Neil不,split("", "") == [""]即一个包含空字符串的单元素数组,但是问题是操作员sizeof("") == 0说的那是不允许的。
Alex A.

@Dennis对于不可索引的字符串,它将失败。(不过,无法想到一个例子。)
Alex A.

3

PHP,92 57字节

再次考虑,您可以以更少的麻烦来做到这一点:

<?php for(;$a=strlen(mb_substr($argv[1],$i++,1));)echo$a;

在线尝试,请注意,由于它使用stdin而不是程序参数,因此会稍长一些。
此版本要求您忽略发送到stderr的通知,但这很好

旧版本:
对另一个php答案使用一种完全不同的方法。依赖缺乏对php中多字节字符串的本机支持。

<?php for($l=strlen($a=$argv[1]);$a=mb_substr($a,1);$l=$v)echo$l-($v=strlen($a));echo$l?:'';

好答案!我认为您可以完全删除开始标签,也可以将其更改为<?=
cat

没有标签,它是代码段,而不是程序,即使允许,它也让我感到模糊。使用alternate标签,您将得到一个解析错误(或者至少我在PHP 5.5上确实这样做了)。
user55641 2013年

好了:)我不知道PHP(我也不想要,咳嗽),但我会在这里点你:codegolf.stackexchange.com/questions/2913

3

Emacs Lisp,55个 49字节

(lambda(s)(mapcar'string-bytes(mapcar'string s)))

首先使用将该字符串分解为一个字符列表(mapcar 'string s)stringEmacs Lisp中的函数获取一个字符列表并从中构建一个字符串。由于Emacs分割字符串的方式mapcar(即,分成整数列表,而不是字符或字符串列表),因此需要这种显式转换。然后将string-bytes函数映射到该字符串列表。

例:

(mapcar 'string "abc") ; => ("a" "b" "c")
(mapcar 'string-bytes '("a" "b" "c")) ; => (1 1 1) 

测试用例:

(mapcar
 (lambda(s)(mapcar'string-bytes(mapcar'string s)))
 '("!""Ciao""tʃaʊ""Adám""ĉaŭ""ĉaŭ""チャオ""""!±≡𩸽""\0"))
;; ((1) (1 1 1 1) (1 2 1 2) (1 1 2 1) (2 1 2) (1 2 1 1 2) (3 3 3) nil (1 2 3 4) (1))

旧答案:

(lambda(s)(mapcar(lambda(s)(string-bytes(string s)))s))

取消高尔夫:

 (lambda (s)
   (mapcar
    ;; we can't use string-bytes directly,
    ;; since Emacs mapcar yields a list of ints instead of characters
    ;; therefore we need a wrapper function here. 
    (lambda (s)
      (string-bytes (string s)))
    s))

测试用例:

(mapcar
 (lambda(s)(mapcar(lambda(s)(string-bytes(string s)))s))
 '("!""Ciao""tʃaʊ""Adám""ĉaŭ""ĉaŭ""チャオ""""!±≡𩸽""\0"))
;; ((1) (1 1 1 1) (1 2 1 2) (1 1 2 1) (2 1 2) (1 2 1 1 2) (3 3 3) nil (1 2 3 4) (1))


nil如果将结果展平,会发生什么?
亚当

1
@Adám nil是一个空列表(也是Emacs中唯一表示“ false”的方式)。尽管Emacs中没有标准的拼合(您可以使用破折号-flatten),但任何可能的实现都可以消除它。
尤玛勋爵

3

JavaScript(节点),27个字节

s=>s.map(Buffer.byteLength)

这将输入作为单个字符的数组,并返回字节计数的数组。

Buffer是表示原始二进制数据的一种方法。Buffer.byteLength(string)给出字符串中的字节数。UTF-8是默认编码。请注意,只有Node.js具有缓冲区,而浏览器JS没有。大致的浏览器等效项称为Blob,大小为31个字节:

s=>s.map(e=>new Blob([e]).size)

测试

保存此文件并通过node运行它,或在线尝试

var f =
  s=>s.map(Buffer.byteLength)

var tests = [
  ["!"],
  ["C","i","a","o"],
  ["t","ʃ","a","ʊ"],
  ["A","d","á","m"],
  ["ĉ","a","ŭ"],
  ["c","̂","a","u","̆"],
  ["チ","ャ","オ"],
  [],
  ["!","±","≡","𩸽"]
];

tests.forEach(test => {
  console.log(test, f(test));
});

结果应该是:

$ node bytes.js
[ '!' ] [ 1 ]
[ 'C', 'i', 'a', 'o' ] [ 1, 1, 1, 1 ]
[ 't', 'ʃ', 'a', 'ʊ' ] [ 1, 2, 1, 2 ]
[ 'A', 'd', 'á', 'm' ] [ 1, 1, 2, 1 ]
[ 'ĉ', 'a', 'ŭ' ] [ 2, 1, 2 ]
[ 'c', '̂', 'a', 'u', '̆' ] [ 1, 2, 1, 1, 2 ]
[ 'チ', 'ャ', 'オ' ] [ 3, 3, 3 ]
[] []
[ '!', '±', '≡', '�' ] [ 1, 2, 3, 4 ]

3

Bash,74个字节

打高尔夫球

xxd -p|fold -2|cut -c1|tr -d '89ab'|echo `tr -t '01234567cbef' '[1*]2234'`

算法

hexdump输入字符串,每行折叠2个字符,仅剪切第一个字符

echo -ne '!±≡𩸽' | xxd -p|fold -2|cut -c1

2
c
b
e
8
a
f
a
b
b

(每个输入字节的4个高位为一个十六进制字符,每行一个)

删除“继续字节” 0x80..0xBF

tr -d '89ab'

2
c

e


f

(剩下的是每个unicode字符的第一个字节的4位)

将前几位映射到char长度,折叠输出并打印

echo `tr -t '01234567cbef' '[1*]2234'`

1 2 3 4

测试

 U() { xxd -p|fold -2|cut -c1|tr -d '89ab'|echo `tr -t '01234567cbef' '[1*]2234'`;}

 echo -ne '!' | U 
 1

 echo -ne 'Ciao' | U
 1 1 1 1

 echo -ne 'tʃaʊ' | U
 1 2 1 2

 echo -ne 'Adám' | U
 1 1 2 1

 echo -ne 'ĉaŭ' | U
 2 1 2

 echo -ne 'ĉaŭ' | U
 1 2 1 1 2

 echo -ne 'チャオ' | U
 3 3 3
 echo -ne '!±≡𩸽' | U
 1 2 3 4

 echo -ne "\x0" | U
 1

 echo -ne '' | U

+1不错的方法。您实际上是直接从输入中读取结果。
亚当

我不熟悉的-t选项tr,并且显然是GNU扩展。配管的命令替换后,echo也可能是值得稍微更详细的解释。
人间


2

C#,89 82个字节

I=>{var J="";foreach(char c in I){J+=Encoding.UTF8.GetByteCount(c+"");}return J;};

一个简单的C#lambda,它遍历字符串并返回以空格分隔的列表。

编辑:由于一些非常好的注释,节省了6个字节。


非常确定您可以做var J="";...
2013年

此外,在评论,你不需要到OP状态输出,使空间分隔11211 2 1 2都OK

1
@cat谢谢,为我节省了6个字节
AstroDan

此外,您还有其他空间} return J;};

似乎您需要using System.Text或大约-进口不是免费的。

2

Haskell,85个字节

import Data.ByteString as B
import Data.ByteString.UTF8
(B.length.fromString.pure<$>)

有点晚了,但是时间会更短些map$...
H.PWiz


1

C,85个字节。

l(unsigned char* c){while(*c){int d=(*c>>4)-11;
d=d<0?1:d+(d==1);putchar(48+d);c+=d;}}

检查每个字节的高4位,以确定编码和要跳过的后续字节数;


这对空字节有效吗?

是的,while *c 在一个空字符串上退出,并且“ c + = d”跳过多字节代码点中间的空值。
AShelly

1
不对 char*C 中的字符串(,实际上)的末尾标有一个空字节。不可能将空字节与字符串的实际结尾区分开。
丹尼斯

@Dennis恰恰是因为没有区别 :)

1
该OP的评论说(和它现在是在后),您可以以字节为单位请求字符串的长度作为参数,这样做,这将再次有效

1

因子57 87 82 80字节

[ [ dup zero? [ drop "1"] [ >bin length 4 /i 10 >base ] if ] { } map-as ""join ]

解释:

USING: kernel math math.parser sequences ;
IN: byte-counts

: string>byte-counts ( str -- counts )
  [                  ! new quotation: takes a char as a fixnum
    dup zero?        ! true if this is a NUL byte
    [ drop "1" ]     ! NUL bytes have length 1
    [ >bin           ! else, convert to binary string
      length         ! length of binary string
      4              ! the constant 4
      /i             ! integer division
      number>string  ! 4 -> "4"
    ] if             ! conditionally execute one of the previous quotations
  ]                  ! end
  { } map-as         ! map and clone-like an { } array
  "" join ;          ! join array of 1strings on empty string

单元测试:

USING: tools.test byte-counts ;
IN: byte-counts.tests

{ "1" } [ "!" string>byte-counts ] unit-test
{ "1111" } [ "Ciao" string>byte-counts ] unit-test
{ "1212"} [ "tʃaʊ" string>byte-counts ] unit-test
{ "1121" } [ "Adám" string>byte-counts ] unit-test
{ "212" } [ "ĉaŭ" string>byte-counts ] unit-test
{ "12112" } [ "ĉaŭ" string>byte-counts ] unit-test
{ "333" } [ "チャオ" string>byte-counts ] unit-test
{ "" } [ "" string>byte-counts ] unit-test
{ "1234" } [ "!±≡𩸽" string>byte-counts ] unit-test
{ "1" } [ "\0" string>byte-counts ] unit-test

他们都过去了。C:


1

迅速2.2,67个 52 50字节

for c in i.characters{print(String(c).utf8.count)}

可怕的丑陋。在Swift中无法获取字符的UTF-8长度,因此我需要逐字符遍历字符串,将转换CharacterString,然后找到该count单个字符的String(嘿,至少有一个内置方法)。寻找优化,可能使用扫描仪。

修订版1:使用count代替节省了15个字节underestimateCount()

修订2:通过使用for-in循环而不是每个闭包都保存了另外2个字符。


1

Rust,53个字节

|s:&str|for c in s.chars(){print!("{}",c.len_utf8())}

Rust具有utf-8 char基元,迭代器和lambda,因此这很简单。测试代码:

fn main() {
    let s = "Löwe 老虎 Léopard💖💖💖💖";
    let f =|s:&str|for c in s.chars(){print!("{}",c.len_utf8())};
    f(s);
}

产出

1211133112111114444 

1

jq,26个字符

(23个字符的代码+ 3个字符的命令行选项)

(./"")[]|utf8bytelength

希望竞争。尽管utf8bytelength此问题之前9 ++个月添加的,但仍未包含在发行版本中。

样品运行:

bash-4.3$ ./jq -R '(./"")[]|utf8bytelength' <<< 'tʃaʊ'
1
2
1
2

bash-4.3$ ./jq -R '(./"")[]|utf8bytelength' <<< 'ĉaŭ '
1
2
1
1
2
1

bash-4.3$ ./jq -R '(./"")[]|utf8bytelength' <<< 'チャオ'
3
3
3

bash-4.3$ ./jq -R '(./"")[]|utf8bytelength' <<< ''

bash-4.3$ ./jq -R '(./"")[]|utf8bytelength' <<< '!±≡𩸽'
1
2
3
4


1

SmileBASIC,69个字节

DEF C B
WHILE I<LEN(B)Q=INSTR(BIN$(B[I],8),"0")I=I+Q+!Q?Q+!Q
WEND
END

输入是一个字节数组。

UTF-8字符1中的字节数等于第一个字节中的前导位数(除非没有1s,在这种情况下该字符为1字节)。要找到前导1的数量,程序会0在二进制表示形式中找到第一个,如果为0,则加1。

0xxxxxxx - no leading ones, 1 byte
110xxxxx 10xxxxxx - 2 leading ones, 2 bytes
1110xxxx 10xxxxxx 10xxxxxx - 3 leading ones, 3 bytes
etc.

1

F#,59 54 66字节

(s)=seq{for c in s->System.Text.Encoding.UTF8.GetByteCount([|c|])}

从技术上讲,s是一个char序列,但事实证明存在一个隐式转换,该转换允许传递字符串。

在控制台中使用进行测试时!±≡𩸽,它将汉字分为两个字符,每个字符长3个字节。所有其他测试用例都可以正常工作。

编辑:原来常见的名称空间导入不是隐式的。再增加12个字符。


1)Timmy D的powershell答案具有相同的每个汉字6字节的问题。我将其归因于Windows在Unicode上愚蠢无用。2)如果从包含的文件中读取汉字时获得了6个字节,UTF-8 without BOM那么这是错误的,应该修复。3)好像F#需要像SML这样的语句需要let f(x)= ...以结尾结尾;;。4)您可以不用为该匿名函数分配名称,即(s)=seq{for c in s->Encoding.UTF8.GetByteCount([|c|])}

另外,我error FS0039: The namespace or module 'Encoding' is not defined在尝试运行此程序时会得到提示。我究竟做错了什么?

另外,欢迎来到“编程难题”和“代码高尔夫球”,这是一个不错的第一答案!:D

@cat您需要打开System.Text名称空间。我假设来自AstroDan的C#答案中打开了名称空间并包含了进入代码。
密封接口

你需要计算的任何字节import#includeopenloadrequireusingUSING:等在这里PPCG。AstroDan的C#答案同样是错误的,我已经通知了他们。

1

05AB1E,15 个字节

ÇεDžy‹i1ë.²<5÷>

在线尝试。
标头ε用于对所有测试用例进行逐一介绍;
页脚ï]J]»漂亮地打印输出字符列表(ï:小数点和所有字符为整数;]:关闭if-else和for-eachJ;:将数字连接在一起;}:关闭页眉foreach;:»通过换行连接)。

说明:

Ç                   # Convert each character to its unicode value
 εD                 # Foreach over this list
      i             #  If the current item
     ‹              #  is smaller than
   žy               #  128
       1            #   Use 1
        ë           #  Else
         .²         #   Use log_2
           <        #   minus 1
            5÷      #   integer-divided by 5
              >     #   plus 1

由于05AB1E没有任何内置函数可将字符转换为使用的字节数,因此我Ç将字符转换为unicode值,并在for-each中使用伪代码执行以下操作:

if(unicodeValue < 128)
  return 1
else
  return log_2(unicodeValue-1)//5+1    # (where // is integer-division)

受到@TheBikingViking的Python 3答案的启发。


0

Zsh,41个字节

for c (${(s::)1})set +o multibyte&&<<<$#c

在线尝试!

Zsh支持UTF-8,因此我们将字符串拆分为字符,然后禁用多字节并打印每个字符的长度。

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.