I have an array of array of numbers as data:
[[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360],
[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360]]
I can import this data into my app and load the state.
So I want to encode this into a URL so it's easier to share.
What is the most size efficient way to encode this data into a URL.
Also acceptable is any reliable third party services that I can save/load my state from, like github gist or something.
CodePudding user response:
Ok, so base64 is not for compression. But I just (re)invented a compression method and base64 is part of it. It compress to about 65% indeed. The idea is to compress each pair of digits to a 2 digit hex number which is one ascii char. Then base64 it for safety.
var data = [
[0.3, 2.1, -0.04, 32, 0, 54],
[9, 593, 82, 593, 1360, 593, 82, 582, 1344, 4676, 1344, 593, 82, 593, 82, 578, 1344, 593, 82, 577, 1344, 593, 82, 567, 1328, 593, 82, 4662, 1328, 593, 82, 4662, 1328, 593, 82, 577, 1344, 593, 82, 4674, 1344, 582, 1344, 594, 1360, 4693, 1360, 599, 1360, 4705, 1376, 582, 1344, 581, 1344, 581, 1344, 4677, 1344, 4678, 1344, 593, 1360, 4690, 1360],
[9, 593, 82, 593, 1360, 593, 82, 582, 1344, 4676, 1344, 593, 82, 593, 82, 578, 1344, 593, 82, 577, 1344, 593, 82, 567, 1328, 593, 82, 4662, 1328, 593, 82, 4662, 1328, 593, 82, 577, 1344, 593, 82, 4674, 1344, 582, 1344, 594, 1360, 4693, 1360, 599, 1360, 4705, 1376, 582, 1344, 581, 1344, 581, 1344, 4677, 1344, 4678, 1344, 593, 1360, 4690, 1360],
];
function encode_char(c) {
if (c == '[') return 'a';
if (c == ']') return 'b';
if (c == ',') return 'c';
if (c == ' ') return 'd';
if (c == '.') return 'e';
if (c == '-') return 'f';
return "" c;
}
function decode_char(c) {
if (c == 'a') return '[';
if (c == 'b') return ']';
if (c == 'c') return ',';
if (c == 'd') return ' ';
if (c == 'e') return '.';
if (c == 'f') return '-';
return "" c;
}
function encode_string(str) {
var result = "";
var arr = str.split("");
if (arr.length % 2) {
arr.push(" ")
}
for (var i = 0; i < arr.length; i = 2) {
var c1 = encode_char(arr[i])
var c2 = encode_char(arr[i 1])
var hex = "" c1 c2
result = String.fromCharCode(parseInt(hex, 16));
}
return result;
}
function decode_string(str) {
var result = "";
var arr = str.split("");
for (var i = 0; i < arr.length; i = 1) {
var char = arr[i]
var hex = char.charCodeAt(0).toString(16);
hex = hex.length < 2 ? "0" hex : hex;
var c1 = decode_char(hex.slice(0, 1))
var c2 = decode_char(hex.slice(1, 2))
result = "" c1 c2
}
return result.trim();
}
function encode_integers(str) {
var result
result = encode_string(str);
result = btoa(result)
result = encodeURIComponent(result)
return result;
}
function decode_integers(str) {
var result
result = decodeURIComponent(str);
result = atob(result)
result = decode_string(result)
return result;
}
var json = JSON.stringify(data);
console.log(json.length, json)
var str = encode_integers(json);
console.log(str.length, str)
var json = decode_integers(str)
console.log(json.length, json)
console.log("compression ratio", (str.length / json.length).toFixed(2))
CodePudding user response:
You can use compression and decompression methods to reduce the size of the input by ~ 65% to encode it in the URL
first I stringify the input then encrypt it
I also attached the description method
You can also find more efficient compression algorithms than this.
ex:
e1 <== slightly more efficient than the one I wrote
e2 <== gzip implementation
const input = [[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360],
[9,593,82,593,1360,593,82,582,1344,4676,1344,593,82,593,82,578,1344,593,82,577,1344,593,82,567,1328,593,82,4662,1328,593,82,4662,1328,593,82,577,1344,593,82,4674,1344,582,1344,594,1360,4693,1360,599,1360,4705,1376,582,1344,581,1344,581,1344,4677,1344,4678,1344,593,1360,4690,1360]]
let firstStep = JSON.stringify(input)
let secondStep = en(firstStep);
console.log("The original input lost: " (1-(secondStep.length / firstStep.length)) " % of it's size"); // this is data encription ratio
// decrept
console.log("decrypted: " de(secondStep))
function en(c){var x='charCodeAt',b,e={},f=c.split(""),d=[],a=f[0],g=256;for(b=1;b<f.length;b )c=f[b],null!=e[a c]?a =c:(d.push(1<a.length?e[a]:a[x](0)),e[a c]=g,g ,a=c);d.push(1<a.length?e[a]:a[x](0));for(b=0;b<d.length;b )d[b]=String.fromCharCode(d[b]);return d.join("")}
function de(b){var a,e={},d=b.split(""),c=f=d[0],g=[c],h=o=256;for(b=1;b<d.length;b )a=d[b].charCodeAt(0),a=h>a?d[b]:e[a]?e[a]:f c,g.push(a),c=a.charAt(0),e[o]=f c,o ,f=a;return g.join("")}