Ich glaube, ich habe diese Frage hier schon einmal gesehen.
Zavior
6
@Oli Dafür sollte es einen Hut geben.
Sotirios Delimanolis
12
Fragen wie diese, die die Datenbank nicht verbessern, sondern nur als Clickbait existieren, sind ein sicherer Weg, um das Hat-Spiel in Zukunft abzubrechen. Bitte ruinieren Sie das Spiel nicht, indem Sie es huren.
Blazemonger
Antworten:
256
Die Zahl 4946144450195624passt auf 64 Bit, ihre binäre Darstellung lautet:
Das Programm decodiert ein Zeichen für jede 5-Bit-Gruppe von rechts nach links
00100|01100|10010|01111|10111|11111|01111|01100|01100|00101|01000
d | l | r | o | w | | o | l | l | e | h
5-Bit-Codierung
Für 5 Bits ist es möglich, 2⁵ = 32 Zeichen darzustellen. Das englische Alphabet enthält 26 Buchstaben, dies lässt Platz für 32 - 26 = 6 Symbole außer Buchstaben. Mit diesem Kodifizierungsschema können Sie alle 26 (ein Fall) englischen Buchstaben und 6 Symbole (Leerzeichen zwischen ihnen) haben.
Beschreibung des Algorithmus
Der >>= 5in der for-Schleife springt von Gruppe zu Gruppe, dann wird die 5-Bit-Gruppe isoliert UND die Zahl mit der Maske 31₁₀ = 11111₂im Satz UND-verknüpftl & 31
Jetzt ordnet der Code den 5-Bit-Wert dem entsprechenden 7-Bit-ASCII-Zeichen zu. Dies ist der schwierige Teil. Überprüfen Sie die binären Darstellungen für die Kleinbuchstaben in der folgenden Tabelle:
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
Hier können Sie sehen, dass die ASCII-Zeichen, die wir zuordnen möchten, mit dem 7. und 6. Bit set ( 11xxxxx₂) beginnen (mit Ausnahme des Leerzeichens, für das nur das 6. Bit aktiviert ist). Sie könnten ORdie 5-Bit-Codierung mit 96( 96₁₀ = 1100000₂) durchführen, und das sollte sein genug, um das Mapping durchzuführen, aber das würde für den Weltraum nicht funktionieren (verdammter Weltraum!)
Jetzt wissen wir, dass besondere Sorgfalt darauf verwendet werden muss, den Raum gleichzeitig mit den anderen Charakteren zu verarbeiten. Um dies zu erreichen, schaltet der Code das 7. Bit (aber nicht das 6.) der extrahierten 5-Bit-Gruppe mit einem ODER 64 64₁₀ = 1000000₂( l & 31 | 64) ein.
Bisher hat die 5-Bit-Gruppe die Form: 10xxxxx₂(Leerzeichen wäre 1011111₂ = 95₁₀). Wenn wir den Raum auf 0andere Werte abbilden können, können wir das 6. Bit einschalten, und das sollte alles sein. Hier ist, was die mod 95Rolle zu spielen kommt, Leerzeichen ist 1011111₂ = 95₁₀, bei Verwendung der Mod-Operation (l & 31 | 64) % 95)geht nur Leerzeichen zurück 0, und danach schaltet der Code das 6. Bit ein, indem er 32₁₀ = 100000₂
zum vorherigen Ergebnis addiert ((l & 31 | 64) % 95) + 32)und den 5-Bit-Wert in ein gültiges ASCII umwandelt Charakter
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
Der folgende Code führt den inversen Prozess aus, wobei bei einer Zeichenfolge in Kleinbuchstaben (max. 12 Zeichen) der 64-Bit-Wert zurückgegeben wird, der mit dem OP-Code verwendet werden kann:
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);}}
Sichtbare Standard-ASCII-Zeichen liegen im Bereich von 32 bis 127.
Deshalb sehen Sie dort 32 und 95 (127 - 32).
Tatsächlich wird jedes Zeichen hier auf 5 Bits abgebildet (Sie können die 5-Bit-Kombination für jedes Zeichen ermitteln), und dann werden alle Bits zu einer großen Zahl verkettet.
Positive Longs sind 63-Bit-Zahlen, die groß genug sind, um eine verschlüsselte Form von 12 Zeichen aufzunehmen. Es ist also groß genug, um es aufzunehmen Hello word, aber für größere Texte sollten Sie größere Zahlen oder sogar eine BigInteger verwenden.
In einer Anwendung wollten wir sichtbare englische Zeichen, persische Zeichen und Symbole per SMS übertragen. Wie Sie sehen, gibt es 32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127mögliche Werte, die mit 7 Bits dargestellt werden können.
Wir haben jedes UTF-8-Zeichen (16 Bit) in 7 Bit konvertiert und ein Komprimierungsverhältnis von mehr als 56% erzielt. So konnten wir Texte mit doppelter Länge in der gleichen Anzahl von SMS senden. (Es ist irgendwie das gleiche passiert hier).
Sie haben Zeichen als 5-Bit-Werte codiert und 11 davon in eine 64-Bit-Länge gepackt.
(packedValues >> 5*i) & 31 ist der i-te codierte Wert mit einem Bereich von 0 bis 31.
Der schwierige Teil ist, wie Sie sagen, die Codierung des Raums. Die englischen Kleinbuchstaben belegen den zusammenhängenden Bereich 97-122 in Unicode (und ASCII und den meisten anderen Codierungen), aber der Abstand beträgt 32.
Um dies zu überwinden, haben Sie eine Arithmetik verwendet. ((x+64)%95)+32ist fast dasselbe wie x + 96(beachten Sie, wie bitweise ODER in diesem Fall der Addition entspricht), aber wenn x = 31 ist, erhalten wir 32.
Sie sollten erklären, was Sie tun, anstatt ein weiteres Rätsel zu stellen
Aleksandr Dubinsky
1
Ich schlage vor, dass Sie einige Anstrengungen unternehmen, um eine Site zu finden (vielleicht Beta StackExchange?), Auf der es Spaß macht, lustige Rätsel zu lösen. Stack Overflow ist eine Q & A-Site mit einem streng erzwungenen Fokus.
Marko Topolnik
1
@MarkoTopolnik Ich würde es hassen, in einer Welt zu leben, in der alle Regeln oder Schwerpunkte so streng durchgesetzt wurden, dass keine Ausnahmen zugelassen wurden. Ganz zu schweigen davon, dass es bei SO unzählige solcher Ausnahmen gibt.
ברקן
1
Ich würde auch, aber SO ist eine solche Welt in ungewöhnlich großem Maße. Sicher gibt es auch hier Ausnahmen, aber sie sind nicht willkommen .
Marko Topolnik
1
Weitere 15 teilten Alexandrs Meinung. Und Sie weisen zu Recht darauf hin, dass die Frage selbst für SO ungeeignet ist, wie unten kommentiert.
Marko Topolnik
3
Ohne ein OracleTag war diese Frage schwer zu erkennen. Aktives Kopfgeld brachte mich hierher. Ich wünschte, die Frage hätte auch andere relevante Technologie-Tags :-(
Ich arbeite hauptsächlich mit Oracle database, also würde ich etwas OracleWissen verwenden, um zu interpretieren und zu erklären :-)
Lassen Sie uns die Zahl 4946144450195624in konvertieren binary. Dafür verwende ich ein kleines functionnamens dec2bin, dh decimal-to-binary .
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>
Verwenden wir die Funktion, um den Binärwert zu erhalten -
SQL> SELECT dec2bin(4946144450195624) FROM dual;
DEC2BIN(4946144450195624)--------------------------------------------------------------------------------10001100100100111110111111110111101100011000010101000
SQL>
Jetzt ist der Haken die 5-bitUmwandlung. Beginnen Sie mit der Gruppierung von rechts nach links mit 5 Ziffern in jeder Gruppe. Wir bekommen :-
Wir würden endlich nur noch 3 Ziffern haben, wenn er rechts endet. Weil wir insgesamt 53 Stellen in der Binärkonvertierung hatten.
SQL> SELECT LENGTH(dec2bin(4946144450195624)) FROM dual;
LENGTH(DEC2BIN(4946144450195624))---------------------------------53
SQL>
hello worldInsgesamt hat 11 Zeichen (einschließlich Leerzeichen), daher müssen wir der letzten Gruppe, in der wir nach der Gruppierung nur noch 3 Bits übrig hatten , 2 Bits hinzufügen .
Jetzt müssen wir es in einen 7-Bit-ASCII-Wert konvertieren. Für die Charaktere ist es einfach, wir müssen nur das 6. und 7. Bit setzen. Fügen Sie 11zu jeder 5-Bit-Gruppe oben links hinzu.
Lassen Sie uns die Binärwerte interpretieren, die ich verwenden werde 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>
Schauen wir uns jeden Binärwert an -
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>
Schauen wir uns an, welche Charaktere sie sind: -
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>
Also, was bekommen wir in der Ausgabe?
dlrow ⌂ olleh
Das ist Hallo Welt in umgekehrter Richtung. Das einzige Problem ist der Platz . Und der Grund wird von @higuaro in seiner Antwort gut erklärt. Ich konnte das Raumproblem ehrlich gesagt beim ersten Versuch nicht selbst interpretieren, bis ich die Erklärung in seiner Antwort sah.
Antworten:
Die Zahl
4946144450195624
passt auf 64 Bit, ihre binäre Darstellung lautet:Das Programm decodiert ein Zeichen für jede 5-Bit-Gruppe von rechts nach links
5-Bit-Codierung
Für 5 Bits ist es möglich, 2⁵ = 32 Zeichen darzustellen. Das englische Alphabet enthält 26 Buchstaben, dies lässt Platz für 32 - 26 = 6 Symbole außer Buchstaben. Mit diesem Kodifizierungsschema können Sie alle 26 (ein Fall) englischen Buchstaben und 6 Symbole (Leerzeichen zwischen ihnen) haben.
Beschreibung des Algorithmus
Der
>>= 5
in der for-Schleife springt von Gruppe zu Gruppe, dann wird die 5-Bit-Gruppe isoliert UND die Zahl mit der Maske31₁₀ = 11111₂
im Satz UND-verknüpftl & 31
Jetzt ordnet der Code den 5-Bit-Wert dem entsprechenden 7-Bit-ASCII-Zeichen zu. Dies ist der schwierige Teil. Überprüfen Sie die binären Darstellungen für die Kleinbuchstaben in der folgenden Tabelle:
Hier können Sie sehen, dass die ASCII-Zeichen, die wir zuordnen möchten, mit dem 7. und 6. Bit set (
11xxxxx₂
) beginnen (mit Ausnahme des Leerzeichens, für das nur das 6. Bit aktiviert ist). Sie könntenOR
die 5-Bit-Codierung mit96
(96₁₀ = 1100000₂
) durchführen, und das sollte sein genug, um das Mapping durchzuführen, aber das würde für den Weltraum nicht funktionieren (verdammter Weltraum!)Jetzt wissen wir, dass besondere Sorgfalt darauf verwendet werden muss, den Raum gleichzeitig mit den anderen Charakteren zu verarbeiten. Um dies zu erreichen, schaltet der Code das 7. Bit (aber nicht das 6.) der extrahierten 5-Bit-Gruppe mit einem ODER 64
64₁₀ = 1000000₂
(l & 31 | 64
) ein.Bisher hat die 5-Bit-Gruppe die Form:
10xxxxx₂
(Leerzeichen wäre1011111₂ = 95₁₀
). Wenn wir den Raum auf0
andere Werte abbilden können, können wir das 6. Bit einschalten, und das sollte alles sein. Hier ist, was diemod 95
Rolle zu spielen kommt, Leerzeichen ist1011111₂ = 95₁₀
, bei Verwendung der Mod-Operation(l & 31 | 64) % 95)
geht nur Leerzeichen zurück0
, und danach schaltet der Code das 6. Bit ein, indem er32₁₀ = 100000₂
zum vorherigen Ergebnis addiert((l & 31 | 64) % 95) + 32)
und den 5-Bit-Wert in ein gültiges ASCII umwandelt CharakterDer folgende Code führt den inversen Prozess aus, wobei bei einer Zeichenfolge in Kleinbuchstaben (max. 12 Zeichen) der 64-Bit-Wert zurückgegeben wird, der mit dem OP-Code verwendet werden kann:
quelle
Hinzufügen eines Werts zu den obigen Antworten. Das folgende groovige Skript druckt Zwischenwerte.
Hier ist es
quelle
Interessant!
Sichtbare Standard-ASCII-Zeichen liegen im Bereich von 32 bis 127.
Deshalb sehen Sie dort 32 und 95 (127 - 32).
Tatsächlich wird jedes Zeichen hier auf 5 Bits abgebildet (Sie können die 5-Bit-Kombination für jedes Zeichen ermitteln), und dann werden alle Bits zu einer großen Zahl verkettet.
Positive Longs sind 63-Bit-Zahlen, die groß genug sind, um eine verschlüsselte Form von 12 Zeichen aufzunehmen. Es ist also groß genug, um es aufzunehmen
Hello word
, aber für größere Texte sollten Sie größere Zahlen oder sogar eine BigInteger verwenden.In einer Anwendung wollten wir sichtbare englische Zeichen, persische Zeichen und Symbole per SMS übertragen. Wie Sie sehen, gibt es
32 (number of Persian chars) + 95 (number of English characters and standard visible symbols) = 127
mögliche Werte, die mit 7 Bits dargestellt werden können.Wir haben jedes UTF-8-Zeichen (16 Bit) in 7 Bit konvertiert und ein Komprimierungsverhältnis von mehr als 56% erzielt. So konnten wir Texte mit doppelter Länge in der gleichen Anzahl von SMS senden. (Es ist irgendwie das gleiche passiert hier).
quelle
| 64
tut.Sie erhalten ein Ergebnis, das zufällig die folgenden
char
Werte darstelltquelle
Sie haben Zeichen als 5-Bit-Werte codiert und 11 davon in eine 64-Bit-Länge gepackt.
(packedValues >> 5*i) & 31
ist der i-te codierte Wert mit einem Bereich von 0 bis 31.Der schwierige Teil ist, wie Sie sagen, die Codierung des Raums. Die englischen Kleinbuchstaben belegen den zusammenhängenden Bereich 97-122 in Unicode (und ASCII und den meisten anderen Codierungen), aber der Abstand beträgt 32.
Um dies zu überwinden, haben Sie eine Arithmetik verwendet.
((x+64)%95)+32
ist fast dasselbe wiex + 96
(beachten Sie, wie bitweise ODER in diesem Fall der Addition entspricht), aber wenn x = 31 ist, erhalten wir32
.quelle
Es druckt "Hallo Welt" aus einem ähnlichen Grund:
aber aus einem etwas anderen Grund als diesem:
quelle
Ohne ein
Oracle
Tag war diese Frage schwer zu erkennen. Aktives Kopfgeld brachte mich hierher. Ich wünschte, die Frage hätte auch andere relevante Technologie-Tags :-(Ich arbeite hauptsächlich mit
Oracle database
, also würde ich etwasOracle
Wissen verwenden, um zu interpretieren und zu erklären :-)Lassen Sie uns die Zahl
4946144450195624
in konvertierenbinary
. Dafür verwende ich ein kleinesfunction
namens dec2bin, dh decimal-to-binary .Verwenden wir die Funktion, um den Binärwert zu erhalten -
Jetzt ist der Haken die
5-bit
Umwandlung. Beginnen Sie mit der Gruppierung von rechts nach links mit 5 Ziffern in jeder Gruppe. Wir bekommen :-Wir würden endlich nur noch 3 Ziffern haben, wenn er rechts endet. Weil wir insgesamt 53 Stellen in der Binärkonvertierung hatten.
hello world
Insgesamt hat 11 Zeichen (einschließlich Leerzeichen), daher müssen wir der letzten Gruppe, in der wir nach der Gruppierung nur noch 3 Bits übrig hatten , 2 Bits hinzufügen .Also, jetzt haben wir: -
Jetzt müssen wir es in einen 7-Bit-ASCII-Wert konvertieren. Für die Charaktere ist es einfach, wir müssen nur das 6. und 7. Bit setzen. Fügen Sie
11
zu jeder 5-Bit-Gruppe oben links hinzu.Das gibt :-
Lassen Sie uns die Binärwerte interpretieren, die ich verwenden werde
binary to decimal conversion function
.Schauen wir uns jeden Binärwert an -
Schauen wir uns an, welche Charaktere sie sind: -
Also, was bekommen wir in der Ausgabe?
dlrow ⌂ olleh
Das ist Hallo Welt in umgekehrter Richtung. Das einzige Problem ist der Platz . Und der Grund wird von @higuaro in seiner Antwort gut erklärt. Ich konnte das Raumproblem ehrlich gesagt beim ersten Versuch nicht selbst interpretieren, bis ich die Erklärung in seiner Antwort sah.
quelle
Ich fand den Code etwas einfacher zu verstehen, wenn er in PHP übersetzt wurde, wie folgt:
Siehe Live-Code
quelle
out.println ((char) (((l & 31 | 64)% 95) + 32/1002439 * 1002439));
Um es zu verschließen: 3
quelle