Bayt / Karakter


28

Görev

Bir UTF-8 dizgisine (herhangi bir yolla) verilen (herhangi bir yolla), her elemanın karşılık gelen giriş karakterini kodlamak için kullanılan bayt sayısı olduğu eşdeğer bir listeye cevap verilir.

Örnekler

!1

Ciao1 1 1 1

tʃaʊ1 2 1 2

Adám1 1 2 1

ĉaŭ2 1 2(tek karakter)

ĉaŭ1 2 1 1 2(kaplamaları birleştirmeyi kullanır)

チャオ3 3 3

(boş giriş) → (boş çıktı)

!±≡𩸽1 2 3 4

A (boş bayt) → 1

Boş bayt

Girdiyi boş baytların ötesinde tutmanın tek yolu toplam bayt sayısını bilmekse, bayt sayısını herhangi bir yolla (kullanıcı girişi bile) alabilirsiniz.

Diliniz boş baytları tamamen işleyemiyorsa, girişin boş içermediğini varsayabilirsiniz.


1
Giriş boşsa 0 veya başka bir falsey değeri yazabilir miyiz?
Alex A.

2
Bayt sayımlarını ayırmadan yazdırabilir miyim? Mümkün olan en yüksek değer 6'dır, yani kesindir.
Dennis,

3
Boş baytları desteklemek zorunda mıyız? Bunlar bazı dillerde gerçek bir acı olabilir ...
Dennis

3
Bunu yazıya eklemelisin. Dillerin çoğunu fark yaratıp yaratmadığını söyleyecek kadar iyi bilmiyorum, ancak cevapların en az ikisini geçersiz kıldığını düşünüyorum.
Dennis,

2
@ Adám evet olacak. Örneğin, C'de, C dizeleri bir NUL byte'ı ile biter, böylece bir tane bulursanız okumaya son verirsiniz. Dizenin uzunluğunu biliyorsanız, bu kadar bayttan sonra, NUL ve hepsinden sonra okumayı bırakırsınız.
kedi,

Yanıtlar:


10

Pyth, 9 7 bayt

2 bayt tasarrufu için @Maltysen için teşekkürler!

mlc.Bd8

Test odası

Girişin her karakterini ikili gösterime dönüştürür ve bunu 8 uzunluğundaki parçalara böler. Bu parçaların sayısı daha sonra bu karakteri kodlamak için gereken bayt miktarıdır.


1
bölmek yerine .E bölmeyle
1'i

@Maltysen Bu zekice, teşekkürler!
Denker

1
Benzer bir numaraya dayanan aynı uzunluktaki cevap:mlhc8.B
FryAmTheEggman

@LeakyNun o zaman başarısız bir test vakası vermek basit bir şey olurdu, değil mi?
16'da

Başka bir bayttan tasarruf etmek için 8’in parçalarına bölünmek yerine, her 8’de birini alın: ml%8.B(şimdi dkapalıdır).
Anders Kaseorg


11

C, 68 65 bayt

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

3 baytlık golf oynamak için @FryAmTheEggman'a teşekkürler!

İdeone üzerinde test et .


11

APL, 15 karakter

≢¨'UTF-8'∘⎕ucs¨

İngilizce: her bir karakteri UTF-8'e çevir (anlam: bayt gösterimi vektörü) ve onun değerini al.


Bir bayt kaydet:≢¨'UTF-8'∘⎕ucs¨
Adám

Gerçekten de @ Adám ... Şerefe.
lstefano

İlginç (ancak daha uzun) dizi temelli bir yaklaşım:+⌿0 7 11 16∘.≤2⍟⎕UCS
Am

Sürüm 16.0:0 7 11 16⍸2⍟⎕UCS
Adám

7

GolfScript, 16 bayt

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

Çevrimiçi deneyin!

Arka fon

GolfScript, Unicode'un ne olduğu hakkında hiçbir ipucu yoktur; tüm dizeler (giriş, çıkış, iç) bayttan oluşur. Bu oldukça can sıkıcı olabilir, ancak bu meydan okuma için mükemmel.

UTF-8 ASCII ve ASCII olmayan karakterleri farklı şekilde kodlar:

  • 128'in altındaki tüm kod noktaları olarak kodlanmıştır 0xxxxxxx.

  • Diğer tüm kod noktaları olarak kodlanmıştır 11xxxxxx 10xxxxxx ... 10xxxxxx.

