¡De lo contrario, resoplará y soplará y derribará tu casa!
Eso fue completamente irrelevante. Este desafío es en realidad sobre la codificación de Huffman . La esencia de esto es la frecuencia de caracteres en un texto dado que se utiliza para acortar su representación. En otras palabras, digamos que nuestro alfabeto es a a
través z
y el espacio. Eso es 27 personajes. Cada uno de ellos puede codificarse de forma única en solo 5 bits porque 5 bits tienen espacio suficiente para 32 caracteres. Sin embargo, en muchas situaciones (como el inglés o los idiomas en general), algunos caracteres son más frecuentes que otros. Podemos usar menos bits para los caracteres más frecuentes y (quizás) más bits para los caracteres menos frecuentes. Bien hecho, hay un ahorro general en el número de bits y el texto original aún puede reconstruirse de forma única.
Tomemos "esta pregunta es sobre la codificación de huffman" como ejemplo. Este texto tiene 37 caracteres, lo que normalmente sería 37 * 8 = 296 bits, aunque solo 37 * 5 = 185 bits si solo usamos 5 bits para cada carácter. Ten eso en mente.
Aquí hay una tabla (más o menos) de cada carácter y sus frecuencias en el texto, ordenada de más a menos frecuente (donde _ representa un espacio):
_ 5
i 4
n 3
o 3
s 3
t 3
u 3
a 2
f 2
h 2
b 1
c 1
d 1
e 1
g 1
m 1
q 1
Una codificación óptima asociada podría ser:
_ 101
i 011
n 1100
o 1101
s 1110
t 1111
u 001
a 10011
f 0001
h 0101
b 00000
c 00001
d 01000
e 01001
g 10000
m 10001
q 10010
Debe quedar claro de inmediato que esta será una mejor codificación que simplemente usar 5 bits para cada carácter. ¡Pero descubramos cuánto mejor!
145 bits , en comparación con 185! ¡Eso es un ahorro de 40 bits, o un poco más del 20%! (Por supuesto, esto supone que la información sobre la estructura está disponible para la decodificación). Esta codificación es óptima porque no se pueden eliminar más bits al cambiar la representación de cualquier carácter.
La tarea
- Escriba un programa o función con un parámetro que ...
- Toma información de STDIN (o equivalente) o como un solo argumento.
- Produzca una codificación Huffman óptima como la anterior con los caracteres ordenados por frecuencia (el orden dentro de una clase de frecuencia no importa).
- Puede suponer que los caracteres en la entrada están restringidos al rango ASCII
32..126
más una nueva línea. - Puede suponer que la entrada no tiene más de 10,000 caracteres (idealmente, en teoría, la entrada debe ser ilimitada).
- Su código debe terminar razonablemente rápido. El ejemplo anterior no debería tomar más de un minuto más o menos en el peor. (Esto tiene la intención de descartar la fuerza bruta).
- La puntuación está en bytes.
Ejemplos
x
---
x 0
xxxxxxxxx
---
x 0
xxxxxxxxy
---
x 0
y 1 (these may be swapped)
xxxxxyyyz
---
x 0
y 10
z 11
uuvvwwxxyyzz
--- (or)
u 000 000
v 001 001
w 100 010
x 101 011
y 01 10
z 11 11
this question is about huffman coding
---
101
i 011
n 1100
o 1101
s 1110
t 1111
u 001
a 10011
f 0001
h 0101
b 00000
c 00001
d 01000
e 01001
g 10000
m 10001
q 10010
¡Feliz codificación!
Tenga en cuenta que esta pregunta similar está estrechamente relacionada, incluso hasta el punto de que esta es un duplicado. Sin embargo, el consenso hasta ahora sobre Meta es que el más antiguo debe considerarse un duplicado de este.
fuente
this question is about huffman coding
, conté el número de bits como 145 , no 136.Respuestas:
Pyth, 53 bytes
Demostración
Aquí hay una versión que muestra el estado interno, para que pueda ver la codificación que se está creando:
Demostración
Copie la salida a un entorno con líneas más anchas para obtener una imagen más clara.
fuente
Python 2, 299 bytes
Aquí está mi intento de respuesta.
Los códigos de Huffman son diferentes de los ejemplos dados, pero aún así deberían ser óptimos.
fuente
Matlab, 116 bytes
tabulate
hace una tabla de frecuenciashuffmandict
toma una lista de símbolos y probabilidades para cada símbolo y calcula el código.fuente
Rubí,
189180 bytesTrabajo en progreso.
Es una función anónima; asignarlo a algo, por ejemplo
f
, y llamarlo conque devuelve un hash como este:
fuente
Haskell, 227 bytes
Ejemplo de uso:
Cómo funciona:
p
llamadasf
que construye la tabla Huffman en forma de una lista de pares (caracteres, codificación), por ejemplo[ ('a',"0"), ('b',"1") ]
, clasifica la tabla por longitud de codificaciones, formatea cada par para la salida y se une con nuevas líneas intermedias.f
primero comprueba el caso de una letra y devuelve la tabla correspondiente. De lo contrario, clasifica la cadena de entrada y agrupa secuencias de caracteres iguales (por ejemplo,"ababa"
->["aaa","bb"]
) y las asigna a pares(sequence , [(char, "")])
, (->[ ("aaa", [('a',"")]), ("bb", [('b', "")])]
. El primer elemento se utiliza para realizar un seguimiento de la frecuencia, el segundo elemento es una lista de pares de un carácter y está codificando (que inicialmente está vacío). Estas son todas las tablas de Huffman de elemento único como se esperabap
y están combinadas porg
yh
.g
ordena la lista de pares según la longitud del primer elemento, es decir, la frecuencia y las llamadash
.h
combina las tablas de Huffman de los dos primeros elementos, concatenando las frecuencias y poniendo un0
(1
) delante de cada elemento de la primera (segunda) tabla. Concatenar ambas tablas. Llama deg
nuevo, detente cuando quede un solo elemento, tira la parte de frecuencia y devuelve la tabla completa de Huffman.fuente
K (ngn / k) , 78 bytes
Pruébalo en línea!
devuelve una lista de cadenas para imprimir
h::0#'x
crea una lista vacía para cada carácter (técnicamente, da nueva forma a cada carácter a la longitud 0). almacenaremos los códigos invertidos de huffman allí. usamos en::
lugar de:
para la asignación para hacerh
global para que sea visible en subfunciones.=x
es una lista de listas: los índices de la cadena agrupados por valor de caracteres(#1_)
es una función que devuelve verdad si la longitud del argumento es> 1 (técnicamente "longitud de 1 gota de ...")(#1_){
...}/
significa: mientras el argumento tiene una longitud> 1, sigue aplicando la función de llavesx@<#'x
ordenar el argumento por longitud0 2_
cortarlo en una cabeza de 2 elementos y una cola{h[x],:!2;y,,,/x}
actualizarh
agregando 0 y 1 a los índices contenidos en el encabezado; devolver la cola con la cabeza como un elemento único(?,/'x,'" ",'|'$h)(?x)?>#'=x
invierte cada uno de losh
caracteres correspondientes, los ordena, los únicos y los antepone, y los formatea bienfuente
JavaScript (ES6) 279
Esencialmente, el algoritmo básico de Wikipedia. Probablemente pueda hacerlo mejor.
Más legible dentro del fragmento a continuación
fuente