Longueur d'une séquence d'octets UTF-8

15

Déterminez la longueur d'une séquence d'octets UTF-8 en fonction de son premier octet. Le tableau suivant montre quelles plages correspondent à chaque longueur possible:

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

Remarques sur les lacunes dans le tableau: 0x80-0xBF sont des octets de continuation, 0xC0-0xC1 démarrerait une séquence trop longue et invalide, 0xF5-0xFF entraînerait un point de code au-delà du maximum Unicode.

Écrivez un programme ou une fonction qui prend en entrée le premier octet d'une séquence d'octets UTF-8 et renvoie ou renvoie la longueur de la séquence. Les E / S sont flexibles. Par exemple, l'entrée peut être un nombre, un caractère à 8 bits ou une chaîne à un caractère. Vous pouvez supposer que le premier octet fait partie d'une séquence valide et appartient à l'une des plages ci-dessus.

C'est le golf de code. La réponse la plus courte en octets l'emporte.

Cas de test

0x00 => 1
0x41 => 1
0x7F => 1
0xC2 => 2
0xDF => 2
0xE0 => 3
0xEF => 3
0xF0 => 4
0xF4 => 4
nwellnhof
la source
Une entrée d'une liste des 8 bits est-elle acceptable?
Jonathan Allan
@JonathanAllan Non, ce serait pousser trop loin les E / S flexibles.
nwellnhof

Réponses:

5

Quatrième, 6 octets

x-size

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

L'entrée et la sortie suivent un modèle Forth standard:

Contribution

Adresse mémoire + longueur (c'est-à-dire 1) d'une "chaîne" UTF-8 à un octet.

Production

Longueur de séquence UTF-8 en octets.

Exemple de code

Stockez 0xF0 dans une cellule mémoire et appelez x-size:

variable v
0xF0 v !
v 1 x-size

Vérifiez le résultat:

.s <1> 4  ok
Zeppelin
la source
En supposant que cela fonctionne dans tio.run/#forth-gforth , pourriez-vous montrer un exemple? Je ne comprends pas comment vous pourriez avoir une chaîne UTF-8 à un octet si l'octet est 0xF0.
Dennis
> pourriez-vous montrer un exemple? Je ne comprends pas comment vous pourriez avoir une chaîne UTF-8 à un octet si l'octet est 0xF0. J'ai ajouté un exemple de code montrant comment le faire. Malheureusement, la version TIO de gforth ne semble pas supporter les mots Unicode (selon "see x-size", il est juste codé en dur d'y retourner 1).
zeppelin
Je vois. Ce n'est pas ce que j'appellerais une chaîne UTF-8, car F0 seul est une séquence d'octets invalide, en ce qui concerne UTF-8.
Dennis
> car F0 seul est une séquence d'octets invalide Vrai (c'est pourquoi j'ai mis le mot "chaîne" entre guillemets), mais cette tâche consiste spécifiquement à reconnaître la séquence par son premier octet, et Forth ne se soucie pas vraiment de son invalidité , ce qui rend cette solution possible, à son tour.
zeppelin
6

Z80Golf , 19 14 octets

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

Essayez-le en ligne!

-5 octets grâce à @Bubbler

Exemple avec entrée 0x41-Essayez-le en ligne! Assemblée

Exemple avec entrée 0xC2-Essayez-le en ligne!

Exemple avec entrée 0xE0-Essayez-le en ligne!

Exemple avec entrée 0xF4-Essayez-le en ligne!

Assemblée:

;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

Essayez-le en ligne!

Logern
la source
Utilisez Bash TIO pour travailler avec l'assemblage, avec des exemples plus faciles à voir. Le lien contient également une version 15 octets de votre solution. Voici les améliorations: xor 0xff -> cpl, pas besoin de or a, jr nz, return -> ret nz, ld a,1 -> inc a.
Bubbler
5

C (gcc) , 39 octets

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

Essayez-le en ligne!

user202729
la source
Pourquoi charet non int?
R .. GitHub ARRÊTER D'AIDER LA GLACE
@R .. Parce qu'ils obtiennent un signe étendu. Par exemple ~(char)0xF0 == ~(int)0xFFFFFFF0(supposez char = signed char, sizeof(int) == 4)
user202729
Ah, en supposant que char est signé.
R .. GitHub ARRÊTEZ D'AIDER LA GLACE
4

Gelée ,  8  7 octets

+⁹BIITḢ

Un lien monadique acceptant l'octet comme un entier.

Essayez-le en ligne! Ou voyez toutes les entrées évaluées .

Si une entrée d'une liste des 8 bits était acceptable, alors la méthode n'est que de 6 octets: 1;IITḢcependant, elle a été jugée trop parlante d'E / S flexibles.

Comment?

+⁹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
la source
3

Gelée , 8 7 octets

»Ø⁷Ba\S

Essayez-le en ligne!

Comment ça fonctionne

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

Fusain , 12 octets

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

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

     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
la source
1

Perl 6 , 18 octets

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

Essayez-le en ligne!

Port de la réponse JavaScript de user202729. Alternatives avec WwhatCode:

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

Assemblage x86, 11 octets

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

Essayez-le en ligne!

Port de la réponse JavaScript de user202729. Utilise les conventions d'appel rapide.

nwellnhof
la source
1

Labyrinthe , 35 octets

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

Essayez-le en ligne!

Version non emballée du code:

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

05AB1E , 8 7 octets

žy‚àb0k

Réponse de Port of @Neil Charcoal .
-1 octet grâce à @Grimy .

Entrez comme entier.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

ž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
la source
1
s)à pour 7. Porter l'autre réponse Jelly donne un autre 8:₁+b¥η€ËO
Grimmy
@Grimy Aucune idée pourquoi je n'ai pas eu en premier lieu ..: S Mais merci pour -1.
Kevin Cruijssen
0

C, 31 octets

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

Essayez-le en ligne!

27 octets avec gcc (-O0)

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

Alternatives, 31 et 33 octets

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

J'ai trouvé ces expressions en jouant avec les Aha! superoptimizer il y a quelques années .

nwellnhof
la source