Bytes / Karakter

28

Tugas

Diberikan string UTF-8 (dengan cara apa pun) jawaban (dengan cara apa pun) daftar setara di mana setiap elemen adalah jumlah byte yang digunakan untuk menyandikan karakter input yang sesuai.

Contohnya

!1

Ciao1 1 1 1

tʃaʊ1 2 1 2

Adám1 1 2 1

ĉaŭ2 1 2(karakter tunggal)

ĉaŭ1 2 1 1 2(menggunakan kombinasi overlay)

チャオ3 3 3

(input kosong) → (output kosong)

!±≡𩸽1 2 3 4

(byte nol) → 1

Null byte

Jika satu-satunya cara untuk tetap membaca input di luar byte nol adalah dengan mengetahui jumlah byte total, Anda dapat memperoleh jumlah byte dengan cara apa pun (bahkan input pengguna).

Jika bahasa Anda tidak bisa menangani byte nol sama sekali, Anda dapat menganggap bahwa input tidak mengandung null.

Adm
sumber
1
Jika input kosong, bisakah kita menampilkan 0 atau nilai falsey lain?
Alex A.
2
Bisakah saya mencetak jumlah byte tanpa pemisahan? Nilai tertinggi yang mungkin adalah 6, jadi tidak ambigu.
Dennis
3
Apakah kita harus mendukung byte nol? Itu bisa sangat menyakitkan dalam beberapa bahasa ...
Dennis
3
Anda harus menambahkan itu ke posting. Saya tidak tahu sebagian besar bahasa dengan cukup baik untuk mengetahui apakah itu membuat perbedaan, tapi saya pikir itu membatalkan setidaknya dua jawaban.
Dennis
2
@ Adám ya itu akan. Dalam C, misalnya, string C diakhiri dengan byte NUL, sehingga Anda berhenti membaca segera setelah Anda menemukannya. Jika Anda tahu panjang string, Anda berhenti membaca setelah itu banyak byte, NUL, dan semua.
kucing

Jawaban:

10

Pyth, 9 7 byte

Terima kasih kepada @Maltysen untuk menghemat 2 byte!

mlc.Bd8

Suite uji

Mengkonversi setiap karakter dari input ke representasi binernya dan kemudian membaginya menjadi potongan-potongan dengan panjang 8. Jumlah potongan-potongan tersebut kemudian jumlah byte yang diperlukan untuk menyandikan karakter itu.

Denker
sumber
1
Anda dapat menyimpan 2 byte dengan pemisahan alih-alih membelah dan kemudian menghapus .E pyth.herokuapp.com/...
Maltysen
@Maltysen Itu pintar, terima kasih!
Denker
1
Jawaban panjang yang sama yang mengandalkan trik serupa:mlhc8.B
FryAmTheEggman
@ LeakyNun maka itu akan menjadi hal yang sederhana untuk memberikan test case yang gagal, bukan?
Lause
Untuk menyimpan byte lain, alih-alih membaginya menjadi 8, ambil setiap 8: ml%8.B(sekarang dimplisit).
Anders Kaseorg
21

Python 3, 42 36 byte

lambda x:[len(i.encode())for i in x]
ahli atlasologi
sumber
13
-1 byte: gunakan map. lambda x:map(len,map(str.encode,x))
NoOneIsHere
11

C, 68 65 byte

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

Terima kasih kepada @FryAmTheEggman untuk bermain golf 3 byte!

Uji di Ideone .

Dennis
sumber
11

APL, 15 karakter

≢¨'UTF-8'∘⎕ucs¨

Dalam bahasa Inggris: konversi setiap karakter ke UTF-8 (artinya: vektor representasi byte) dan dapatkan penghitungannya.

lstefano
sumber
Simpan satu byte:≢¨'UTF-8'∘⎕ucs¨
Adám
Memang @ Adám ... Ceria.
lstefano
Pendekatan berbasis array yang menarik (tetapi lebih lama):+⌿0 7 11 16∘.≤2⍟⎕UCS
Adám
Versi 16.0:0 7 11 16⍸2⍟⎕UCS
Adám
7

GolfScript, 16 byte

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

Cobalah online!

Latar Belakang

GolfScript tidak memiliki petunjuk apa itu Unicode; semua string (input, output, internal) terdiri dari byte. Meskipun itu bisa sangat menjengkelkan, itu sempurna untuk tantangan ini.

