バイト/文字


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

ヌルバイト

nullバイトを超えて入力を読み続ける唯一の方法が、総バイト数を知ることである場合、任意の手段(バイト入力でも)でバイト数を取得できます。

ご使用の言語がヌルバイトをまったく処理できない場合は、入力にヌルが含まれていないと想定できます。


1
入力が空の場合、0または別のfalsey値を出力できますか?
アレックスA.

2
バイトカウントを分離せずに印刷できますか?可能な最大値は6なので、明確です。
デニス

3
nullバイトをサポートする必要がありますか?これらはいくつかの言語で本当に苦痛になることがあります
デニス

3
それを投稿に追加する必要があります。私はそれが違いを生むかどうかを伝えるのに十分なほど多くの言語を知りませんが、少なくとも2つの答えを無効にしていると思います。
デニス

2
@Adámはい、そうです。たとえば、Cでは、C文字列はNULバイトで終わるため、1つを見つけるとすぐに読み取りを停止します。文字列の長さがわかっている場合は、NULとすべてのバイト数の読み取りを停止します。

回答:


10

Pyth、9 7バイト

2バイトを節約してくれた@Maltysenに感謝します!

mlc.Bd8

テストスイート

入力のすべての文字をバイナリ表現に変換し、これを長さ8のチャンクに分割します。これらのチャンクの数は、その文字のエンコードに必要なバイト数になります。


1
あなたの代わりに分割し、その後、削除の分割と2バイト保存することができ.E pyth.herokuapp.com/...を
Maltysen

@Maltysenそれは賢い、ありがとう!
デンカー

1
同様のトリックに依存する同じ長さの回答:mlhc8.B
FryAmTheEggman

@LeakyNunそれなら、失敗するテストケースを与えるのは簡単でしょう?
-Lause

別のバイトを保存するには、8のチャンクに分割する代わりに、8番目ごとに取得しますml%8.B(現在dは暗黙的です)。
アンデルスカセオルグ16


11

C、68 65バイト

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

3バイトのゴルフをしてくれた@FryAmTheEggmanに感謝します!

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文字のエンコードには、1 0xxxxxxxバイトまたは1 11xxxxxxバイトと1〜5 10xxxxxxバイトのいずれかが含まれます。

入力のすべてのバイトを分割することにより64、我々はオン0xxxxxxx0又は111xxxxxx3、及び10xxxxxx2

商を2と比較すると、12に押します。そして、0のために01、及び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