Bu, her Unicode karakterinin kodlamasının, tek bir 0xxxxxxxbayt veya bir tek 11xxxxxxbayt ve 1 ila 5 10xxxxxxbayt içerdiği anlamına gelir .

Tarafından girilecek tüm bayt bölerek 64 , ki bu 0xxxxxxxiçine 0 ya da 1 , 11xxxxxxiçine 3 ve 10xxxxxxiçine 2 .

Bölüm 2 ile karşılaştırılırsa - 1 için 2'ye ; ve 0 , 1 ve 3 için 0 - her karakter 0'a , ardından 1 - 5 1 'e çevrilir .

Geriye kalan tek şey sonuç dizgisini 0 oluşumunda bölmek, bu sıfırlar arasında 1 'in sayısını saymak ve miktara bir tane eklemek.

Nasıl çalışır

{     }%          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 bayt

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

NB

Tamam, bu çalışması gerekir ve bir 𩸽şekilde 3,3benim makinemde sayılması dışında, neredeyse tüm test durumlarında çalışır . Bu karakter bilgisayarımda 7 byte bile gösteriyor . Bunun nedeninin yerel olarak çalıştığım Windows veya .NET sürümünde bir hata olduğuna inanıyorum, çünkü @Mego'da bu sorun yok . ( Düzenleme: bunu @cat noktaları nedeniyle BOM , @cat bu sırrı çözmek için teşekkürler.! )

Ancak, bu hala tüm sorunu hesaba katmıyor. Sanırım bazı sorunların nereden geldiğini biliyorum . .NET içinde, tüm dizeler UTF-16 kod birimlerinden oluşur (System.Char türüdür). PowerShell'in kullandığı çok gevşek tiplendirme ile, arka plandaki türler arasında çok sayıda gizli döküm ve dönüşüm vardır. Muhtemelen bu, gördüğümüz davranışa katkıda bulunan bir faktördür - örneğin, [system.text.encoding]::utf8.getchars([System.Text.UTF8Encoding]::UTF8.GetBytes('𩸽'))tek bir karakter yerine iki yazdırılamaz.


açıklama

Çok basit kod. Girdiyi alır $args[0]ve açıkça bir karakter dizisi olarak atar, böylece dizginin her bir bileşeni boyunca dolaşabiliriz |%{...}. Her yinelemede, geçerli karakterin bayt sayısını almak için .NET çağrısını [System.Text.Encoding]::UTF8.GetByteCount()( System.ima edilir) kullanırız $_. Daha sonra çıkış için boru hattına yerleştirilir. [int]Döndürülen bir s koleksiyonu olduğundan, bir diziye yayın yapmak çok önemlidir.

Test Çalıştırması

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

Eklemek üzere düzenlenmiş Bu, verileri bir metin dosyasından çekip aşağıdaki şekilde aktarmanız koşuluyla, başlangıçta gönderildikten sonra zorluğa eklenen boş bayt gereksinimlerini doğru şekilde hesaplar:

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.Evet, bunun nedeni UTF-8 ile Windows'ta elde ettiğiniz Bayt-Order Mark . Not Defteri ++ 'ya kullanmasını söyleyin UTF-8 without BOM( BOM'dan özellikle kaçınmanız gerektiğinden , özellikle Kurallar ile uyumluluğun olması için) ve dosyanın 4 bayt boyutunda olduğunu göreceksiniz, çünkü ürün listesi 3 ve 4 + 3 = 7
cat

@ cat Ah, evet, bu mantıklı. Tamam, böylece dosya boyutlarındaki farkı hesaba katar. Ancak, bu hala kabuğun kendi içindeki farklı davranışları hesaba katmaz. Örneğin, ürün reçetesi olmadan UTF-8 olarak kaydetme ve çalıştırma get-content -Encoding UTF8 .\z.txt|%{.\bytes-per-character.ps1 $_}hala geri döner 3,3.
AdmBorkBork



6

JavaScript (ES6), 54 45 43 bayt

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

Düzenleme: @ l4m2 yardımı ile 2 bayt kaydedildi.


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

@ l4m2 Bu BMP olmayan karakterler için başarısız olur, ancak bunu düzeltebildim.
Neil


5

Perl 6 ,  77 69  63 bayt

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

Yana Perl 6 kullanır dizeleri NFG Ben özelliğini sidesteps hangi doğrudan bayt çekmek için var.
(NFG, NFC gibidir, ayrıca sentetik oluşan kod noktaları yaratır.)

Çıktı yeni satırlarla ayrılmıştır.

Ölçek:

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)

