Tarea
Dada una cadena UTF-8 (por cualquier medio), responda (por cualquier medio) una lista equivalente donde cada elemento es el número de bytes utilizados para codificar el carácter de entrada correspondiente.
Ejemplos
!
→ 1
Ciao
→ 1 1 1 1
tʃaʊ
→ 1 2 1 2
Adám
→ 1 1 2 1
ĉaŭ
→ 2 1 2
(caracteres individuales)
ĉaŭ
→ 1 2 1 1 2
(utiliza superposiciones combinadas)
チャオ
→ 3 3 3
(entrada vacía) →
(salida vacía)
!±≡𩸽
→ 1 2 3 4
(un byte nulo) → 1
Bytes nulos
Si la única forma de seguir leyendo la entrada más allá de los bytes nulos es conociendo el recuento total de bytes, puede obtener el recuento de bytes por cualquier medio (incluso la entrada del usuario).
Si su idioma no puede manejar bytes nulos, puede suponer que la entrada no contiene nulos.
Respuestas:
Pyth,
97 bytes¡Gracias a @Maltysen por guardar 2 bytes!
Banco de pruebas
Convierte cada carácter de la entrada en su representación binaria y luego lo divide en fragmentos de longitud 8. El número de esos fragmentos es la cantidad de bytes necesarios para codificar ese carácter.
fuente
.E
pyth.herokuapp.com/…mlhc8.B
ml%8.B
(ahora eld
está implícito).Python 3,
4236 bytesfuente
map
.lambda x:map(len,map(str.encode,x))
C,
6865 bytes¡Gracias a @FryAmTheEggman por jugar 3 bytes!
Pruébalo en Ideone .
fuente
APL, 15 caracteres
En inglés: convierta cada carácter a UTF-8 (significado: vector de representación de bytes) y obtenga su cuenta.
fuente
≢¨'UTF-8'∘⎕ucs¨
+⌿0 7 11 16∘.≤2⍟⎕UCS
0 7 11 16⍸2⍟⎕UCS
GolfScript, 16 bytes
Pruébalo en línea!
Fondo
GolfScript no tiene idea de qué es Unicode; Todas las cadenas (entrada, salida, interna) están compuestas de bytes. Si bien eso puede ser bastante molesto, es perfecto para este desafío.
UTF-8 codifica caracteres ASCII y no ASCII de manera diferente:
Todos los puntos de código por debajo de 128 están codificados como
0xxxxxxx
.Todos los demás puntos de código están codificados como
11xxxxxx 10xxxxxx ... 10xxxxxx
.Esto significa que la codificación de cada carácter Unicode contiene un solo
0xxxxxxx
byte o un solo11xxxxxx
byte y de 1 a 510xxxxxx
bytes.Al dividir todos los bytes de la entrada por 64 , nos convertimos
0xxxxxxx
en 0 o 1 ,11xxxxxx
en 3 y10xxxxxx
en 2 .Si comparamos el cociente con 2 , presionamos 1 por 2 ; y 0 para 0 , 1 y 3 : cada carácter se convertirá en un 0 , seguido de 1 a 5 1 's.
Todo lo que queda es dividir la cadena resultante en ocurrencias de 0 , contar el número de 1 entre esos ceros y agregar uno a la cantidad.
Cómo funciona
fuente
PowerShell v4, 58 bytes
nótese bien
OK, esto debería funcionar, y lo hace en casi todos los casos de prueba, excepto
𩸽
que de alguna manera se cuenta como3,3
en mi máquina. Ese personaje incluso se muestra como 7 bytes en mi computadora. Sospecho que esto se debe a algún tipo de error en la versión de Windows o .NET que estoy ejecutando localmente, ya que @Mego no tiene ese problema . ( Editar: @cat señala que esto se debe a BOM . ¡Gracias por resolver ese misterio, @cat! )Sin embargo, eso todavía no explica todo el problema. Sin embargo, creo que sé de dónde provienen algunos de los problemas. Dentro de .NET, todas las cadenas están compuestas de unidades de código UTF-16 (que es el tipo System.Char). Con el tipo de letra muy flexible que usa PowerShell, hay una gran cantidad de conversión implícita y conversión entre tipos en segundo plano. Probablemente este es un factor que contribuye al comportamiento que estamos viendo, por ejemplo,
[system.text.encoding]::utf8.getchars([System.Text.UTF8Encoding]::UTF8.GetBytes('𩸽'))
devuelve dos caracteres no imprimibles, en lugar de un solo personaje.Explicación
Código muy sencillo. Toma la entrada
$args[0]
y la convierte explícitamente como una matriz de caracteres para que podamos recorrer cada componente de la cadena|%{...}
. En cada iteración, usamos la llamada .NET[System.Text.Encoding]::UTF8.GetByteCount()
(System.
está implícita) para obtener el recuento de bytes del carácter actual$_
. Eso se coloca en la tubería para la salida posterior. Como se trata de una colección de[int]
correos electrónicos devueltos, la conversión a una matriz es implícita.Ejecuciones de prueba
Editado para agregar Esto explica adecuadamente el requisito de bytes nulos que se agregó al desafío después de que publiqué originalmente, siempre que extraiga los datos de un archivo de texto y los canalice de la siguiente manera:
fuente
That character even shows as 7 bytes on my computer.
Sí, eso se debe a Byte-Order Mark, que es lo que obtienes en Windows con UTF-8. Indique a Notepad ++ que useUTF-8 without BOM
(ya que siempre debe evitar la lista de materiales , especialmente para la compatibilidad con Unicies) y encontrará que el archivo tiene un tamaño de 4 bytes, porque la lista de materiales es 3 y 4 + 3 = 7get-content -Encoding UTF8 .\z.txt|%{.\bytes-per-character.ps1 $_}
aún devuelve3,3
.-Encoding
parámetro no parece ser compatible .JavaScript (ES6),
544543 bytesEditar: Guardado 2 bytes con ayuda de @ l4m2.
fuente
s=>[...s].map(c=>encodeURI(c).length/3-4&3)
Rubí, 33 bytes
Apenas supera a Python, ¡sí! Pruébalo en línea.
fuente
Perl 6 ,
77 6963 bytesComo Perl 6 usa cadenas NFG, tengo que extraer los bytes directamente, lo que evita la función.
(NFG es como NFC, excepto que también crea puntos de código compuestos sintéticos)
La salida está separada por nuevas líneas.
Prueba:
Explicación:
Esto funciona porque el primer byte en un punto de código de varios bytes tiene el número de bytes codificados dentro de él, y los otros bytes en el punto de código tienen el bit más alto establecido, pero no el siguiente más alto. Mientras que los puntos de código de un solo byte no tienen el bit más alto establecido.
fuente
read:1
y / o en su/while$
lugar? ¿Y si eso funcionaif$
?while
.\n1\n1\n
, ¿es intencional? Básicamente, ¿esto maneja bytes NUL?perl -e 'print "𩸽\0𩸽"' | perl6 -e '...'
me sale414
como esperaba. (Sin embargo, la parte sobre nuls se agregó después de quePython 3, 82 bytes
Esto es mucho más largo que la otra respuesta de Python, y la mayoría de las otras respuestas, pero utiliza un enfoque que involucra logaritmos que aún no he visto.
Una función anónima que toma la entrada, a través del argumento, como una cadena y devuelve una lista.
Pruébalo en Ideone
Cómo funciona
Este método se basa en la forma en que UTF-8 codifica el punto de código de un personaje. Si el punto de código es menor que 128, el carácter se codifica como en ASCII:
donde
x
representa los bits del punto de código. Sin embargo, para puntos de código mayores o iguales a 128, el primer byte se rellena con el mismo número de1
s que el número total de bytes, y comienzan los bytes subsiguientes10
. Los bits del punto de código se ingresan para obtener la secuencia multibyte más corta posible, y se convierten en los bits restantes0
.Etcétera.
Ahora se puede notar que para cada número de bytes
n
, el límite superior para el número de bits de punto de código viene dado por(-n+7)+6(n-1) = 5n+1
. Por lo tanto, el puntoc
de código de límite superior para cada unon
está dado, en decimal, porc= 2^(5n+1)
. Reorganizar esto dan = (log2(c)-1)/5
. Entonces, para cualquier punto de código, se puede encontrar el número de bytes evaluando la expresión anterior y luego tomando el techo.Sin embargo, esto no funciona para los puntos de código en el rango
64 <= c <= 127
, ya que la falta de un relleno1
debido a la codificación ASCII para caracteres de 1 byte significa que se predice el límite superior incorrecto ylog2
no está definidoc = 0
, lo que sucede si un byte nulo está presente en la entrada. Por lo tanto, sic <= 127
,1
se devuelve un valor de n.Esto es exactamente lo que está haciendo el código; para cada carácter
i
en la cadenax
, el punto de código se encuentra usando laord
función, y el techo de la expresión se encuentra usando un entero en lugar de una división flotante5
y luego sumando1
. Dado que el tipo flotante de Python siempre representa enteros ya quex.0
, incluso después de la división de enteros, el resultado se pasa a laint
función para eliminar el cero final. Siord(i) <= 127
, un cortocircuito lógico significa que en1
su lugar se devuelve. El número de bytes para cada carácter se almacena como un elemento en una lista y se devuelve esta lista.fuente
Java 10,
10096956761 bytes-4 bytes eliminando espacios porque esto está permitido en los comentarios
-1 byte cambiando
UTF-8
autf8
-28 bytes pasando de Java 7 a 8 (en
a->{...}
lugar devoid c(char[]i)throws Exception{...}
)-3 bytes tomando la entrada como String-array en lugar de character-array, y
-3 bytes pasando de Java 8 a 10 (en
var
lugar deString
)Explicación:
Pruébalo en línea.
fuente
Julia, 34 bytes
Esta es una función anónima que acepta una cadena y devuelve una matriz entera. Para llamarlo, asígnelo a una variable.
El enfoque es bastante sencillo: si la entrada está vacía, la salida está vacía. De lo contrario, asignamos la
sizeof
función, que cuenta el número de bytes en una cadena, a cada subcadena de un carácter.Pruébalo en línea! (incluye todos los casos de prueba)
fuente
s->[sizeof("$c")for c=s]
Guarda algunos bytes.split("","")
no volver[]
? (JavaScript"".split("")
sí.)split("","")
parece dar""
(a diferencia de Python que da una excepción) pero no sé nada sobre la compatibilidad de[]
y""
en julia.split("", "") == [""]
es decir, una matriz de un elemento que contiene una cadena vacía, pero el problema es quesizeof("") == 0
el OP dijo que no está permitido.PHP,
9257 bytesPensándolo bien, puedes hacer esto con mucho menos engaño:
Pruébelo en línea, tenga en cuenta que esto es un poco más largo ya que utiliza stdin en lugar de un argumento de programa.
Esta versión requiere que ignore los avisos enviados a stderr, pero está bien .
versión anterior:
utiliza un enfoque bastante diferente a la otra respuesta php. Se basa en la falta de soporte nativo para cadenas de varios bytes en php.
fuente
<?=
Emacs Lisp,
5549 bytesPrimero disecciona la cadena en una lista de caracteres con
(mapcar 'string s)
. Lastring
función en Emacs Lisp toma una lista de caracteres y construye una cadena a partir de ellos. Debido a la forma en que Emacs divide cadenasmapcar
(es decir, en una lista de enteros, no caracteres o cadenas), esta conversión explícita es necesaria. Luego asigna lastring-bytes
función a esa lista de cadenas.Ejemplo:
Casos de prueba:
Vieja respuesta:Sin golf:
Casos de prueba:
fuente
nil
si aplana el resultado?nil
es una lista vacía (y la única forma de decir "falso" en Emacs). Si bien no hay un aplanamiento estándar en Emacs (puede usar guiones-flatten
), cualquier implementación posible lo eliminaría.JavaScript (nodo), 27 bytes
Esto toma la entrada como una matriz de caracteres individuales y devuelve una matriz de recuentos de bytes.
Buffer
es un método para representar datos binarios sin procesar. Buffer.byteLength (cadena) da el número de bytes en la cadena. UTF-8 es la codificación predeterminada. Tenga en cuenta que solo Node.js tiene buffers, no el navegador JS. El equivalente aproximado del navegador se llama Blob , que viene en 31 bytes:Prueba
Guarde este archivo y ejecútelo a través del nodo, o pruébelo en línea .
Este debería ser el resultado:
fuente
Bash, 74 bytes
Golfed
Algoritmo
cadena de entrada hexdump, doble 2 caracteres por línea, corte solo el primer carácter
(4 bits de orden superior de cada byte de entrada como un carácter hexadecimal, uno por línea)
Eliminar "bytes de continuación" 0x80..0xBF
(lo que queda son 4 bits del primer byte de cada carácter unicode)
mapear los primeros bits en la longitud del carácter, contraer la salida e imprimir
Prueba
fuente
-t
opción atr
no me era familiar, y aparentemente es una extensión de GNU. La canalización a la sustitución de comandos despuésecho
también podría valer una explicación un poco más detallada.PHP, 126 bytes
Pruébalo en línea!
fuente
<?=($s=fgets(STDIN))?
DO#,
8982 bytesUna simple lambda de C # que itera a través de la cadena y devuelve la lista separada por espacios.
Editar: guardado 6 bytes gracias a algunos comentarios muy agradables.
fuente
var J="";...
1121
y1 2 1 2
ambos están bien} return J;};
using System.Text
o por ahí: las importaciones no son gratuitas.Haskell, 85 bytes
fuente
map$...
Pyth, 17 bytes
Pruébalo en línea!
Use el punto de código de los personajes con algunas aritméticas.
fuente
C, 85 bytes.
Examina los 4 bits altos de cada byte para determinar la codificación y el número de bytes subsiguientes que se omitirán;
fuente
while *c
salidas en una cadena vacía, y el 'c + = d' omite nulos en el medio de un punto de código de múltiples bytes.char*
, realmente) en C está marcado con un byte nulo. Es imposible distinguir los bytes nulos del final real de la cadena.Factor,
57878280 bytesExplicado:
Pruebas unitarias:
Todos pasan, ahora. do:
fuente
Swift 2.2,
675250 bytesHorriblemente feo. No hay forma de obtener la longitud UTF-8 de un personaje en Swift, así que necesito iterar a través de la cadena por carácter, convertir el
Character
a aString
y encontrar elcount
de ese carácter únicoString
(hey, al menos hay un incorporado) método para hacer eso). Buscando optimizaciones, posiblemente usando un escáner.Revisión 1: se guardaron 15 bytes utilizando en
count
lugar deunderestimateCount()
.Revisiones 2: guardó otros 2 caracteres mediante el uso de un bucle for-in en lugar de un para cada cierre.
fuente
Óxido, 53 bytes
Rust tiene primitivas de caracteres utf-8, iteradores y lambdas, por lo que esto fue sencillo. Código de prueba:
Salidas
fuente
jq, 26 caracteres
(Código de 23 caracteres + opción de línea de comando de 3 caracteres)
Con suerte compitiendo. Aunque
utf8bytelength
era agregó 9 ++ meses antes de esta pregunta, todavía no se incluye en la versión lanzada.Ejecución de muestra:
fuente
C (gcc) , 53 bytes
Pruébalo en línea!
fuente
SmileBASIC, 69 bytes
La entrada es una matriz de bytes.
El número de bytes en un carácter UTF-8 es igual al número de
1
bits iniciales en el primer byte (a menos que no haya1
s, en cuyo caso el carácter es 1 byte). Para encontrar el número de 1 principales, el programa encuentra el primero0
en la representación binaria, luego agrega 1 si fue 0.fuente
F #,
595466 bytesTécnicamente, s es una secuencia de caracteres, pero resulta que hay una conversión implícita que permite pasar una cadena.
Al probar esto en la consola con
!±≡𩸽
, divide el kanji en dos caracteres, cada uno de 3 bytes de longitud. Todos los demás casos de prueba funcionan bien.Editar: Resulta que las importaciones de espacios de nombres comunes no están implícitas. Hasta otros 12 caracteres.
fuente
UTF-8 without BOM
entonces esto es incorrecto y debería repararse . 3) Parece que F # necesita declaraciones comolet f(x)= ...
para terminar;;
, como SML. 4) Puede dejar de asignar un nombre a esta función anónima, es decir(s)=seq{for c in s->Encoding.UTF8.GetByteCount([|c|])}
.error FS0039: The namespace or module 'Encoding' is not defined
cuando intento ejecutar esto. ¿Qué estoy haciendo mal?System.Text
espacio de nombres. Supongo que se abre el espacio de nombres y se incluye el código de entrada, proveniente de la respuesta de C # de AstroDan.import
,#include
,open
,load
,require
,using
,USING:
etc aquí en PPCG. La respuesta de C # de AstroDan es igualmente errónea, y se lo notifiqué.05AB1E , 15 bytes
Pruébalo en línea.
El encabezado
ε
se utiliza para cada uno de los casos de prueba;Pie
ï]J]»
depáginapara imprimir bonitas las listas de caracteres de salida (ï
: decimales y caracteres a enteros;:]
cierre if-else y for-eachJ
;: unir dígitos juntos}
;: cerrar encabezado foreach;»
unirse por nuevas líneas).Explicación:
Como 05AB1E no tiene ninguna función incorporada para convertir caracteres a la cantidad de bytes utilizados, utilizo
Ç
para convertir los caracteres a sus valores unicode, y para cada uno, haga lo siguiente en pseudocódigo:Inspirado por la respuesta de Python 3 de @TheBikingViking .
fuente
Zsh , 41 bytes
Pruébalo en línea!
Zsh es compatible con UTF-8, por lo que dividimos la cadena en los caracteres, luego deshabilitamos multibyte e imprimimos la longitud de cada carácter.
fuente