UTF-8 menyandikan karakter ASCII dan non-ASCII secara berbeda:

  • Semua poin kode di bawah 128 dikodekan sebagai 0xxxxxxx.

  • Semua titik kode lainnya dikodekan sebagai 11xxxxxx 10xxxxxx ... 10xxxxxx.

Ini berarti bahwa pengkodean setiap karakter Unicode berisi 0xxxxxxxbyte tunggal atau 11xxxxxxbyte tunggal dan 1 hingga 5 10xxxxxxbyte.

Dengan membagi semua byte input dengan 64 , kita berubah 0xxxxxxxmenjadi 0 atau 1 , 11xxxxxxmenjadi 3 , dan 10xxxxxxmenjadi 2 .

Jika kita membandingkan hasil bagi dengan 2 - mendorong 1 untuk 2 ; dan 0 untuk 0 , 1 , dan 3 - setiap karakter akan diubah menjadi 0 , diikuti oleh 1 hingga 5 1 's.

Yang tersisa adalah untuk membagi string yang dihasilkan pada kejadian 0 , hitung jumlah 1 di antara nol itu dan tambahkan satu ke jumlah tersebut.

Bagaimana itu bekerja

{     }%          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.
Dennis
sumber
6

PowerShell v4, 58 byte

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

NB

OK, ini seharusnya bekerja, dan bisa dilakukan di hampir semua test case kecuali 𩸽yang entah bagaimana dihitung seperti 3,3pada mesin saya. Karakter itu bahkan menunjukkan 7 byte di komputer saya. Saya menduga ini karena beberapa jenis bug di Windows atau versi .NET yang saya jalankan secara lokal, karena @Mego tidak memiliki masalah itu . ( Sunting: @cat menunjukkan ini karena BOM . Terima kasih telah memecahkan misteri itu, @cat! )

Namun, itu masih belum memperhitungkan semua masalah. Saya rasa saya tahu dari mana beberapa masalah itu berasal. Di dalam .NET, semua string terdiri dari unit kode UTF-16 (yang merupakan tipe System.Char). Dengan typecasting sangat longgar yang menggunakan PowerShell, ada banyak casting dan konversi implisit antara jenis di latar belakang. Kemungkinan ini adalah faktor yang berkontribusi terhadap perilaku yang kita lihat - misalnya, [system.text.encoding]::utf8.getchars([System.Text.UTF8Encoding]::UTF8.GetBytes('𩸽'))mengembalikan dua yang tidak diinginkan, daripada satu karakter.


Penjelasan

Kode yang sangat mudah. Mengambil input $args[0]dan secara eksplisit melemparkannya sebagai char-array sehingga kita dapat mengulang setiap komponen dari string |%{...}. Setiap iterasi, kami menggunakan panggilan .NET [System.Text.Encoding]::UTF8.GetByteCount()( System.tersirat) untuk mendapatkan jumlah byte karakter saat ini $_. Itu ditempatkan pada pipa untuk keluaran nanti. Karena itu adalah kumpulan dari [int]s yang dikembalikan, casting ke array adalah implisit.

Tes Berjalan

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

Diedit untuk menambahkan Ini benar-benar memperhitungkan persyaratan null-byte yang ditambahkan ke tantangan setelah saya awalnya diposting, asalkan Anda menarik data dari file teks dan pipa itu sebagai berikut:

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

z.txt

AdmBorkBork
sumber
That character even shows as 7 bytes on my computer.Ya, itu karena Byte-Order Mark yang merupakan apa yang Anda dapatkan di Windows dengan UTF-8. Beri tahu Notepad ++ untuk digunakan UTF-8 without BOM(karena Anda harus selalu menghindari BOM , terutama untuk kepatuhan dengan Unicies) dan Anda akan menemukan file memiliki ukuran 4 byte, karena BOM adalah 3 dan 4 + 3 = 7
cat
@ kucing Ah, ya, itu masuk akal. OK, sehingga menyumbang perbedaan dalam ukuran file. Namun, itu masih tidak menjelaskan perbedaan perilaku di dalam shell itu sendiri. Misalnya, menyimpannya sebagai UTF-8 tanpa BOM, dan menjalankan get-content -Encoding UTF8 .\z.txt|%{.\bytes-per-character.ps1 $_}masih kembali 3,3.
AdmBorkBork
Namun ternyata itu tetap bekerja dengan baik
AdmBorkBork
6

JavaScript (ES6), 54 45 43 byte

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

Sunting: Disimpan 2 byte dengan bantuan dari @ l4m2.