OK、これは動作するはずで、ほとんどすべてのテストケースで動作しますが、𩸽それ以外は3,3私のマシンで何らかの理由でカウントされます。その文字は、コンピューター上では7バイトと表示されます。@Megoにはその問題がないため、これローカルで実行しているWindowsまたは.NETバージョンの何らかのバグによるものと思われます。(編集:@catはこれがBOMによるものであると指摘しています。その謎を解決してくれてありがとう、@ cat!

ただし、それでもすべての問題を説明できるわけではありません。しかし、私は問題のいくつかがどこから来ているの知っていると思います。.NET内では、すべての文字列はUTF-16コードユニット(System.Char型)で構成されます。PowerShellが使用する非常に緩やかな型キャストでは、バックグラウンドでの型間の暗黙的なキャストと変換が多く行われます。おそらく、これは私たちが見ている振る舞いに寄与する要因です。たとえば、[system.text.encoding]::utf8.getchars([System.Text.UTF8Encoding]::UTF8.GetBytes('𩸽'))単一の文字ではなく、2つの印刷できないものを返します。


説明

非常に簡単なコード。入力を受け取り$args[0]、明示的にchar-arrayとしてキャストし、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

追加して編集これは、最初に投稿した後にチャレンジに追加されたnullバイトの要件を適切に考慮します。ただし、テキストファイルからデータを取得し、次のようにパイプします。

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.はい、これはWindowsでUTF-8を使用して取得できるバイトオーダーマークによるものです。Notepad ++にUTF-8 without BOM(特にUniciesとの互換性のために常にBOMを避けるように)使用すると、BOMが3および4 + 3 = 7
cat

@catああ、はい、それは理にかなっています。OK、ファイルサイズの違いを説明します。ただし、それでも、シェル自体の内部の異なる動作を考慮していません。たとえば、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

@ 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$
エリックアウトゴルファー

@EʀɪᴋᴛʜᴇGᴏʟғᴇʀいいえ、それは異なるものとして解析されるからです。前にスペースを削除できwhileます。
ブラッドギルバートb2gills

NFG対策について説明してもらえますか?
JDługosz

NULバイトをこのプログラムのSTDINにエコーすると、出力されますが、それ\n1\n1\nは意図的なものですか?基本的に、これはNULバイトを処理しますか?

@catなぜそうしないのですか?私はこれを行うと:perl -e 'print "𩸽\0𩸽"' | perl6 -e '...'私が得る4␤1␤4ちょうど私が期待するように。(nulsに関する部分は、私が投稿した後に追加されました)
ブラッドギルバート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は、10進数でで与えられc= 2^(5n+1)ます。これを再配置すると、が得られn = (log2(c)-1)/5ます。したがって、どのコードポイントでも、上記の式を評価して上限を取得することで、バイト数を見つけることができます。

しかしながら、これは、範囲内のコードポイントのために動作しない64 <= c <= 127パディングの欠如ので、1起因して誤った上限が予測され、その1バイト文字手段をコードするASCII状log2用に定義されていないc = 0ヌルバイト場合に発生しています、入力に存在します。したがって、の場合c <= 127、値1 nのが返されます。

これはまさにコードが行っていることです。i文字列内の各文字についてxord関数を使用してコードポイントが検索され、式の上限は、による除算ではなく整数を使用して検索され5、次にを追加し1ます。Pythonのfloat型は常に整数をとして表現するためx.0、整数除算の後でも、結果はint関数に渡されて末尾のゼロが削除されます。の場合ord(i) <= 127、論理的な短絡1は代わりに返されることを意味します。各文字のバイト数はリストの要素として保存され、このリストが返されます。


5

ジャワ10、100の 96 95 67 61バイト

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

コメントで許可されているためスペースを削除する-4バイト
-1バイト をJava 7から-28 バイトに変更UTF-8する-1バイトutf8
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

nullバイトに対して機能しますか?

@cat null-bytesのテストケースは後で追加されました。しかし、はい、それはヌルバイトでも動作し、テストケースを追加しました。
ケビンCruijssen

3

ジュリア、34バイト

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

これは、文字列を受け入れて整数配列を返す匿名関数です。呼び出すには、変数に割り当てます。

アプローチは非常に簡単です。入力が空の場合、出力は空です。それ以外の場合はsizeof、文字列のバイト数をカウントする関数を各1文字の部分文字列にマッピングします。

オンラインでお試しください!(すべてのテストケースを含む)


s->[sizeof("$c")for c=s]数バイト節約します。
デニス

奇数; split("","")戻りません[]か?(JavaScript "".split("")はそうです。)
ニール

@Neilがsplit("","")与える表示されます""(例外を与えるPythonでとは違って)が、私はの互換性については何も知らない[]""ジュリアでは。

@Neilいいえ、split("", "") == [""]つまり、空の文字列を含む1要素配列ですが、問題はsizeof("") == 0、OPが許可していないことです。
アレックスA.

@Dennisインデックス化できない文字列では失敗します。(しかし、手違いの例を考えることはできません。)
アレックス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?:'';

いい答えだ!私はあなたが完全に開始タグをドロップすることができると思う、またはそれを変更する<?=

タグがないと、プログラムではなくコードスニペットであり、たとえ許可されていても、漠然と汚い気分になります。代替タグを使用すると、解析エラーが発生します(少なくとも、私が慣れているphp 5.5で実行しました)。
user55641

大丈夫:)私は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で「偽」と言う唯一の方法です)。Emacsには標準のフラット化機能はありませんが(ダッシュを使用できます-flatten)、可能な実装はそれを排除します。
主ゆうま

3

JavaScript(ノード)、27バイト

s=>s.map(Buffer.byteLength)

これは、個々の文字の配列として入力を受け取り、バイトカウントの配列を返します。

Buffer生のバイナリデータを表現する方法です。Buffer.byteLength(string)は、文字列のバイト数を示します。UTF-8がデフォルトのエンコードです。ブラウザーJSではなく、Node.jsのみにバッファーがあることに注意してください。大まかなブラウザの同等物はBlobと呼ばれ、31バイトで来ます:

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

