Comprimento de uma sequência de bytes UTF-8

15

Determine o comprimento de uma sequência de bytes UTF-8, considerando o primeiro byte. A tabela a seguir mostra quais intervalos são mapeados para cada comprimento possível:

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

Observações sobre lacunas na tabela: 0x80-0xBF são bytes de continuação, 0xC0-0xC1 iniciaria uma sequência inválida excessiva; 0xF5-0xFF resultaria em um ponto de código além do máximo do Unicode.

Escreva um programa ou função que aceite o primeiro byte de uma sequência de bytes UTF-8 como entrada e saída ou retorne o comprimento da sequência. A E / S é flexível. Por exemplo, a entrada pode ser um número, um caractere de 8 bits ou uma cadeia de um caractere. Você pode assumir que o primeiro byte faz parte de uma sequência válida e se enquadra em um dos intervalos acima.

Isso é código de golfe. A resposta mais curta em bytes vence.

Casos de teste

0x00 => 1
0x41 => 1
0x7F => 1
0xC2 => 2
0xDF => 2
0xE0 => 3
0xEF => 3
0xF0 => 4
0xF4 => 4
Nwellnhof
fonte
A entrada de uma lista dos 8 bits é aceitável?
Jonathan Allan
@ JonathanAllan Não, isso levaria muito longe a E / S flexível.
Nwellnhof

Respostas:

5

Quarto, 6 bytes

x-size

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

A entrada e a saída seguem um modelo Forth padrão:

Entrada

Endereço de memória + comprimento (isto é, 1) de uma "sequência" de UTF-8 de byte único.

Resultado

Comprimento da sequência UTF-8 em bytes.

Código de amostra

Armazene 0xF0 em uma célula de memória e chame o tamanho x:

variable v
0xF0 v !
v 1 x-size

Veja o resultado:

.s <1> 4  ok
zepelim
fonte
Supondo que isso funcione em tio.run/#forth-gforth , você poderia mostrar um exemplo? Eu não entendo como você poderia ter uma string UTF-8 de byte único se o byte for 0xF0.
Dennis
> você poderia mostrar um exemplo? Eu não entendo como você poderia ter uma string UTF-8 de byte único se o byte for 0xF0. Eu adicionei um código de exemplo demonstrando como fazer isso. Infelizmente, a versão TIO do gforth parece não suportar as palavras Unicode (de acordo com "consulte x-size", é apenas codificado para retornar 1).
Zeppelin #
Entendo. Isso não é o que eu chamaria de string UTF-8, já que F0 sozinho é uma sequência de bytes inválida, no que diz respeito ao UTF-8.
Dennis
> como F0 sozinho é uma sequência de bytes inválida True (foi por isso que coloquei a palavra "string" entre aspas), mas esta tarefa é especificamente sobre o reconhecimento da sequência pelo primeiro byte, e Forth não se importa realmente com a invalidade , o que torna essa solução possível, por sua vez.
Zeppelin #
6

Z80Golf , 19 14 bytes

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

Experimente online!

-5 bytes graças a @Bubbler

Exemplo com entrada 0x41-Experimente online! Montagem

Exemplo com entrada 0xC2-Experimente online!

Exemplo com a entrada 0xE0-Experimente online!

Exemplo com entrada 0xF4-Experimente online!

Montagem:

;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

Experimente online!

Logern
fonte
Use o Bash TIO para trabalhar com montagem, com exemplos mais fáceis de ver. O link também possui a versão de 15 bytes da sua solução. Aqui estão as melhorias: xor 0xff -> cpl, não há necessidade de or a, jr nz, return -> ret nz, ld a,1 -> inc a.
quer
5

C (gcc) , 39 bytes

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

Experimente online!

user202729
fonte
Por que chare não int?
R .. GitHub Pare de ajudar o gelo
@R .. Porque eles recebem sinal estendido. Por exemplo ~(char)0xF0 == ~(int)0xFFFFFFF0(assume char = signed char, sizeof(int) == 4)
user202729 07/10
Ah, assumindo que char esteja assinado.
R .. GitHub Pare de ajudar o gelo
4

Geléia ,  8  7 bytes

+⁹BIITḢ

Um link monádico que aceita o byte como um número inteiro.

Experimente online! Ou veja todas as entradas avaliadas .

Se uma entrada de uma lista dos 8 bits for aceitável, o método terá apenas 6 bytes: 1;IITḢno entanto, foi considerado como falando de E / S flexível demais.

Quão?

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

Geléia , 8 7 bytes

»Ø⁷Ba\S

Experimente online!

Como funciona

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

Carvão , 12 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

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

Perl 6 , 18 bytes

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

Experimente online!

Porta da resposta JavaScript do user202729. Alternativas ao WhateverCode:

(255-*).msb*6%34%7
-(255-*).msb%6%5+1
Nwellnhof
fonte
1

Montagem x86, 11 bytes

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

Experimente online!

Porta da resposta JavaScript do user202729. Usa convenções de ligação rápida.

Nwellnhof
fonte
1

Labirinto , 35 bytes

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

Experimente online!

Versão desembrulhada do código:

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

05AB1E , 8 7 bytes

žy‚àb0k

Resposta do porto de @Neil 's Charcoal .
-1 byte graças a @Grimy .

Entrada como inteiro.

Experimente online ou verifique todos os casos de teste .

Explicação:

ž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
fonte
1
s)para a 7. Portando a outra resposta Jelly dá outra 8:₁+b¥η€ËO
Grimmy
@ Grimy Não faço idéia por que eu não tive em primeiro lugar ..: S Mas obrigado por -1.
Kevin Cruijssen 4/10/19
0

C, 31 bytes

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

Experimente online!

27 bytes com gcc (-O0)

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

Alternativas, 31 e 33 bytes

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

Eu encontrei essas expressões ao brincar com o Aha! superoptimizador há alguns anos atrás .

Nwellnhof
fonte