Neil
sumber
s=>[...s].map(c=>encodeURI(c).length/3-4&3)
l4m2
@ l4m2 Itu gagal untuk karakter non-BMP tapi saya bisa memperbaikinya.
Neil
5

Ruby, 33 byte

Nyaris tidak menggunakan Python, yay! Cobalah online.

->s{s.chars.map{|c|c.bytes.size}}
Nilai Tinta
sumber
5

Perl 6 ,  77 69  63 byte

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

Karena Perl 6 menggunakan string NFG saya harus menarik byte secara langsung, yang menghindari fitur ini.
(NFG seperti NFC kecuali itu juga membuat codepoints sintetis)

Outputnya dipisahkan oleh baris baru.

Uji:

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)

Penjelasan:

# 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

Ini berfungsi karena byte pertama dalam multi-byte codepoint memiliki jumlah byte yang disandikan di dalamnya, dan byte lain dalam codepoint memiliki set bit tertinggi, tetapi bukan yang tertinggi berikutnya. Sementara titik byte tunggal tidak memiliki set bit tertinggi.

Brad Gilbert b2gills
sumber
Tidak bisa melakukan read:1dan / atau /while$sebaliknya? Dan jika itu berhasil , if$?
Erik the Outgolfer
@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Tidak karena itu akan diurai sebagai sesuatu yang berbeda. Saya dapat menghapus ruang sebelumnya while.
Brad Gilbert b2gills
Bisakah Anda menjelaskan tindakan pencegahan NFG?
JDługosz
Jika saya menggemakan byte NUL ke STDIN program ini, ia mencetak \n1\n1\n, apakah itu disengaja? Pada dasarnya, apakah ini menangani byte NUL?
kucing
@ kucing Kenapa tidak? Ketika saya melakukan ini: perl -e 'print "𩸽\0𩸽"' | perl6 -e '...'saya mendapatkan 4␤1␤4seperti yang saya harapkan. (Bagian tentang nuls ditambahkan setelah saya diposting)
Brad Gilbert b2gills
5

Python 3, 82 byte

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

Ini jauh lebih lama daripada jawaban Python yang lain, dan sebagian besar dari jawaban lainnya, tetapi menggunakan pendekatan yang melibatkan logaritma yang belum saya lihat.

Fungsi anonim yang mengambil input, melalui argumen, sebagai string dan mengembalikan daftar.

Cobalah di Ideone

Bagaimana itu bekerja

Metode ini bergantung pada cara UTF-8 mengkodekan titik kode karakter. Jika titik kode kurang dari 128, karakter dikodekan seperti pada ASCII:

0xxxxxxx

di mana xmewakili bit dari titik kode. Namun, untuk kode-poin lebih besar dari atau sama dengan 128, byte pertama diisi dengan jumlah 1s yang sama dengan jumlah total byte, dan byte berikutnya dimulai 10. Bit-bit dari titik kode kemudian dimasukkan untuk memberikan urutan multibyte sesingkat mungkin, dan bit yang tersisa menjadi 0.

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

Dan seterusnya.

Sekarang dapat diperhatikan bahwa untuk setiap jumlah byte n, batas atas untuk jumlah bit kode-titik diberikan oleh (-n+7)+6(n-1) = 5n+1. Oleh karena itu, titik kode batas atas cuntuk masing-masing ndiberikan, dalam desimal, oleh c= 2^(5n+1). Menyusun ulang ini memberin = (log2(c)-1)/5 . Jadi untuk titik kode apa pun, jumlah byte dapat ditemukan dengan mengevaluasi ekspresi di atas, dan kemudian mengambil plafon.

Namun, ini tidak berfungsi untuk titik kode dalam rentang 64 <= c <= 127, karena kurangnya padding 1karena pengkodean seperti ASCII untuk 1 byte karakter berarti bahwa batas atas yang salah diprediksi, dan log2tidak ditentukan untuk c = 0, yang terjadi jika byte nol hadir dalam input. Karena itu, jika c <= 127, nilai1 dikembalikan untuk n.

Inilah yang dilakukan oleh kode; untuk setiap karakter idalam string x, titik-kode ditemukan menggunakan ordfungsi, dan langit-langit ekspresi ditemukan dengan menggunakan integer daripada pembagian float dengan 5dan kemudian menambahkan 1. Karena tipe float Python selalu mewakili bilangan bulat sebagai x.0, bahkan setelah pembagian bilangan bulat, hasilnya dilewatkan ke intfungsi untuk menghapus trailing nol. Jika ord(i) <= 127, hubung-pendek logis berarti yang 1dikembalikan. Jumlah byte untuk setiap karakter disimpan sebagai elemen dalam daftar, dan daftar ini dikembalikan.