テスト

このファイルを保存してノードで実行するか、オンラインで試してください

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入力文字列、1行につき2文字を折りたたみ、最初の文字のみを切り取ります

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

2
c
b
e
8
a
f
a
b
b

(各入力バイトの4つの高位ビット、16進文字として、行ごとに1つ)

「継続バイト」0x80..0xBFを削除

tr -d '89ab'

2
c

e


f

(残っているのは、各Unicode文字の最初のバイトの4ビットです)

最初のビットを文字の長さにマップし、出力を折りたたみ、印刷します

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かもしれないことも、Aもう少し詳しく説明する価値があります。
トリプリー


2

C#、89 82バイト

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

文字列を反復処理し、スペースで区切られたリストを返す単純なC#ラムダ。

編集:いくつかの非常に素晴らしいコメントのおかげで6バイトを節約しました。


あなたができることはかなり確かですvar J="";...

あなたは、スペース区切りので、出力をする必要がないことをコメントでも、OP状態11211 2 1 2両方OKです

1
@catありがとう、6バイト節約しました
AstroDan

また、次の場所に余分なスペースがあります} return J;};
cat

必要なように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の文字列の終わり(、実際)はヌルバイトでマークされます。nullバイトと実際の文字列の終わりを区別することは不可能です。
デニス

@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

SWIFT 2.2 67の 52 50バイト

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

ひどくい。私は、文字による文字列を反復処理変換する必要があるので、スウィフトの文字のUTF-8長さを取得する方法は、ありませんCharacterString、そして見つけるcountその単一文字のをString必要があり(少なくとも、組み込みのそれを行う方法)。おそらくスキャナーを使用して、最適化を探しています。

リビジョン1:を使用して15バイトを保存 count代わりにunderestimateCount()

リビジョン2:for eachクロージャーの代わりにfor-inループを使用して、別の2文字を保存しました。


1

さび、53バイト

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

Rustにはutf-8 charプリミティブ、反復子、およびラムダが含まれているため、これは簡単でした。テストコード:

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

うまくいけば競争します。この質問の9か月前utf8bytelength追加されましたが、リリースバージョンにはまだ含まれていません。

サンプル実行:

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バイト長の2文字に分割されます。他のすべてのテストケースは正常に動作します。

編集:一般的な名前空間のインポートは暗黙的ではないことがわかりました。さらに12文字上げます。


1) Timmy D's powershell answer has the same 6-bytes-per-kanji problem. I would attribute it to Windows being dumb and useless at Unicode. 2) If you get 6 bytes for the kanji when reading from a file enocded with UTF-8 without BOM then this is wrong and should be fixed. 3) Seems like F# needs statements like let f(x)= ... to end in ;;, like SML. 4) You can leave off assigning this anonymous function a name, i.e. (s)=seq{for c in s->Encoding.UTF8.GetByteCount([|c|])}.
cat

Also, I get error FS0039: The namespace or module 'Encoding' is not defined when trying to run this. What am I doing wrong?
cat

Also, welcome to Programming Puzzles and Code Golf, this is a nice first answer! :D
cat

@cat You need to open the System.Text namespace. I'm assuming namespace opens and entry code are included, coming from AstroDan's C# answer.
sealed interface

You need to count the bytes of any import, #include, open, load, require, using, USING: etc here on PPCG. AstroDan's C# answer is similarly erroneous, and I notified them of that.
cat

1

05AB1E, 15 bytes

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

Try it online.
Header ε is used to for-each over all the test cases;
Footer ï]J]» to pretty-print the output character-lists (ï: decimals and characters to integers; ]: close if-else and for-each; J: Join digits together; }: close header foreach; »: Join by new-lines).

Explanation:

Ç                   # 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

Since 05AB1E doesn't have any builtins to convert characters to amount of bytes used, I use Ç to convert the characters to their unicode values, and in a for-each do the following in pseudo-code:

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

Inspired by @TheBikingViking's Python 3 answer.


0

Zsh, 41 bytes

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

Try it online!

Zsh is UTF-8 aware, so we split the string on characters, then disable multibyte and print each character's length.

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.