UTF-8 é uma maneira relativamente simples de codificar pontos de código Unicode em um formato de largura variável, para que não confunda facilmente código que não é compatível com Unicode.
Visão geral do UTF-8
- Bytes no intervalo de 1-0x7F, inclusive, são normalmente válidos
- Os bytes com o padrão de bits
10XX XXXX
são considerados bytes de continuação, com os seis bits menos significativos sendo usados para codificar parte de um ponto de código. Eles não devem aparecer, a menos que sejam esperados por um byte anterior. - Os bytes com o padrão
110X XXXX
esperam um byte de continuação depois - Os bytes com o padrão
1110 XXXX
esperam dois bytes de continuação depois - Os bytes com o padrão
1111 0XXX
esperam três bytes de continuação depois - Todos os outros bytes são inválidos e não devem aparecer em nenhum lugar de um fluxo UTF-8. Clusters de 5, 6 e 7 bytes são possíveis em teoria, mas não serão permitidos para os propósitos deste desafio.
Codificações excessivas
O UTF-8 também exige que um ponto de código seja representado com o número mínimo de bytes. Qualquer sequência de bytes que possa ser representada com menos bytes não é válida. O UTF-8 modificado adiciona uma exceção a isso para caracteres nulos (U + 0000), que devem ser representados como C0 80
(representação hexadecimal)) e, em vez disso, não permite que bytes nulos apareçam em qualquer lugar do fluxo. (Isso o torna compatível com cadeias terminadas em nulo)
Desafio
Você deve criar um programa que, ao receber uma sequência de bytes, determine se essa sequência representa UTF-8 modificado válido e retornará um valor verdadeiro, se válido, e caso contrário, um valor falso. Observe que você deve verificar se há codificações longas e bytes nulos (já que este é UTF-8 modificado). Você não precisa decodificar os valores UTF-8.
Exemplos
41 42 43 ==> yes (all bytes are in the 0-0x7F range)
00 01 02 ==> no (there is a null byte in the stream)
80 7F 41 ==> no (there is a continuation byte without a starter byte)
D9 84 10 ==> yes (the correct number of continuation bytes follow a starter byte)
F0 81 82 41 ==> no (there are not enough continuation bytes after F0)
EF 8A A7 91 ==> no (too many continuation bytes)
E1 E1 01 ==> no (starter byte where a continuation byte is expected)
E0 80 87 ==> no (overlong encoding)
41 C0 80 ==> yes (null byte encoded with the only legal overlong encoding)
F8 42 43 ==> no (invalid byte 'F8')
Regras
- Aplicam-se regras e brechas padrão
- A entrada e a saída podem estar em qualquer formato conveniente, desde que todos os valores no intervalo de bytes não assinados (0-255) possam ser lidos.
- Pode ser necessário usar uma matriz ou arquivo em vez de uma sequência terminada por nulo. Você precisa ler bytes nulos.
- O menor código vence!
- Observe que não é garantido que o uso de built-in para decodificar o UTF-8 esteja em conformidade com os requisitos fornecidos aqui. Pode ser necessário contorná-lo e criar casos especiais.
EDIT: bônus adicional por não usar builtins que decodificam UTF-8
EDIT2: bônus removido, já que apenas a resposta Rust foi qualificada e é difícil de definir.
fonte
Respostas:
Elixir , 69 bytes
Experimente online!
Faz uso da função interna de validação de string. Recebe a entrada como Elixir binário.
fonte
APL (Dyalog Unicode) ,
4139 bytes SBCSFunção de prefixo tácito anônimo. Toma uma string Unicode como argumento em que os pontos de código dos caracteres representam os bytes de entrada.
Experimente online!
'À\x80'⎕R⎕A
R moran Jr.C0 80
s com a letra maiúscula Um lphabet{
…}
Aplique a seguinte função anônima, em que o argumento é⍵
:0::
se ocorrer algum erro:0
retornar zero⋄
tentar:⎕UCS⍵
converter a string em pontos de código'UTF-8'⎕UCS⍣2
interpretar como UTF-8 bytes e converter o texto resultante em bytes⌊/
byte mais baixo (zero se houver um byte nulo, positivo se não for, "infinito" se for uma string vazia)×
sinal (zero se houver byte nulo, um se não estiver)fonte
D9 C0 80 84 C0 80 10
?C0 80
faz com que bytes não relacionados sejam adjacentes de uma maneira que seja válida, embora sejam inválidos quando separados? Editar: atualizado para corrigir isso sem custo de bytes.Python 2 ,
104102 bytesExperimente online!
Saídas via código de saída
fonte
Ferrugem -
191 bytes313 bytesPor comentário abaixo original não funcionou corretamente. Versão nova e melhorada. Nenhuma biblioteca é usada, porque o Mighty Rust não precisa de você e de suas bibliotecas. Esse código usa a correspondência de padrões com uma máquina de estado. Por descaradamente arrancando a especificação UTF8 , depois de encontrar, através de referência e discussão por Jon Skeet , podemos copiar a especificação quase personagem para personagem em um jogo de bloco padrão de jogo ferrugem. No final, adicionamos o requisito especial Mutf8 da Beefster para que o C0 80 seja considerado válido. Ungolfed:
experimentá-lo no parque infantil ferrugem
fonte