TheBikingViking
sumber
5

Java 10, 100 96 95 67 61 byte

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

-4 byte menghapus spasi karena ini diperbolehkan dalam komentar
-1 byte berubah UTF-8menjadi utf8
-28 byte pergi dari Java 7 ke 8 ( a->{...}bukan void c(char[]i)throws Exception{...})
-3 byte mengambil input sebagai String-array bukan karakter-array, dan
-3 byte pergi dari Java 8 ke 10 ( varbukan String)

Penjelasan:

Cobalah online.

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
Kevin Cruijssen
sumber
Apakah itu berfungsi untuk byte nol?
kucing
@ kucing Uji kasus untuk null-byte kemudian ditambahkan. Tapi ya, itu juga berfungsi untuk null-byte dan saya telah menambahkan test case.
Kevin Cruijssen
3

Julia, 34 byte

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

Ini adalah fungsi anonim yang menerima string dan mengembalikan array integer. Untuk menyebutnya, tetapkan ke variabel.

Pendekatannya cukup mudah: Jika input kosong, output kosong. Kalau tidak, kita memetakan sizeoffungsi, yang menghitung jumlah byte dalam string, untuk setiap substring satu karakter.

Cobalah online! (termasuk semua kasus uji)

Alex A.
sumber
s->[sizeof("$c")for c=s]menghemat beberapa byte.
Dennis
Aneh; tidak split("","")tidak kembali []? (JavaScript "".split("")tidak.)
Neil
@ Neil split("","")tampaknya memberi ""(tidak seperti dalam Python yang memberikan pengecualian) tapi saya tidak tahu apa-apa tentang kompatibilitas []dan ""di julia.
kucing
@Neil No,, split("", "") == [""]yaitu array satu elemen yang berisi string kosong, tetapi masalahnya adalah itu sizeof("") == 0, yang menurut OP tidak diizinkan.
Alex A.
@ Dennis Itu akan gagal untuk string yang tidak dapat diindeks. (Tidak bisa memikirkan contoh begitu saja.)
Alex A.
3

PHP, 92 57 byte

Setelah dipikir-pikir, Anda bisa melakukan ini dengan lebih mudah:

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

Coba online, catat bahwa ini sedikit lebih lama karena menggunakan stdin daripada argumen program.
Versi ini mengharuskan Anda untuk mengabaikan pemberitahuan yang dikirim ke stderr tapi itu tidak masalah .

versi lama:
Menggunakan pendekatan yang agak berbeda dengan jawaban php lainnya. Bergantung pada kurangnya dukungan asli untuk string multi-byte di php.

<?php for($l=strlen($a=$argv[1]);$a=mb_substr($a,1);$l=$v)echo$l-($v=strlen($a));echo$l?:'';
pengguna55641
sumber
Jawaban bagus! Saya pikir Anda dapat menghapus tag pembuka seluruhnya, atau mengubahnya ke<?=
cat
Tanpa tag itu adalah potongan kode daripada sebuah program, dan bahkan jika diizinkan, itu membuat saya merasa kotor. Dengan tag alternatif Anda mendapatkan kesalahan parse (atau setidaknya saya lakukan di php 5.5 yang biasa saya lakukan).
user55641
Oke :) Saya tidak tahu PHP (saya juga tidak mau, batuk ) tapi saya tunjukkan di sini: codegolf.stackexchange.com/questions/2913
cat
3

Emacs Lisp, 55 49 byte

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

Pertama membedah string menjadi daftar karakter dengan (mapcar 'string s) . The stringfungsi dalam Emacs Lisp mengambil daftar karakter dan membangun string dari mereka. Karena cara Emacs membagi string mapcar(yaitu ke dalam daftar bilangan bulat, bukan karakter atau string), konversi eksplisit ini diperlukan. Kemudian memetakan string-bytesfungsi ke daftar string.

Contoh:

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

Testcases:

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

Jawaban lama:

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

Tidak Terkumpul:

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

Testcases:

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

Tuan Yuuma
sumber
Apa yang terjadi pada niljika Anda meratakan hasilnya?
Adám
1
@ Adám niladalah daftar kosong (dan satu-satunya cara untuk mengatakan "false" di Emacs). Meskipun tidak ada standar perataan di Emacs (Anda dapat menggunakan tanda hubung -flatten) setiap implementasi yang mungkin akan menghilangkannya.
Tuan Yuuma
3

JavaScript (Node), 27 byte

s=>s.map(Buffer.byteLength)

Ini mengambil input sebagai array karakter individual, dan mengembalikan array jumlah byte.

Bufferadalah metode yang mewakili data biner mentah. Buffer.byteLength (string) memberikan jumlah byte dalam string. UTF-8 adalah penyandian default. Perhatikan bahwa hanya Node.js yang memiliki buffer, bukan browser JS. Setara browser kasar disebut Blob , yang datang pada 31 byte:

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

Uji

Simpan file ini dan jalankan melalui node, atau coba online .

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));
});

