Długość sekwencji bajtów UTF-8

15

Określ długość sekwencji bajtów UTF-8, biorąc pod uwagę jej pierwszy bajt. Poniższa tabela pokazuje, które zakresy mapują na każdą możliwą długość:

  Range    Length
---------  ------
0x00-0x7F    1
0xC2-0xDF    2
0xE0-0xEF    3
0xF0-0xF4    4

Uwagi na temat braków w tabeli: 0x80-0xBF są bajtami kontynuacyjnymi, 0xC0-0xC1 uruchomiłoby zbyt długą, niepoprawną sekwencję, 0xF5-0xFF spowodowałoby, że punkt kodowy przekroczyłby maksimum Unicode.

Napisz program lub funkcję, która pobiera pierwszy bajt sekwencji bajtów UTF-8 jako dane wejściowe i wyjściowe lub zwraca długość sekwencji. I / O jest elastyczny. Na przykład wejściem może być liczba, znak 8-bitowy lub ciąg jednego znaku. Możesz założyć, że pierwszy bajt jest częścią prawidłowej sekwencji i należy do jednego z powyższych zakresów.

To jest kod golfowy. Najkrótsza odpowiedź w bajtach wygrywa.

Przypadki testowe

0x00 => 1
0x41 => 1
0x7F => 1
0xC2 => 2
0xDF => 2
0xE0 => 3
0xEF => 3
0xF0 => 4
0xF4 => 4
nwellnhof
źródło
Czy wprowadzenie listy 8 bitów jest dopuszczalne?
Jonathan Allan,
@JonathanAllan Nie, to zbyt daleko posunąłoby się elastycznych operacji we / wy.
nwellnhof,

Odpowiedzi:

5

Dalej, 6 bajtów

x-size

patrz https://forth-standard.org/standard/xchar/X-SIZE

Dane wejściowe i wyjściowe są zgodne ze standardowym modelem Forth:

Wejście

Adres pamięci + długość (tj. 1) jednobajtowego „ciągu” UTF-8.

Wynik

Długość sekwencji UTF-8 w bajtach.

Przykładowy kod

Zapisz 0xF0 w komórce pamięci i wywołaj rozmiar x:

variable v
0xF0 v !
v 1 x-size

Sprawdź wynik:

.s <1> 4  ok
zepelin
źródło
Zakładając, że działa to w tio.run/#forth-gforth , czy możesz podać przykład? Nie rozumiem, jak możesz mieć jednobajtowy ciąg UTF-8, jeśli bajt ma wartość 0xF0.
Dennis
> czy możesz pokazać przykład? Nie rozumiem, jak możesz mieć jednobajtowy ciąg UTF-8, jeśli bajt ma wartość 0xF0. Dodałem przykładowy kod pokazujący, jak to zrobić. Niestety, gforth w wersji TIO nie obsługuje słów Unicode (zgodnie z „patrz x-size”, po prostu jest na stałe zakodowany, aby zwrócić tam 1).
zeppelin
Widzę. Nie to jednak nazwałbym ciągiem UTF-8, ponieważ sam F0 jest nieprawidłową sekwencją bajtów, jeśli chodzi o UTF-8.
Dennis
> ponieważ sam F0 jest nieprawidłową sekwencją bajtów Prawda (dlatego umieściłem słowo „ciąg” w cudzysłowach), ale to zadanie polega konkretnie na rozpoznaniu sekwencji po pierwszym bajcie, a Forth tak naprawdę nie dba o to, aby była niepoprawna , co z kolei umożliwia takie rozwiązanie.
zeppelin
6

Z80Golf , 19 14 bajtów

00000000: 2f6f 3e10 37ed 6a3d 30fb ee07 c03c       /o>.7.j=0....<

Wypróbuj online!

-5 bajtów dzięki @Bubbler

Przykład z wejściem 0x41 - Wypróbuj online! montaż

Przykład z wejściem 0xC2 - Wypróbuj online!

Przykład z wejściem 0xE0 - Wypróbuj online!

Przykład z wejściem 0xF4 - Wypróbuj online!

Montaż:

;input: register a
;output: register a
byte_count:			;calculate 7^(log2(255^a))||1
	cpl			;xor 255
	ld l,a
	log2:
		ld	a,16
		scf
	log2loop:
		adc	hl,hl
		dec	a
		jr	nc,log2loop
	xor 7
	ret nz
	inc a

Wypróbuj online!

Logern
źródło
Użyj Bash TIO do pracy z asemblerem, z łatwiejszymi do zobaczenia przykładami. Link zawiera również 15-bajtową wersję Twojego rozwiązania. Oto ulepszenia: xor 0xff -> cpl, nie ma potrzeby or a, jr nz, return -> ret nz, ld a,1 -> inc a.
Bubbler,
5

C (gcc) , 39 bajtów

t(char x){x=(__builtin_clz(~x)-24)%7u;}

Wypróbuj online!

