Preguntas como esta, que no mejoran la base de datos pero existen únicamente como clickbait, son una forma segura de cancelar el juego Hat en el futuro. Por favor, no arruines el juego golpeándolo.
Blazemonger
Respuestas:
256
El número se 4946144450195624ajusta a 64 bits, su representación binaria es:
El programa decodifica un carácter para cada grupo de 5 bits, de derecha a izquierda
00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000
d | l | r | o | w | | o | l | l | e | h
Codificación de 5 bits
Para 5 bits, es posible representar 2⁵ = 32 caracteres. El alfabeto inglés contiene 26 letras, esto deja espacio para 32 - 26 = 6 símbolos aparte de las letras. Con este esquema de codificación, puede tener las 26 letras inglesas (un caso) y 6 símbolos (siendo el espacio entre ellos).
Descripción del algoritmo
En >>= 5el bucle for salta de un grupo a otro, luego el grupo de 5 bits se aísla ANDing el número con la máscara 31₁₀ = 11111₂en la oraciónl & 31
Ahora el código asigna el valor de 5 bits a su correspondiente carácter ascii de 7 bits. Esta es la parte difícil, verifique las representaciones binarias para las letras minúsculas del alfabeto en la siguiente tabla:
ascii | ascii | ascii | algorithm
character | decimal value | binary value | 5-bit codification
--------------------------------------------------------------
space | 32 | 0100000 | 11111
a | 97 | 1100001 | 00001
b | 98 | 1100010 | 00010
c | 99 | 1100011 | 00011
d | 100 | 1100100 | 00100
e | 101 | 1100101 | 00101
f | 102 | 1100110 | 00110
g | 103 | 1100111 | 00111
h | 104 | 1101000 | 01000
i | 105 | 1101001 | 01001
j | 106 | 1101010 | 01010
k | 107 | 1101011 | 01011
l | 108 | 1101100 | 01100
m | 109 | 1101101 | 01101
n | 110 | 1101110 | 01110
o | 111 | 1101111 | 01111
p | 112 | 1110000 | 10000
q | 113 | 1110001 | 10001
r | 114 | 1110010 | 10010
s | 115 | 1110011 | 10011
t | 116 | 1110100 | 10100
u | 117 | 1110101 | 10101
v | 118 | 1110110 | 10110
w | 119 | 1110111 | 10111
x | 120 | 1111000 | 11000
y | 121 | 1111001 | 11001
z | 122 | 1111010 | 11010
Aquí puede ver que los caracteres ascii que queremos mapear comienzan con el conjunto de 7 y 6 bits ( 11xxxxx₂) (excepto el espacio, que solo tiene el 6to bit activado ), puede ORcodificar con 5 bits con 96(96₁₀ = 1100000₂ ) y eso debería ser suficiente para hacer el mapeo, pero eso no funcionaría para el espacio (¡maldito espacio!)
Ahora sabemos que se debe tener especial cuidado al procesar el espacio al mismo tiempo que los otros personajes. Para lograr esto, el código activa el séptimo bit (pero no el sexto) en el grupo extraído de 5 bits con un OR 6464₁₀ = 1000000₂ ( l & 31 | 64).
Hasta ahora, el grupo de 5 bits tiene la forma: 10xxxxx₂(el espacio sería 1011111₂ = 95₁₀). Si podemos asignar espacio a 0otros valores que no afectan, entonces podemos activar el sexto bit y eso debería ser todo. Esto es lo que mod 95viene a jugar la parte, el espacio es 1011111₂ = 95₁₀, usando la operación de modulación (l & 31 | 64) % 95)solo vuelve el espacio 0, y después de esto, el código activa el sexto bit al agregarlo 32₁₀ = 100000₂
al resultado anterior,((l & 31 | 64) % 95) + 32) transformando el valor de 5 bits en un ascii válido personaje
isolates 5 bits --+ +---- takes 'space' (and only 'space') back to 0
| |
v v
(l & 31 | 64) % 95) + 32
^ ^
turns the | |
7th bit on ------+ +--- turns the 6th bit on
El siguiente código realiza el proceso inverso, dada una cadena en minúscula (máximo 12 caracteres), devuelve el valor de 64 bits que podría usarse con el código del OP:
publicclass D {publicstaticvoid main(String... args){String v ="hello test";int len =Math.min(12, v.length());long res =0L;for(int i =0; i < len; i++){long c =(long) v.charAt(i)&31;
res |=((((31- c)/31)*31)| c)<<5* i;}System.out.println(res);}}
Los caracteres ASCII estándar que están visibles están en el rango de 32 a 127.
Es por eso que ves 32 y 95 (127 - 32) allí.
De hecho, cada carácter se asigna a 5 bits aquí (puede encontrar la combinación de 5 bits para cada carácter), y luego todos los bits se concatenan para formar un gran número.
Los largos positivos son números de 63 bits, lo suficientemente grandes como para contener una forma cifrada de 12 caracteres. Por lo tanto, es lo suficientemente grande como para contenerlo Hello word, pero para textos más grandes usará números más grandes, o incluso un BigInteger.
En una aplicación, queríamos transferir caracteres visibles en inglés, caracteres persas y símbolos por SMS. Como puede ver, hay 32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127valores posibles, que se pueden representar con 7 bits.
Convertimos cada carácter UTF-8 (16 bits) a 7 bits, y ganamos más del 56% de relación de compresión. Entonces podríamos enviar mensajes de texto con el doble de longitud en la misma cantidad de SMS. (De alguna manera sucedió lo mismo aquí).
Ha codificado caracteres como valores de 5 bits y ha empaquetado 11 de ellos en una longitud de 64 bits.
(packedValues >> 5*i) & 31 es el i-ésimo valor codificado con un rango de 0-31.
La parte difícil, como dices, es codificar el espacio. Las letras inglesas en minúsculas ocupan el rango contiguo 97-122 en Unicode (y ascii, y la mayoría de las otras codificaciones), pero el espacio es 32.
Para superar esto, usaste algo de aritmética. ((x+64)%95)+32es casi lo mismo que x + 96(tenga en cuenta cómo OR a nivel de bits es equivalente a la suma, en este caso), pero cuando x = 31, obtenemos 32.
Deberías explicar lo que estás haciendo, en lugar de publicar otro acertijo
Aleksandr Dubinsky
1
Le sugiero que invierta un poco de esfuerzo en encontrar un sitio (¿tal vez un poco de Beta StackExchange?) Donde sea divertido contribuir con acertijos divertidos. Stack Overflow es un sitio de preguntas y respuestas con un enfoque estrictamente obligatorio.
Marko Topolnik el
1
@MarkoTopolnik Odiaría vivir en un mundo donde todas las reglas o el enfoque se aplicaran tan estrictamente como para nunca permitir excepciones. Sin mencionar que hay innumerables excepciones en SO.
עדלעד ברקן
1
Yo también lo haría, pero SO es un mundo tan excepcional. Claro que hay excepciones incluso aquí, pero no son bienvenidas .
Marko Topolnik
1
Otros 15 compartieron el sentimiento de Alexandr. Y tiene razón al señalar que la pregunta en sí misma es inapropiada para SO, como se comenta a continuación.
Marko Topolnik
3
Sin una Oracleetiqueta, era difícil ver esta pregunta. La generosidad activa me trajo aquí. Ojalá la pregunta tuviera otras etiquetas tecnológicas relevantes también :-(
Principalmente trabajo con ellos Oracle database, así que usaría algunos Oracleconocimientos para interpretar y explicar :-)
Vamos a convertir el número 4946144450195624a binary. Para eso utilizo un pequeño functionllamado dec2bin, es decir, decimal a binario .
SQL> CREATE OR REPLACE FUNCTION dec2bin (N in number) RETURN varchar2 IS
2 binval varchar2(64);3 N2 number := N;4 BEGIN
5while( N2 >0) loop
6 binval := mod(N2,2)|| binval;7 N2 := trunc( N2 /2);8 end loop;9return binval;10 END dec2bin;11/Function created.
SQL> show errors
No errors.
SQL>
Usemos la función para obtener el valor binario:
SQL> SELECT dec2bin(4946144450195624) FROM dual;
DEC2BIN(4946144450195624)--------------------------------------------------------------------------------10001100100100111110111111110111101100011000010101000
SQL>
Ahora el truco es la 5-bitconversión. Comience a agrupar de derecha a izquierda con 5 dígitos en cada grupo. Obtenemos :-
Finalmente nos quedarían con solo 3 dígitos en el final a la derecha. Porque, tuvimos un total de 53 dígitos en la conversión binaria.
SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual;
LENGTH(DEC2BIN(4946144450195624))---------------------------------53
SQL>
hello worldel total tiene 11 caracteres (incluido el espacio), por lo que debemos agregar 2 bits al último grupo donde nos quedamos con solo 3 bits después de la agrupación.
Ahora, necesitamos convertirlo a un valor ascii de 7 bits. Para los personajes es fácil, solo necesitamos establecer el 6to y 7mo bit. Agregue 11a cada grupo de 5 bits arriba a la izquierda.
Interpretemos los valores binarios que usaré binary to decimal conversion function.
SQL> CREATE OR REPLACE FUNCTION bin2dec (binval in char) RETURN number IS
2 i number;3 digits number;4 result number :=0;5 current_digit char(1);6 current_digit_dec number;7 BEGIN
8 digits := length(binval);9for i in 1..digits loop
10 current_digit := SUBSTR(binval, i,1);11 current_digit_dec := to_number(current_digit);12 result :=(result *2)+ current_digit_dec;13 end loop;14return result;15 END bin2dec;16/Function created.
SQL> show errors;No errors.
SQL>
Veamos cada valor binario:
SQL> set linesize 1000
SQL>
SQL> SELECT bin2dec('1100100') val,2 bin2dec('1101100') val,3 bin2dec('1110010') val,4 bin2dec('1101111') val,5 bin2dec('1110111') val,6 bin2dec('1111111') val,7 bin2dec('1101111') val,8 bin2dec('1101100') val,9 bin2dec('1101100') val,10 bin2dec('1100101') val,11 bin2dec('1101000') val
12 FROM dual;
VAL VAL VAL VAL VAL VAL VAL VAL VAL VAL VAL
--------------------------------------------------------------------------------------------------------------100108114111119127111108108101104
SQL>
Veamos qué personajes son: -
SQL> SELECT chr(bin2dec('1100100')) character,2 chr(bin2dec('1101100')) character,3 chr(bin2dec('1110010')) character,4 chr(bin2dec('1101111')) character,5 chr(bin2dec('1110111')) character,6 chr(bin2dec('1111111')) character,7 chr(bin2dec('1101111')) character,8 chr(bin2dec('1101100')) character,9 chr(bin2dec('1101100')) character,10 chr(bin2dec('1100101')) character,11 chr(bin2dec('1101000')) character
12 FROM dual;
CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER CHARACTER
---------------------------------------------------------------------------------------------------
d l r o w ⌂ o l l e h
SQL>
Entonces, ¿qué obtenemos en la salida?
dlrow ⌂ olleh
Eso es hello⌂world a la inversa. El único problema es el espacio . Y la razón está bien explicada por @higuaro en su respuesta. Sinceramente, no pude interpretar el problema espacial por mí mismo en el primer intento, hasta que vi la explicación dada en su respuesta.
Respuestas:
El número se
4946144450195624
ajusta a 64 bits, su representación binaria es:El programa decodifica un carácter para cada grupo de 5 bits, de derecha a izquierda
Codificación de 5 bits
Para 5 bits, es posible representar 2⁵ = 32 caracteres. El alfabeto inglés contiene 26 letras, esto deja espacio para 32 - 26 = 6 símbolos aparte de las letras. Con este esquema de codificación, puede tener las 26 letras inglesas (un caso) y 6 símbolos (siendo el espacio entre ellos).
Descripción del algoritmo
En
>>= 5
el bucle for salta de un grupo a otro, luego el grupo de 5 bits se aísla ANDing el número con la máscara31₁₀ = 11111₂
en la oraciónl & 31
Ahora el código asigna el valor de 5 bits a su correspondiente carácter ascii de 7 bits. Esta es la parte difícil, verifique las representaciones binarias para las letras minúsculas del alfabeto en la siguiente tabla:
Aquí puede ver que los caracteres ascii que queremos mapear comienzan con el conjunto de 7 y 6 bits (
11xxxxx₂
) (excepto el espacio, que solo tiene el 6to bit activado ), puedeOR
codificar con 5 bits con96
(96₁₀ = 1100000₂
) y eso debería ser suficiente para hacer el mapeo, pero eso no funcionaría para el espacio (¡maldito espacio!)Ahora sabemos que se debe tener especial cuidado al procesar el espacio al mismo tiempo que los otros personajes. Para lograr esto, el código activa el séptimo bit (pero no el sexto) en el grupo extraído de 5 bits con un OR 64
64₁₀ = 1000000₂
(l & 31 | 64
).Hasta ahora, el grupo de 5 bits tiene la forma:
10xxxxx₂
(el espacio sería1011111₂ = 95₁₀
). Si podemos asignar espacio a0
otros valores que no afectan, entonces podemos activar el sexto bit y eso debería ser todo. Esto es lo quemod 95
viene a jugar la parte, el espacio es1011111₂ = 95₁₀
, usando la operación de modulación(l & 31 | 64) % 95)
solo vuelve el espacio0
, y después de esto, el código activa el sexto bit al agregarlo32₁₀ = 100000₂
al resultado anterior,((l & 31 | 64) % 95) + 32)
transformando el valor de 5 bits en un ascii válido personajeEl siguiente código realiza el proceso inverso, dada una cadena en minúscula (máximo 12 caracteres), devuelve el valor de 64 bits que podría usarse con el código del OP:
fuente
Agregar algo de valor a las respuestas anteriores. El siguiente script maravilloso imprime valores intermedios.
Aquí está
fuente
¡Interesante!
Los caracteres ASCII estándar que están visibles están en el rango de 32 a 127.
Es por eso que ves 32 y 95 (127 - 32) allí.
De hecho, cada carácter se asigna a 5 bits aquí (puede encontrar la combinación de 5 bits para cada carácter), y luego todos los bits se concatenan para formar un gran número.
Los largos positivos son números de 63 bits, lo suficientemente grandes como para contener una forma cifrada de 12 caracteres. Por lo tanto, es lo suficientemente grande como para contenerlo
Hello word
, pero para textos más grandes usará números más grandes, o incluso un BigInteger.En una aplicación, queríamos transferir caracteres visibles en inglés, caracteres persas y símbolos por SMS. Como puede ver, hay
32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127
valores posibles, que se pueden representar con 7 bits.Convertimos cada carácter UTF-8 (16 bits) a 7 bits, y ganamos más del 56% de relación de compresión. Entonces podríamos enviar mensajes de texto con el doble de longitud en la misma cantidad de SMS. (De alguna manera sucedió lo mismo aquí).
fuente
| 64
está haciendo.Obtendrá un resultado que
char
representa los valores inferioresfuente
Ha codificado caracteres como valores de 5 bits y ha empaquetado 11 de ellos en una longitud de 64 bits.
(packedValues >> 5*i) & 31
es el i-ésimo valor codificado con un rango de 0-31.La parte difícil, como dices, es codificar el espacio. Las letras inglesas en minúsculas ocupan el rango contiguo 97-122 en Unicode (y ascii, y la mayoría de las otras codificaciones), pero el espacio es 32.
Para superar esto, usaste algo de aritmética.
((x+64)%95)+32
es casi lo mismo quex + 96
(tenga en cuenta cómo OR a nivel de bits es equivalente a la suma, en este caso), pero cuando x = 31, obtenemos32
.fuente
Imprime "hola mundo" por una razón similar que esto hace:
pero por una razón algo diferente a esto:
fuente
Sin una
Oracle
etiqueta, era difícil ver esta pregunta. La generosidad activa me trajo aquí. Ojalá la pregunta tuviera otras etiquetas tecnológicas relevantes también :-(Principalmente trabajo con ellos
Oracle database
, así que usaría algunosOracle
conocimientos para interpretar y explicar :-)Vamos a convertir el número
4946144450195624
abinary
. Para eso utilizo un pequeñofunction
llamado dec2bin, es decir, decimal a binario .Usemos la función para obtener el valor binario:
Ahora el truco es la
5-bit
conversión. Comience a agrupar de derecha a izquierda con 5 dígitos en cada grupo. Obtenemos :-Finalmente nos quedarían con solo 3 dígitos en el final a la derecha. Porque, tuvimos un total de 53 dígitos en la conversión binaria.
hello world
el total tiene 11 caracteres (incluido el espacio), por lo que debemos agregar 2 bits al último grupo donde nos quedamos con solo 3 bits después de la agrupación.Entonces, ahora tenemos: -
Ahora, necesitamos convertirlo a un valor ascii de 7 bits. Para los personajes es fácil, solo necesitamos establecer el 6to y 7mo bit. Agregue
11
a cada grupo de 5 bits arriba a la izquierda.Eso da :-
Interpretemos los valores binarios que usaré
binary to decimal conversion function
.Veamos cada valor binario:
Veamos qué personajes son: -
Entonces, ¿qué obtenemos en la salida?
dlrow ⌂ olleh
Eso es hello⌂world a la inversa. El único problema es el espacio . Y la razón está bien explicada por @higuaro en su respuesta. Sinceramente, no pude interpretar el problema espacial por mí mismo en el primer intento, hasta que vi la explicación dada en su respuesta.
fuente
Encontré el código un poco más fácil de entender cuando se traduce a PHP, de la siguiente manera:
Ver código en vivo
fuente
out.println ((char) (((l & 31 | 64)% 95) + 32/1002439 * 1002439));
Para hacerlo mayúsculas: 3
fuente