Ini seharusnya hasilnya:

$ 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 ]
NinjaBearMonkey
sumber
3

Bash, 74 byte

Golf

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

Algoritma

string input hexdump, lipat 2 karakter per baris, potong karakter pertama saja

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

2
c
b
e
8
a
f
a
b
b

(4 bit orde tinggi dari setiap byte input sebagai hex hex, satu per baris)

Hapus "lanjutan byte" 0x80..0xBF

tr -d '89ab'

2
c

e


f

(apa yang tersisa, adalah 4 bit byte pertama dari setiap karakter unicode)

memetakan bit pertama ke dalam panjang char, menciutkan output dan mencetak

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

1 2 3 4

Uji

 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
zeppelin
sumber
+1 Pendekatan yang bagus. Anda benar-benar membaca hasilnya langsung dari input.
Adám
The -tpilihan untuk trasing bagi saya, dan ternyata ekstensi GNU. Perpipaan ke substitusi perintah setelah echomungkin juga layak penjelasan yang sedikit lebih rinci.
tripleee
2

PHP, 126 byte

<?php $s=fgets(STDIN);echo $s!=''?implode(' ',array_map(function($x){return strlen($x);},preg_split('/(?<!^)(?!$)/u',$s))):'';

Cobalah online!

Michał Perłakowski
sumber
Anda dapat memulai kode Anda dengan<?=($s=fgets(STDIN))?
Marco
2

C #, 89 82 byte

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

C # lambda sederhana yang beriterasi melalui string dan mengembalikan daftar spasi yang dipisahkan.

Sunting: disimpan 6 byte berkat beberapa komentar yang sangat bagus.

AstroDan
sumber
cukup yakin Anda bisa melakukannyavar J="";...
kucing
Juga, OP menyatakan dalam komentar bahwa Anda tidak perlu memisahkan ruang outputnya 1121 dan 1 2 1 2keduanya OK
cat
1
@cat Terima kasih, selamatkan saya 6 byte
AstroDan
Juga, Anda memiliki ruang ekstra di} return J;};
cat
Sepertinya kamu perlu using System.Text atau sekitar itu - impor tidak gratis.
kucing
2

Haskell, 85 byte

import Data.ByteString as B
import Data.ByteString.UTF8
(B.length.fromString.pure<$>)
Angs
sumber
Sedikit terlambat, tapi ini akan lebih pendek karenamap$...
H.PWiz
1

Pyth, 17 byte

mhxS+11+16,7lCdlC

Cobalah online!

Gunakan titik kode karakter dengan beberapa aritmatika.

Biarawati Bocor
sumber
4
Ada jawaban yang lebih pendek alerady.
Erik the Outgolfer
1

C, 85 byte.

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

Memeriksa tinggi 4 bit setiap byte untuk menentukan encoding dan jumlah byte berikutnya untuk dilewati;