Açıklama:

# 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

Bu çalışır çünkü çok baytlık bir kod noktasındaki ilk bayt, içinde kodlanmış bayt sayısına sahiptir ve kod noktasındaki diğer baytlar en yüksek bit kümesine sahiptir, ancak en yüksek bit ayarına sahiptir. Tek bayt kod noktaları en yüksek bit ayarına sahip değildir.


Yapamaz read:1ve / veya /while$yerine? Ve eğer işe yararsa if$?
Outgolfer Erik,

@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Hayır, çünkü bu farklı bir şey olarak ayrıştırılır. whileGerçi daha önce boşluğu kaldırabilirim .
Brad Gilbert 2

NFG önlemlerini açıklayabilir misiniz?
JDługosz

Bu programın STDIN'sine bir NUL baytı ekosam, yazdırıyor \n1\n1\n, kasıtlı mı? Temel olarak, bu NUL baytını işler mi?
Kedi,

@ cat Neden olmasın? Bunu yaparken: perl -e 'print "𩸽\0𩸽"' | perl6 -e '...'Ben olsun 4␤1␤4sadece ben beklenebilir gibi. (Nuls ile ilgili bölüm ben yayınlanmıştır sonra eklendi)
Brad Gilbert 13

5

Python 3, 82 bayt

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

Bu, diğer Python cevabından ve diğer cevapların çoğunluğundan çok daha uzun, ancak henüz görmediğim logaritmaları içeren bir yaklaşım kullanıyor.

Girdiyi argüman yoluyla dize olarak alan ve bir liste döndüren adsız bir işlev.

Ideone'da dene

Nasıl çalışır

Bu yöntem UTF-8'in bir karakterin kod noktasını kodlama şekline dayanır. Kod noktası 128'den küçükse, karakter ASCII'deki gibi kodlanır:

0xxxxxxx

burada xkod noktasının biti temsil eder. Bununla birlikte, 128'den büyük veya ona eşit kod noktaları için, ilk bayt, 1toplam bayt sayısıyla aynı s sayısı ile doldurulur ve ardından bayt başlar 10. Kod noktasının bitleri mümkün olan en kısa bayt sırasını vermek için girilir ve kalan bit olur 0.

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

ve diğerleri.

Artık her bir bayt nsayısı için, kod noktası bitlerinin sayısı için üst limitin verildiği fark edilebilir (-n+7)+6(n-1) = 5n+1. Bu nedenle, cher nbiri için üst limit kod noktası , ondalık olarak verilir c= 2^(5n+1). Bunun yeniden düzenlenmesi verir n = (log2(c)-1)/5. Bu nedenle, herhangi bir kod noktası için, yukarıdaki ifadeyi değerlendirerek ve sonra tavan alarak bayt sayısı bulunabilir.

Ancak, bu aralıktaki kod noktaları için çalışmaz 64 <= c <= 127bir dolgu eksikliği beri 1nedeniyle yanlış üst sınır tahmin ediliyor ve bu 1 bayt karakterler vasıtasıyla için kodlama ASCII benzeri log2için tanımlanmamış c = 0null byte olur ki, girişte mevcut. Bu nedenle, eğer c <= 127, 1n için bir değer döndürülür.

Bu tam olarak kodun yaptığı şeydir; idizedeki her karakter xiçin kod noktası, ordişlev kullanılarak bulunur ve ifadenin tavanı, kayan bölme yerine 5ve sonra ekleyerek tam sayı kullanılarak bulunur 1. Python'un yüzdürme türü her zaman tamsayıları temsil ettiğinden x.0, tamsayı bölünmesinden sonra bile sonuç, intsıfırı sıfırdan kaldırma işlevine iletilir . Eğer ord(i) <= 127, mantıksal kısa devre 1, bunun yerine geri gönderildiği anlamına gelir . Her karakter için bayt sayısı bir listede öğe olarak saklanır ve bu liste döndürülür.


