Länge einer UTF-8-Byte-Sequenz

15

Bestimmen Sie die Länge einer UTF-8-Byte-Sequenz anhand ihres ersten Bytes. Die folgende Tabelle zeigt, welche Bereiche jeder möglichen Länge zugeordnet sind:

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

Hinweise zu Lücken in der Tabelle: 0x80-0xBF sind Fortsetzungsbytes, 0xC0-0xC1 würde eine überlange, ungültige Sequenz starten, 0xF5-0xFF würde zu einem Codepunkt jenseits des Unicode-Maximums führen.

Schreiben Sie ein Programm oder eine Funktion, die das erste Byte einer UTF-8-Byte-Sequenz als Ein- und Ausgabe verwendet oder die Länge der Sequenz zurückgibt. I / O ist flexibel. Die Eingabe kann zum Beispiel eine Zahl, ein 8-Bit-Zeichen oder eine 1-Zeichen-Zeichenfolge sein. Sie können davon ausgehen, dass das erste Byte Teil einer gültigen Sequenz ist und in einen der obigen Bereiche fällt.

Das ist Code Golf. Die kürzeste Antwort in Bytes gewinnt.

Testfälle

0x00 => 1
0x41 => 1
0x7F => 1
0xC2 => 2
0xDF => 2
0xE0 => 3
0xEF => 3
0xF0 => 4
0xF4 => 4
nwellnhof
quelle
Ist eine Eingabe einer Liste der 8 Bits akzeptabel?
Jonathan Allan
@ JonathanAllan Nein, das würde flexible I / O zu weit bringen.
Nwellnhof

Antworten:

5

Viertens 6 Bytes

x-size

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

Input und Output folgen einem Standardmodell von Forth:

Eingang

Speicheradresse + Länge (dh 1) eines Einzelbyte-UTF-8- "Strings".

Ausgabe

UTF-8-Sequenzlänge in Bytes.

Beispielcode

Speichern Sie 0xF0 in einer Speicherzelle und rufen Sie x-size auf:

variable v
0xF0 v !
v 1 x-size

Überprüfen Sie das Ergebnis:

.s <1> 4  ok
Zeppelin
quelle
Wenn dies in tio.run/#forth-gforth funktioniert , können Sie ein Beispiel zeigen? Ich verstehe nicht, wie Sie eine Single-Byte-UTF-8-Zeichenfolge haben könnten, wenn das Byte 0xF0 ist.
Dennis
> könntest du ein Beispiel zeigen? Ich verstehe nicht, wie Sie eine Single-Byte-UTF-8-Zeichenfolge haben könnten, wenn das Byte 0xF0 ist. Ich habe ein paar Beispiele hinzugefügt, die zeigen, wie es geht. Leider scheint die TIO-Version von gforth die Unicode-Wörter nicht zu unterstützen (laut "see x-size" ist es nur hartcodiert, dort 1 zurückzugeben).
Zeppelin
Aha. Das würde ich allerdings nicht als UTF-8-Zeichenfolge bezeichnen, da F0 für UTF-8 allein eine ungültige Bytefolge ist.
Dennis
> da F0 allein eine ungültige Byte-Sequenz ist Stimmt (deshalb habe ich das Wort "string" in Anführungszeichen gesetzt), aber bei dieser Aufgabe geht es speziell darum, die Sequenz an ihrem ersten Byte zu erkennen, und Forth kümmert sich nicht wirklich darum, dass sie ungültig ist , was diese Lösung wiederum ermöglicht.
Zeppelin
6

Z80Golf , 19 14 Bytes

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

Probieren Sie es online!

-5 Bytes dank @Bubbler

Beispiel mit Eingabe 0x41-Online ausprobieren! Versammlung

Beispiel mit Eingabe 0xC2-Online ausprobieren!

Beispiel mit Eingabe 0xE0-Online ausprobieren!

Beispiel mit Eingabe 0xF4-Online ausprobieren!

Versammlung:

;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

Probieren Sie es online!

Logern
quelle
Verwenden Sie Bash TIO , um mit Baugruppen zu arbeiten, und zeigen Sie Beispiele, die übersichtlicher sind. Der Link enthält auch eine 15-Byte-Version Ihrer Lösung. Hier sind die Verbesserungen: xor 0xff -> cpl, keine Notwendigkeit zu or a, jr nz, return -> ret nz, ld a,1 -> inc a.
Bubbler
5

C (gcc) , 39 Bytes

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

Probieren Sie es online!

user202729
quelle
Warum charnicht int?
R ..
@R .. Weil sie Zeichen erweitert bekommen. Zum Beispiel ~(char)0xF0 == ~(int)0xFFFFFFF0(angenommen char = signed char, sizeof(int) == 4)
user202729
Ah, unter der Annahme, dass char unterschrieben ist.
R ..
4

Gelee ,  8  7 Bytes

+⁹BIITḢ

Eine monadische Verbindung, die das Byte als Ganzzahl akzeptiert.

Probieren Sie es online! Oder sehen Sie alle Eingänge ausgewertet .

Wenn eine Eingabe einer Liste der 8 Bits akzeptabel war, beträgt die Methode nur 6 Bytes: 1;IITḢ wurde jedoch angenommen, dass die flexible E / A zu weit verbreitet ist.

Wie?

+⁹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
quelle
3

Gelee , 8 7 Bytes

»Ø⁷Ba\S

Probieren Sie es online!

Wie es funktioniert

»Ø⁷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
quelle
1

Kohle , 12 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

     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
quelle
1

Perl 6 , 18 Bytes

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

Probieren Sie es online!

Port der JavaScript-Antwort von user202729. Alternativen mit WhateverCode:

(255-*).msb*6%34%7
-(255-*).msb%6%5+1
nwellnhof
quelle
1

x86-Assembly, 11 Byte

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

Probieren Sie es online!

Port der JavaScript-Antwort von user202729. Verwendet Fastcall-Konventionen.

nwellnhof
quelle
1

Labyrinth , 35 Bytes

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

Probieren Sie es online!

Entpackte Version des Codes:

?:_128&1!@
      ;
      _16/_3&2!@
            )
            !
            @
Herman L
quelle
1

05AB1E , 8 7 Bytes

žy‚àb0k

Port of @Neil 's Charcoal Antwort .
-1 Byte dank @Grimy .

Eingabe als Ganzzahl.

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung:

ž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
quelle
1
s)zu 7. Portierung der anderen Gelee-Antwort ergibt weitere 8:₁+b¥η€ËO
Grimmy
@Grimy Keine Ahnung warum ich überhaupt keine hatte ..: S Aber danke für -1.
Kevin Cruijssen
0

C 31 Bytes

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

Probieren Sie es online!

27 Bytes mit gcc (-O0)

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

Alternativen, 31 und 33 Bytes

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

Ich habe diese Ausdrücke beim Herumspielen mit der Aha gefunden! Superoptimierer vor ein paar Jahren .

nwellnhof
quelle