ASHelly
sumber
Apakah ini berfungsi pada byte nol?
kucing
Ya, while *c keluar pada string kosong, dan `c + = d 'melompati nulls di tengah multi-byte codepoint.
AShelly
1
Itu tidak benar. Akhir string ( char*, sungguh) dalam C ditandai dengan byte nol. Tidak mungkin membedakan byte nol dari ujung string yang sebenarnya.
Dennis
@ Dennis Tepatnya karena tidak ada perbedaan :)
cat
1
OP menyatakan dalam komentar (dan sekarang di pos) bahwa Anda dapat meminta panjang string dalam byte sebagai argumen, jadi lakukan itu dan ini akan valid lagi
cat
1

Factor, 57 87 82 80 byte

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

Dijelaskan:

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

Tes unit:

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

Mereka semua lewat, sekarang. c:

kucing
sumber
1

Swift 2.2, 67 52 50 byte

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

Sangat jelek. Tidak ada cara untuk mendapatkan panjang UTF-8 dari Karakter di Swift, jadi saya perlu beralih melalui string dengan karakter, konversiCharacter ke String, dan menemukancount karakter tunggal ituString (hei, setidaknya ada built-in metode untuk melakukan itu). Mencari optimasi, mungkin menggunakan pemindai.

Revisi 1: Disimpan 15 byte dengan menggunakan count alih-alihunderestimateCount() .

Revisi 2: Menyimpan 2 karakter lainnya dengan menggunakan for-in loop alih-alih untuk setiap penutupan.

JAL
sumber
1

Rust, 53 byte

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

Rust memiliki primitif utf-8 char, iterators, dan lambdas, jadi ini mudah. Kode uji:

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

Keluaran

1211133112111114444 
Harald Korneliussen
sumber
1

jq, 26 karakter

(23 karakter kode + 3 opsi opsi baris perintah)

(./"")[]|utf8bytelength

Semoga bersaing. Meskipun utf8bytelengthtelah ditambahkan 9 ++ bulan sebelum pertanyaan ini, masih belum termasuk dalam versi yang dirilis.

Contoh dijalankan:

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
manatwork
sumber
1

SmileBASIC, 69 byte

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

Input adalah array byte.

Jumlah byte dalam karakter UTF-8 sama dengan jumlah 1bit terkemuka di byte pertama (kecuali tidak ada 1s, dalam hal ini karakternya adalah 1 byte). Untuk menemukan jumlah 1s terkemuka, program menemukan yang pertama 0dalam representasi biner, lalu menambahkan 1 jika ini adalah 0.

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

F #, 59 54 66 byte

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

Secara teknis, s adalah urutan char, tetapi ternyata ada konversi implisit yang memungkinkan string diteruskan.

Saat menguji ini di konsol dengan !±≡𩸽, itu membagi kanji menjadi dua karakter, masing-masing panjangnya 3 byte. Semua test case lainnya bekerja dengan baik.

Sunting: Ternyata impor namespace umum tidak tersirat. Naik 12 karakter lagi.

antarmuka disegel
sumber
1) Jawaban Powerhell Timmy D memiliki masalah 6-byte-per-kanji yang sama. Saya akan mengaitkannya dengan Windows yang bodoh dan tidak berguna di Unicode. 2) Jika Anda mendapatkan 6 byte untuk kanji saat membaca dari file yang disertakanUTF-8 without BOM maka ini salah dan harus diperbaiki. 3) Sepertinya F # membutuhkan pernyataan yang ingin let f(x)= ...diakhiri ;;, seperti SML. 4) Anda dapat mengabaikan fungsi nama anonim ini, yaitu (s)=seq{for c in s->Encoding.UTF8.GetByteCount([|c|])}.
kucing
Juga, saya dapatkan error FS0039: The namespace or module 'Encoding' is not definedketika mencoba menjalankan ini. Apa yang saya lakukan salah?
kucing
Juga, selamat datang di Programming Puzzles dan Code Golf, ini adalah jawaban pertama yang bagus! : D
cat
@ kucing Anda harus membuka System.Textnamespace. Saya mengasumsikan namespace terbuka dan kode entri disertakan, berasal dari jawaban C # AstroDan's.
antarmuka tertutup
Anda perlu menghitung byte apa saja import , #include, open, load, require, using, USING:dll di sini di PPCG. Jawaban AstroDan sama keliru, dan saya memberi tahu mereka tentang itu.
kucing
1

05AB1E , 15 byte

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

Cobalah online.
Headerεdigunakan untuk masing-masing atas semua kasus uji;
Footerï]J]»untuk mencetak daftar karakter keluaran dengan cantik (ï: desimal dan karakter ke integer;:]tutup jika-yang lain dan untuk masing-masingJ;: Gabungkan digit bersama-sama};: tutup tajuk depan;;»Gabung dengan baris baru).

Penjelasan:

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

Karena 05AB1E tidak memiliki builtin untuk mengonversi karakter ke jumlah byte yang digunakan, saya gunakan Çuntuk mengonversi karakter ke nilai unicode mereka, dan di-masing-masing melakukan hal berikut dalam pseudo-code:

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

Terinspirasi oleh @TheBikingViking 's Python 3 jawaban .

Kevin Cruijssen
sumber
0

Zsh , 41 byte

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

Cobalah online!

Zsh sadar akan UTF-8, jadi kami membagi string pada karakter, lalu menonaktifkan multibyte dan mencetak panjang setiap karakter.

Fungsi Gamma
sumber