użytkownik202729
źródło
Dlaczego charnie int?
R .. GitHub ZATRZYMAJ LOD
@R .. Ponieważ dostają znak przedłużony. Na przykład ~(char)0xF0 == ~(int)0xFFFFFFF0(zakładamy char = signed char, sizeof(int) == 4)
user202729
Ach, zakładając, że char jest podpisany.
R .. GitHub ZATRZYMAJ LÓD
4

Galaretka ,  8  7 bajtów

+⁹BIITḢ

Łącze monadyczne akceptujące bajt jako liczbę całkowitą.

Wypróbuj online! Lub zobacz wszystkie ocenione dane wejściowe .

Jeśli wejście listy 8 bitów jest akceptowalne, wówczas metoda ma tylko 6 bajtów: 1;IITḢ jednak za daleko została uznana za mówiącą elastyczne we / wy.

W jaki sposób?

+⁹BIITḢ - Link: integer       e.g.: 127 (7f)            223 (df)            239 (ef)            244 (f4)
 ⁹      - literal 256
+       - add                       383                 479                 495                 500
  B     - to a list of bits         [1,0,1,1,1,1,1,1,1] [1,1,1,0,1,1,1,1,1] [1,1,1,1,0,1,1,1,1] [1,1,1,1,1,0,1,0,0]
   I    - increments                [-1,1,0,0,0,0,0,0]  [0,0,-1,1,0,0,0,0]  [0,0,0,-1,1,0,0,0]  [0,0,0,0,-1,1,-1,0]
    I   - increments                [2,-1,0,0,0,0,0]    [0,-1,2,-1,0,0,0]   [0,0,-1,2,-1,0,0]   [0,0,0,-1,2,-2,1]
     T  - truthy indices            [1,2]               [2,3,4]             [3,4,5]             [4,5,6,7]
      Ḣ - head                      1                   2                   3                   4
Jonathan Allan
źródło
3

Galaretka , 8 7 bajtów

»Ø⁷Ba\S

Wypróbuj online!

Jak to działa

»Ø⁷Ba\S  Main link. Argument: n (integer)

 Ø⁷      Yield 128.
»        Take the maximum of n and 128.
   B     Yield the array of binary digits.
    a\   Cumulatively reduce by AND, replacing 1's after the first 0 with 0's.
      S  Take the sum.
Dennis
źródło
1

Węgiel drzewny , 12 bajtów

I⌕⍘⌈⟦N¹²⁸⟧²0

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

     N          Input number
      ¹²⁸       Literal 128
   ⌈⟦    ⟧      Take the maximum
  ⍘       ²     Convert to base 2 as a string
 ⌕         0    Find the position of the first `0`
I               Cast to string
                Implicitly print
Neil
źródło
1

Perl 6 , 18 bajtów

{7-msb(255-$_)||1}

Wypróbuj online!

Port odpowiedzi JavaScript użytkownika user202729. Alternatywy z dowolnym kodem:

(255-*).msb*6%34%7
-(255-*).msb%6%5+1
nwellnhof
źródło
1

Zestaw x86, 11 bajtów

00000000 <f>:
   0:   f6 d1                   not    %cl
   2:   0f bd c1                bsr    %ecx,%eax
   5:   34 07                   xor    $0x7,%al
   7:   75 01                   jne    a <l1>
   9:   40                      inc    %eax
0000000a <l1>:
   a:   c3                      ret

Wypróbuj online!

Port odpowiedzi JavaScript użytkownika user202729. Korzysta z konwencji szybkiego połączenia.

nwellnhof
źródło
1

Labirynt , 35 bajtów

? 28& 16/ )!@!
:_1 ";_ _3&""2
   @1

Wypróbuj online!

Nieopakowana wersja kodu:

?:_128&1!@
      ;
      _16/_3&2!@
            )
            !
            @
Herman L.
źródło
1

05AB1E , 8 7 bajtów

žy‚àb0k

Port odpowiedzi na węgiel drzewny @Neil .
-1 bajt dzięki @Grimy .

Wprowadź jako liczbę całkowitą.

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

žy       # Push 128
        # Pair it with the (implicit) input-integer
   à     # Take the maximum of this pair (128 and input)
    b    # Convert it to a binary-string
     0k  # Get the 0-based first index of a "0" in this binary-string
         # (and output it implicitly as result)
Kevin Cruijssen
źródło
1
s)do do 7. Przenoszenie druga odpowiedź Jelly daje inny 8:₁+b¥η€ËO
Grimmy
@Grimy Nie mam pojęcia, dlaczego nie miałem w ogóle ..: S Ale dzięki za -1.
Kevin Cruijssen
0

C, 31 bajtów

f(x){return(x-160>>20-x/16)+2;}

Wypróbuj online!

27 bajtów z gcc (-O0)

f(x){x=(x-160>>20-x/16)+2;}

Alternatywy, 31 i 33 bajty

f(x){return(10>>15-x/16)+7>>2;}
f(x){return x/128-(-3>>15-x/16);}

Znalazłem te wyrażenia podczas zabawy z Aha! superoptimizer kilka lat temu .

nwellnhof
źródło