5

Java 10, 100 96 95 67 61 bayt

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

-4 için boşlukları kaldırarak bayt bu yorumlar izin verilir
-1 değişen bayt UTF-8için utf8
-28 8 (Java 7 giden bayt a->{...}yerine void c(char[]i)throws Exception{...})
-3 dize-dizi yerine karakter dizisi, ve benzeri gibi girdi alma bayt
-3 bayt Java 8’den 10’a kadar ( varyerine String)

Açıklama:

Çevrimiçi deneyin.

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

Boş baytlar için çalışıyor mu?
kedi,

@ cat Boş baytlar için test durumu daha sonra eklendi. Ama evet, boş baytlar için de işe yarıyor ve test vakasını ekledim.
Kevin Cruijssen

3

Julia, 34 bayt

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

Bu bir dizgeyi kabul eden ve bir tamsayı dizisi döndüren adsız bir işlevdir. Aramak için değişkene atayın.

Yaklaşım oldukça basittir: Giriş boşsa, çıkış boştur. Aksi halde sizeof, bir dizgideki bayt sayısını her bir karakter alt dizgisine sayan işlevi eşleriz.

Çevrimiçi deneyin! (tüm test durumlarını içerir)


s->[sizeof("$c")for c=s]birkaç bayt kaydeder.
Dennis

Tek; mu split("","")döndürmez []? (JavaScript'in "".split("")yaptığı.)
Neil

@Neil split("","")vermek için görünür ""(bir istisna verir Python aksine) ama uyumluluğu hakkında hiçbir şey bilmiyorum []ve ""Julia içinde.
Kedi,

@Neil Hayır, split("", "") == [""]yani boş bir dize içeren tek elemanlı bir dizi, ancak sorun sizeof("") == 0OP'nin izin verilmediğidir.
Alex A.,

@Dennis Dizin oluşturulamayan dizeler için başarısız olur. (Buna rağmen önceden bir örnek düşünemiyorum.)
Alex A. 20

3

PHP, 92 57 bayt

İkinci düşündüğünüzde, bunu daha az solma ile yapabilirsiniz:

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

Çevrimiçi olarak deneyin, bunun bir program argümanı yerine stdin kullandığı için biraz daha uzun olduğunu unutmayın.
Bu sürüm stderr'e gönderilen bildirimleri görmezden gelmenizi gerektirir, ancak sorun değil .

eski sürüm:
Diğer php cevabına oldukça farklı bir yaklaşım kullanır. PHP'de çok baytlık dizeler için yerel destek eksikliğine güvenir.

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

Güzel cevap! Ben tamamen açılış etiketi bırakın veya değiştirebilirsiniz düşünüyorum<?=
kedi

Etiketi olmadan, bir program yerine bir kod pasajı ve izin olsa bile, kendimi belirsiz kirli hissediyorum. Alternatif etiket ile bir ayrıştırma hatası alırsınız (veya en azından alışkın olduğum php 5.5'te yaptım).
user55641

Tamam :) PHP bilmiyorum (ne de olsa öksürmek istemiyorum ) ama sizi buraya işaret edeceğim: codegolf.stackexchange.com/questions/2913
cat

3

Emacs Lisp, 55 49 bayt

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

İlk önce dizgiyi, ile bir karakter listesine ayırır (mapcar 'string s). stringEmacs Lisp fonksiyon karakterlerin bir listesini alır ve onlardan bir dize oluşturur. Emacs'in dizeleri bölüştüğü için mapcar(yani, karakter veya dizgiler yerine tamsayılar listesine), bu açık dönüşüme ihtiyaç vardır. Ardından string-bytesişlevi bu dizeler listesine eşler .

Örnek:

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

Eski cevap:

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

Ungolfed:

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


nilSonucu düzleştirirseniz ne olur ?
Adám

1
@ Adám nilboş bir listedir (ve Emacs'ta "yanlış" demenin tek yolu). Emacs'ta standart düzleşme olmamasına rağmen (kısa çizgi kullanabilirsiniz -flatten) olası uygulamaların hepsi ortadan kaldırır.
Lord Yuuma

3

JavaScript (Düğüm), 27 bayt

s=>s.map(Buffer.byteLength)

Bu, girdiyi tek tek karakter dizisi olarak alır ve bir bayt sayısı dizisi döndürür.

Bufferham ikili verileri temsil eden bir yöntemdir. Buffer.byteLength (string) dizedeki bayt sayısını verir. UTF-8 varsayılan kodlamadır. Yalnızca Node.js’nin arabellekleri olduğunu, JS tarayıcısının olmadığını unutmayın. Kaba tarayıcı eşdeğeri, 31 baytta gelen Blob olarak adlandırılır :

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

Ölçek

Bu dosyayı kaydedin ve düğümü kullanarak çalıştırın veya çevrimiçi deneyin .

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

Sonuç bu olmalı:

$ 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 bayt

golfed

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

Algoritma

hexdump giriş dizgisi, satır başına 2 karakter katlama, yalnızca ilk karakteri kesme

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

2
c
b
e
8
a
f
a
b
b

(Her satırda bir tane olmak üzere her bir giriş baytının altıgen char olarak 4 yüksek sipariş biti

"Devamı bayt" 0x80..0xBF çıkarın

tr -d '89ab'

2
c

e


f

(geriye kalanlar, her bir unicode karakterinin ilk baytının 4 bitidir)

ilk bitleri karakter uzunluğu ile eşleştirin, çıktıyı daraltın ve yazdırın

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

1 2 3 4

Ölçek

 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 Güzel yaklaşım. Aslında sonucu doğrudan girdiden okudunuz.
Adám

Bu -tseçenek trbana yabancıydı ve görünüşe göre GNU’nun bir uzantısı. Daha sonra komut yerine geçen echoboruları biraz daha ayrıntılı bir şekilde açıklamaya değer olabilir.
tripleee


2

C #, 89 82 bayt

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

Dizi içinde yinelenen ve boşlukla ayrılmış listeyi döndüren basit bir C # lambda.

Düzenleme: çok güzel yorumlarınız sayesinde 6 bayt kaydedildi.


Yapabildiğinizden eminvar J="";...
kedi

Ayrıca OP, yorumda çıktıyı boşlukla ayırmanız gerekmediğini 1121ve 1 2 1 2her ikisinin de tamam olduğunu belirtir
cat

1
@cat Teşekkürler, beni 6 bayt kurtardı
AstroDan

Ayrıca, fazladan bir boşluğunuz var} return J;};
kedi

İhtiyacınız olan using System.Textya da bunlara ihtiyacınız gibi görünüyor - ithalat ücretsiz değildir.
kedi,

2

Haskell, 85 bayt

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

Biraz geç, ama bu daha kısa olurdumap$...
H.PWiz


1

C, 85 bayt.

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

Kodlamayı ve atlanacak sonraki bayt sayısını belirlemek için her bir baytın yüksek 4 bitini inceler;


Bu boş baytlarda çalışır mı?
kedi

Evet, while *c boş bir dizgeden çıkar ve `c + = d 'çoklu bayt kod noktasının ortasındaki boşları atlar.
AShelly

1
Bu yanlış. char*C'deki bir dizgenin sonu ( , gerçekten) boş bir baytla işaretlenir. Boş baytları dizenin gerçek sonundan ayırt etmek imkansızdır.
Dennis,

@Dennis Kesinlikle fark yok çünkü :)
kedi

1
OP yorumunda belirtilen (ve post şimdi var) Eğer bir argüman olarak bayt dize uzunluğunu talep yüzden bunu ve bu tekrar geçerli olacaktır ki
kedi

1

Faktör, 57 87 82 80 bayt

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

Açıklaması:

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

Birim testleri:

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

Şimdi hepsi geçiyor. c:


1

Hızlı 2.2, 67 52 50 bayt

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

Korkunç derecede çirkin. UTF-8'in Swift'deki bir Karakter uzunluğunu almasının bir yolu yoktur, bu yüzden karaktere göre dizgiyi yinelemeliyim,Character aString ve counto tek karakterin karakterini bulmam gerekiyor String(hey, en azından yerleşik bir karakter var) bunu yapma yöntemi). Muhtemelen bir tarayıcı kullanarak, optimizasyonlar arıyorsunuz.

Revizyon 1: Kullanmak countyerine 15 bayt kaydedildi underestimateCount().

2. Düzeltme: Her kapatma için bir for-in döngüsü kullanarak başka bir 2 karakter daha kaydedildi.


1

Pas, 53 bayt

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

Rust, utf-8 karakter ilkellerine, yineleyicilere ve lambdalara sahiptir, bu yüzden kolaydı. Test kodu:

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

çıktılar

1211133112111114444 

1

jq, 26 karakter

(23 karakter kod + 3 karakter komut satırı seçeneği)

(./"")[]|utf8bytelength

Umarım rekabet eder. Bu sorudan 9 ay önce eklenmiş olmasına rağmen utf8bytelength, yayımlanan sürüme hala dahil edilmemiştir.

Örnek çalışma:

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 bayt

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

Giriş bir bayt dizisidir.

UTF-8 karakterindeki bayt sayısı 1, ilk bayttaki öncül bit sayısına eşittir ( 1s olmadıkça , bu durumda karakter 1 bayttır). Önde gelen 1 sayısını bulmak için, program ilk önce 0ikili göstergede bulur , sonra eğer 0 ise 1 ekler.

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 bayt

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

Teknik olarak, s bir karakter dizisidir, ancak bir dizgenin geçmesine izin veren örtük bir dönüşüm olduğu ortaya çıkmaktadır.

Bunu konsolda test ederken !±≡𩸽, kanjiyi her biri 3 bayt uzunluğunda iki karaktere böler. Diğer tüm test durumları iyi çalışıyor.

Düzenleme: Ortak ad alanı içe aktarma işlemlerinin örtük olmadığı ortaya çıktı. 12 karakter daha.


1) Timmy D'nin powhellhell cevabı , 6-byte-kanji başına aynı problemi vardır. Unicode'da Windows'un aptal ve işe yaramaz olmasına bağlanırdım. 2) Kanji için 6 bayt alırsanız, kodlanmış bir dosyadan okurken UTF-8 without BOMbu yanlış olur ve düzeltilmesi gerekir. 3) F # gibi let f(x)= ...biter ;;gibi SML gibi biter gibi ifadeler . 4) Bu isimsiz fonksiyona bir isim atayarak, yani bırakabilirsiniz (s)=seq{for c in s->Encoding.UTF8.GetByteCount([|c|])}.
Kedi,

Ayrıca, bunu error FS0039: The namespace or module 'Encoding' is not definedçalıştırmaya çalışırken alıyorum . Neyi yanlış yapıyorum?
kedi,

Ayrıca, Programming Puzzles ve Code Golf'a hoş geldiniz, bu güzel bir ilk cevap! : D
kedi

@ cat Ad alanını açmanız gerekir System.Text. Ad alanının açıldığını ve AstroDan'ın C # cevabından gelen giriş kodunun dahil olduğunu varsayıyorum.
mühürlü arayüz

Herhangi bir bayt saymam gerekir import, #include, open, load, require, using, USING:vb burada PPCG üzerinde. AstroDan'ın C # cevabı benzer şekilde yanlıştır ve ben de onları bilgilendirdim.
kedi,

1

05AB1E , 15 bayt

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

Çevrimiçi deneyin. Tüm test durumlarında her biri için
üstbilgiεkullanılır;
Altbilgiï]J]»çıkış karakter listeleri oldukça-yazdırmak için (ï: tamsayılar için ondalık sayılar ve karakterler;]: yakın if-else ve foreach;J: Birlikte basamak Katılım;}: yakın başlık foreach;»: Yeni-çizgilerle Katıl).

Açıklama:

Ç                   # 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, karakterleri kullanılan bayt miktarına dönüştürmek için herhangi bir yerleşik yapıya sahip olmadığından Ç, karakterleri unicode değerlerine dönüştürmek için kullanıyorum ve her biri için sözde kodda şunu yapıyorum:

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

@ TheBikingViking'in Python 3 cevabından ilham almıştır .


0

Zsh , 41 bayt

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

Çevrimiçi deneyin!

Zsh UTF-8 farkındadır, bu yüzden dizgiyi karakterlere böleriz, sonra çoklu bayfı devre dışı bırakırız ve her karakterin uzunluğunu yazdırırız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.