LZMAとは
LZ法と二値Range符号を組み合わせた汎用圧縮programで、高い圧縮率を誇っていらっしゃいます。圧縮速度は控え目ですが、伸長速度は超特急です。
言わずと知れた7zip、RAR、FreeArc等の書庫製造噐で採用されています。つまりあまりにも高性能過ぎるかもしれないので、皆さん遠慮なくLZMAを酷使無双し、こき使いまくってLZMA中毒重症患者になりましょうって話な訳がありません。
decoder
都合上Base64形式で掲載。復号すればきっちり828bytesとなります(制御文字多数混在)。関数名はf
です。ちなみに大域変数 _
が存在します。
828 bytes版
Zm9yKGY9JzoxVjw8VVVlVC0tUyxuUik6UTUsUD4+Pk9oT04sY00yNTY7THArfmJLPmE/SmE9N0pJaz1IZm9yKEc7RztGKytdRTEpRDFELEN8fChCZihsLGRBdCx0PXZAMTYrH10sHh5hKh9kKSkdKHUsHDpyHDMsYSofGz1kGik7GT1jGChmWxdlPRY7ZDxMKRU9HGFNKT0+FD1iLGI9E2w9b1twRT0SPTERUzspEHVbYV0PHmEpPygOaWYoDGVsc2V7C3JldHVybiAJHmQpKzIsSQhSPW5VOHxzW2lFB2QrGisGZhcFKUcVBkEpBD5lO2IrGFQrKykGGD0FNh5kAyxOMjRCaFU9OAcZAhR7dmFyIGQ9AWYBdVswHhZkLzksZgEPQg8RMDI0GWMaKihOQ2MYPm5PMD8oaBgsDys9MjA0OC1kT1AwUShoLRhSLRgsDy0aT1BEAgljfSxxFGYcMCk/ZhxEPx9yHDgsRBsyNkQrOBs1Q3IBMSwWYUZhEAZmHGQrYxkJMVReZH0scz11LHQsdix3GiU5LGosbFIsbRFUL1BnEVQlUHAaPWE9MCxiLG89Wx5oETZ8Z1NVOCxpETgtaCxrRmgQZltoXT1bXQdGO2Q9cCZtLUQMBTAdewwWBTEeYSkpBTIOBTMOBTQOFmosaj10URZAURZ2LEgwLHYTZVEoSCEFNR0mJihJOTpDa0JIcRc5CDhWMRkLSHEXOAg3VjAsaj1ALHYTchc3HjYsNj5rP2stMlU2VjkyGQxiPjMpDHU9Yk8xTRMoMnxiJkRVU3UsZBE0PmMpR2w9YiszMS1jO3UDK2wZC0c7NDx1EE4RTT1uLU4zMVItPWgmU2MsBi1jAkdiKxpVNCxkETs0AxkMYjwwKQlvfX1HFks7axASb1tlRX0LbD1mWx8obE84LXd8KHAmZylVdykeZBE7DDc+YQQ7C0cWb1tLXRUMSGVPNyYxLGVVESwGGD1BfGsrMVU4KU1eawR9EmQtTGEtPTRKYVYwSjM6Nn19JztfPS9bAS0fQC1WXS8uZXhlYyhmKTspd2l0aChmLnNwbGl0KF8pKWY9am9pbihzaGlmdCgpKTtldmFsKGYp
2024.2.11更新 821 bytes版(関数1個削減)
Zm9yKGY9J3IoV2s9Vj4+PlVoVVQ8PFNTZVI6MVExLFAtLU8pOk5wK35iTWRVNSxMPmE/S2E9N0tKMjU2O0ktPUgrPUd8fChGZm9XRTtFO0QxKUMxQyxCKytdQXQsdD12QGZbHyxkHik7HWYoHGM9GzE2KxplPRljLBg7ZDxJKRddLBYWYSk/KBU9YixiPRRsPW9bcEE9ExZhKhpkKSkSPTERdVthXRBPOykPOlcYMx4qGg5pHAxlbHNlewtyZXR1cm4gCSxuPW5TOHxzW2lBCGRHZCsHHB8GKUUXBxxsHikFPmU7YkdjUisrKQc9GwY2FmQELFQyNEZoUz04CB0DPSh1LGEsYyk9Pnt2YXIgZD0CFlYcGDApPxwYQz8aVxg4LEMOMjZDKzgONUJrRzIsSgFmAnVbMBYZZC85LGYCEEYQETAyNB0bZCooVEIbYz5uVTA/KGg9GBBHMjA0OC1MME4oaEgYbkgYEEhMQwMJY30scgJQGWFEYQ8HHHUeK2MdCTFSXmR9LHM9dSx0LHYsdz1kJTksaixsLG4sbRFSLzUsZxFSJTUscD1kPWE9MCxiLG89WxZoETZ8Z09TOCxpETgtaCxrRGgPH2hdPVtdCEQ7ZD1wJm0tQwwGMBJ7DBkGMRZhKSkGMhUGMxUGNBUZaixqPXROGUBOGXYsVjAsdhRlTihWIQY1EiYmKEo5OkJrRhsfOQE4UTEdCxsfOAE3UTAsaj1ALHYUVx83FjYsNj5rP2stMlM2UTkyHQxiPjMpDHU9YlVQYxQoMnxiJkNTT3UeETQ+YylFbD1iKzMxLWM7dQQrbB0LRTs0PHUPVBEsG24tVDNQbkhoJk8YBy1jA0ViR2RTNB4ROzQEHQxiPDApCW99fUUZTTtrDxNvW2VBfQtsPR8aKGxVOC13fChwJmcpU3cpFmQROww3PmEFOwtFGW9bTV0XDFZlVTcmUGVTESwHPRscbB58aysxUzgpLGNeawV9E2QtSWFINEthUTBLMzo2fX0nO189L1sBLR9ALVddLy5leGVjKGYpOyl3aXRoKGYuc3BsaXQoXykpZj1qb2luKHNoaWZ0KCkpO2V2YWwoZik
2024.2.23更新818 bytes
Zm9yKGY9J3IoWGs9Vz4+PlZoVlU6MVQtLVMpOlJwK35iUWRWNSxQYixiPU8+YT9OYT03Tk0yNTY7TCxqPXRLLT1KKz1JfHwoSD0xRzw8RkdGZUVmb1hEO0Q7QzEpQjFCLEErK11AMSwfZlseLGQdKTscZigbZT0aMTYrGWM9GGMsFztkPEwpFl0sFRVhKT8oFGw9b1twQD0TFWEqGWQpKRI9dix2PU8RdVthXRBTOykPOlgXMx0qGQ5pGwxlbHNlewtyZXR1cm4gCSxuPW5GOHxzW2lACGRJZCsHGx4GKUQWBxtsHSkFPmU7YkljRmUrKykHPRgGNhVkBCxVMjRIaEY9OAgcAz0odSxhLGMpPT57dmFyIGQ9AhVXGxcwKT8bF0I/GVgXOCxCDjI2Qis4DjVBa0kyLE0BZgJ1WzAVGmQvOSxmAhBIEEcwMjQcGGQqKFVBGGM+blYwPyhoPRcQSTIwNDgtUDBSKGhKF25KFxBKUEIDCWN9LHICHxphQ2EPBxt1HStjHAlkXkV9LHM9dSx0LHYsdz1kJTksaixsLG4sbUUvNSxnRSU1LHA9ZD1hPTAsYixvPVsVaEc2fGdTRjgsaUc4LWgsa0NoDx5oXT1bXQhDO2Q9cCZtLUIMBjESewwGGlcwFWEpKQYyFAYzFAY0FBpqS1IadCx0PXZSZRFlUihXIQY1EiYmKE05OkFrSBgeOQE4VDEcCxgeOAE3VDBLLHQRWB43FTYsNj5rP2stMkY2VDkyHAxiPjMpDHU9YlYfGE8oMnxiJkJGU3UdRzQ+YylEbD1iKzMxLWM7dQQrbBwLRDs0PHUPVT0fGG4tVTMfbkpoJlMXBy1jA0RiSWRGNB1HOzQEHAxiPDApCW99fUQaUTtrDxNvW2VAfQtsPR4ZKGxWOC13fChwJmcpRncpFWRHOww3PmEFOwtEGm9bUV0WDFdlVjcmH2VGPR8HPRgbbB18aysxRjgpLGNeawV9E2QtTGFKNE5hVDBOMzo2fX0nO189L1sBLR9ALVhdLy5leGVjKGYpOyl3aXRoKGYuc3BsaXQoXykpZj1qb2luKHNoaWZ0KCkpO2V2YWwoZik
2024.3.18更新 815 bytes
Zm9yKGY9J3IoWWs9WD4+PldoV1Y6MVUtLVQpOlNwK35iUmRXNSxRYixiPVA+YT9PYT03T05hPTAsTTI1NjtMLT1LKz1KfHwoST0xSDw8R0hHZUZmb1lFO0U7RDEpQzFDLEIrK11BMSxAZlsfXSweKTsdZigcZT0bYywaMTYrGSxqPXQYYz0XLGQWO2Q8TCkVbD1vW3BBPRQ9dix2PVATVDspEh5hKhlkKSkRHmEpPygQOlkaMxYqGQ9pHA51W2FdDGVsc2V7C3JldHVybiAJLG49bkc4fHNbaUEIZEpkKwccHwYpRRUHHGwWKQU+ZTtiSmNHZSsrKQc9FwY2XRYELFYyNEloRz04CB0DPSh1LE1jKT0+e3ZhciBkPQIeWBxjKT8cGkM/GVkaOCxDDzI2Qys4DzVCa0oyLE4BZgIMLBtkLzksZgIMSQxIMDI0HRdkKihWQhdjPm5XMD8oaD0aDEoyMDQ4LVEwUyhoSxpuSxoMS1FDAwljfSxyAkAbYURhEgccdRYrYx0JZF5GfSxzPXUsdCx2LHc9ZCU5GCxsLG4sbUYvNSxnRiU1LHA9ZD1NYixvPVseaEg2fGdURzgsaUg4LWgsa0RoEh9oXT1bXQhEO2Q9cCZtLUMOBjERew4GG1gwHmEpKQYyEAYzEAY0EBtqGFMbdCx0PXZTZRNlUyhYIQY1ESYmKE45OkJrSRcfOQE4VTEdCxcfOAE3VTAYLHQTWR83HjYsNj5rP2stMkc2VTkyHQ5iPjMpDnU9YldAF1AoMnxiJkNHVHUWSDQ+YylFbD1iKzMxLWM7dQQrbB0LRTs0PHUSVj1AF24tVjNAbktoJlQaBy1jA0ViSmRHNBZIOzQEHQ5iPDApCW99fUUbUjtrEhRvW2VBfQtsPR8ZKGxXOC13fChwJmcpR3cpXRZIOw43PmEFOwtFG29bUl0VDlhlVzcmQGVHPUAHPRccbBZ8aysxRzgpLGNeawV9FGQtTGFLNE9hVTBPMzo2fX0nO189L1sBLR9ALVldLy5leGVjKGYpOyl3aXRoKGYuc3BsaXQoXykpZj1qb2luKHNoaWZ0KCkpO2V2YWwoZik
使用例
a=f([93,0,0,1,0,6,0,0,0,0,0,0,0,0,49,24,74,43,255,186,138,31,255,255,111,92]);
console.log(a,String.fromCharCode.apply(0,a))
第一引数に数値配列を渡せば良い。戻り値はArray Objectとなります。上記例では[98,97,110,97,110,97]
が返されています。String.fromCharCodeに渡された結果banana
という文字列が出現。
制約
本家LZMA decoderとは異なり、圧縮元の大きさや辞書長を読む機能はありません。従って圧縮時に-eos
optionが有効な形式にしておく必要があります(End of stream marker刻印)。
それから展開可能な大きさもArray Objectの限界値までとなります。
動作検証
See the Pen Untitled by xezz (@xezz) on CodePen.
無圧縮版のウス汚い整形ブツ
f = (u, a, c) => {
var d = u[0], e = d / 9,
f = (u, a, c) => {// 1 bit復号
var d = u[a] || (u[a] = 1024);
c = d * (h >>> 11), c = c > n >>> 0 ? (h = c, u[a] += 2048 - d >>> 5, 0) : (h -= c, n -= c, u[a] -= d >>> 5, 1), h >>> 24 || (h <<= 8, n = n << 8 | s[i++]);
return c
},
r = (u, a, c) => {// n bit復号
var d = 1,e = a;
for (; a--;) d += d + f(u, d + c);
return 1 << e ^ d
},
s = u, t, v, w = d % 9,
j, l, n, m = 1 << e / 5,
g = 1 << e % 5,
p = d = a = 0,
b, o = [],
h = 16 | g-- << 8,
i = 18 - h,k;
// modelとrange coder初期化
for (; h--;) f[h] = [], n = n << 8 | s[i++];
// main loop
for (;; d = p & m - 1)
if (f(f[1], a * 16 + d)) {
// 辞書から復元
if (f(f[e=k=0], a))
f(f[2], a) ? (f(f[3], a) ? (f(f[4], a) ? (e = j, j = t) : e = t, t = v) : e = v, v = b, b = e) : (k = !f(f[5], a * 16 + d)) && (a = 7 > a ? 9 : 11), k || (c = f[9], k = f(c, 0) ? f(c, 1) ? 16 + r(c, 8, 1) : r(c, 3, d * 16 + 261) + 8 : r(c, 3, d * 16 + 511), k+=2, a = 7 > a ? 8 : 11);
else {
// 一致長と距離
c = f[8], k = f(c, 0) ? f(c, 1) ? 16 + r(c, 8, 1) : r(c, 3, d * 16 + 261) + 8 : r(c, 3, d * 16 + 511), k+=2, a = 7 > a ? 7 : 10, j = t, t = v, v = b, b = r(f[7], 6, 6 > k ? k - 2 << 6 : 192);
if (b > 3)
if (u = b >>> 1, c = b, b = (2 | b & 1) << --u, d = 14 > c)
for (l = b + 31 - c; u > e; b += c << e++) d += d += c = f(f[6], d + l);
else {
for (; 4 < u--;) h >>>= 1, c = n - h >>> 31, n -= h & --c, d += d + -c, h >>> 24 || (h <<= 8, n = n << 8 | s[i++]);
for (b += d << 4, d = 1; 4 > e; b += c << e++) d += d += c = f(f[6], d);
if (b < 0) return o
}
}
for (e = p + ~b; k--;) l = o[p++] = o[e++]
} else {
// 1文字復元
l = f[16 + (l >>> 8 - w | (p & g) << w)], d = 1;
if (7 > a)
for (; d < 256;) d += d + f(l, d);
else {
for (e = o[p + ~b]; d < 256;)
if (k = e >>> 7 & 1, e <<= 1, d += d += c = f(l, d | k + 1 << 8), c ^ k)
for (; d < 256;) d += d + f(l, d)
}
l = o[p++] = d - 256;
a -= 4 > a ? a : 10 > a ? 3 : 6
}
}
よく見ると分かりますが、無駄な文字が幾つか混入しています。for
にvar
を入れて変数宣言してないのも気になる所ですが、これらを圧縮する上ではその方が良いのです(RegPackを改造した私家版で圧縮します)。
ついでにhtml+jsで974 bytes版も作ってみました(例によってBase64変換)。js1kでも通用する変態program。関数f
の仕様は微妙に変更。
PGlucHV0IHR5cGU9ZmlsZSBvbmlucHV0PSdmb3IoZj1gPj4+cWhxcEE9bToxay0tfyk6X3JyYXlabmV3IFlkcTUsWD5hP1dhPTdXVkwrfmJUMjU2O1MpKVFyKFAtPU4rPU18fChLPTFKPDxJSkllSGZvUEc7RztGMSlFMUUsRCsrXUMxLCRmWyNdLCJmKB9pHx5lPR1jLBwxNisbLGo9dBopOxljPRgsZBc7ZDxTKRZsPW9bTEM9FT12LHY9YixiPRR/OykTImEqG2RREiJhKT8oESh1LGE9MCxjKT0+EDpQHDMXKhsPHyMOdVthXQxlbHNlewtyZXR1cm4gCSxuPW5JOHxzW2lDCFlVaW50OEFaKAdkTWQrBilHFgYfbBcpBT5lO2JNY0llKyspBj0YDjZdFwQscDI0S2hJPTgIGQM9EHt2YXIgZD0CIm0fYyk/HxxFPxtQHDgsRQ8yNkUrOA81REFNMixWAWZpbGVzWzBdLmFaQnVmZmVQKS50aGVuKBBkLmhyZWY9c2VsZi5VUkwuY3JlYXRlT2JqZWN0VVJMKFlCbG9iKFsHHwd1USldURlmAgwsHWQvOSxmAgxLDEowMjQZGGQqKHBEGGM+bnEwPyhoPRwMTTIwNDgtWDBfKGhOHG5OHAxOWEUDCWN9LHICJB1hRmETBh91FytjGQlkXkh9LHM9dSx0LHYsdz1kJTkaLGwsbixCSC81LGdIJTUsTD1kPTAsYixvPVsiaEo2fGd/STgsaUo4LWgsQUZoEyNoXT1bXQhGO2Q9TCZCLUUeDjESex4OHW0wImFRDjIRDjMRDjQRHWoaXx10LHQ9dl9lFGVfKG0hDjUSJiYoVjk6REFLGCM5AThrMRkLGCM4ATdrMBosdBRQIzciNiw2PkE/QS0ySTZrOTIZHmI+MykedT1icSQYYixiPSgyfGImRUl/dRdKND5jKUdsPWIrMzEtYzt1BCtsGQtHOzQ8dRNwPSQYbi1wMyRuTmgmfxwGLWMDR2JNZEk0F0o7NAQZHmI8MCkJb319Rx1UO0ETFW9bZUN9C2w9IxsobHE4LXd8KEwmZylJdyldF0o7Hjc+YQU7C0cdb1tUXRYebWVxNyYkZUk9JAY9GB9sF3xBKzFJOCksY15BBX0VZC1TYU40V2FrMFczOjZ9fWA7Xz0vW14gISUtQkxPUlVbLV5hLWpsbm9yLX5dLy5leGVjKGYpOyl3aXRoKGYuc3BsaXQoXykpZj1qb2luKHNoaWZ0KCkpO2V2YWwoZiknPjxhIGlkPWQgZG93bmxvYWQ+REw
本家とほぼ完全互換版
圧縮時に-eos
が無効だった圧縮fileでも処理できるようにしたprogramも解き放っておきます。なぜ ほぼ かと言うと、64 bits浮動小数点数で計算している都合上、正常に復号できるFileの大きさは253 bytesまでだからです。ただしArray Objectの尺の限界を超えられません。
例によってBase64変換。元は845 bytes。使い方は前述の816 bytes版と同じ
Zm9yKGY9YDoxd2s9Wi0tWXIoWCk6Vz4+PlZoVlUyNTY7VGQ8VClTcCt+YlI+YT9RYT03UVBiLGI9T2RWNSxOLT1NPTFMPDxLTEtlSisrXUkxKUgxSCxHfHwoRj0wLEVmW0QsZENmb1hCQjsfKz0eMSwdKTscZigbYywaZT0ZMTYrGCxqPXQXYz0WXSwVbD1vW3BJPRQ9dix2PU8TWTspEhVhKhhkKSkRFWEpPygQOlgaM0MqGA9pGw51W2FdDGVsc2V7CyxuPW5LOHxzW2lJCWQeZCsIG0QHcmV0dXJuIAYpH1MIG2xDKQU+ZTtiHmNLZSsrKQg9Fgc2FWQELFUyNEZoSz04CRwDPSh1LGFFYyk9Pnt2YXIgZD0CFVobYyk/GxpIPxhYGjgsSA8yNkgrOA81R2seMixQAWYCDCwZZC85LGYCDEYMTDAyNBwWZCooVUcWYz5uVjA/KGg9GgweMjA0OC1OMFcoaE0abk0aDE1OSAMGY30scgIdGWE7H2ESCBt1QytjHAZkXkp9LHM9dSx0LHYscT1kJTkXLGwsbixtSi81LGdKJTUscD1hPWRFQUViLG89WxVoTDZ8Z1lLOCxpTB1rTDsfaBJEaF09W107H2k8MTg7KUEeaypzW2ktNl0JLGsqPVQfcDxBO2Q9cCZtLUgOBzERew4HGVowFWEpKQcyEAczEAc0EBlqF1cZdCx0PXZXZRNlVyhaIQc1ESYmKFA5OkdrRhZEOQE4dzEcCxZEOAE3dzAXLHQTWEQ3FTYsNj5rP2stMks2dzkyHA5iPjMpDnU9YlYdFk8oMnxiJkhLWXVDTDQ+YylCbD1iKzMxLWM7dQQrbBwLHzQ8dRJVPR0Wbi1VMx1uTWgmWRoILWMDQmIeZEs0Q0w7NAQcDmI8MCkGb319QhlSO2sSFG9bZUl9C2w9RBgobFY4LXF8KHAmZylLcSkVZEw7Djc+YQU7C0IZb1tSXTtTDlplVjcmHWVLPR0IPRYbbEN8aysxSzgpLGNeawV9FGQtVGFNNFFhdzBRMzo2fQZvfWA7Xz0vWwEtH0ItWnddLy5leGVjKGYpOyl3aXRoKGYuc3BsaXQoXykpZj1qb2luKHNoaWZ0KCkpO2V2YWwoZik
html+jsの単独動作版1003 bytes
PGlucHV0IHR5cGU9ZmlsZSBvbmlucHV0PSdmb3IoZj1gPj4+cWhxcEE9bToxay0tfyk6X3JyYXlabmV3IFlkcTUsWD5hP1dhPTdXVk8rfmJUKSlTcihRLT1QfHwoTj0xTTw8S01LZUo9MCxJMSlIMUgsRysrXUZmb1FFRTtEZltDXSwkKz0jMSwiZigfaR8eZT0dYywcMTYrGyxqPXQaKTsZYz0YLGQXbD1vW09GPRY9dix2PWIsYj0VMjU2OxR/OykTJGEqG2RTEiRhKT8oESh1LGFJYyk9PhA6URwzFyobDx9DDnVbYV0MZWxzZXsLLG49bks4fHNbaUYJWVVpbnQ4QVooCGQjZCsHcmV0dXJuIAYpRGQ8FCkHH2wXKQU+ZTtiI2NLZSsrKQc9GA42XRcELHAyNE5oSz04CRkDPRB7dmFyIGQ9AiRtH2MpPx8cSD8bURw4LEgPMjZIKzgPNUdBIzIsVgFmaWxlc1swXS5hWkJ1ZmZlUSkudGhlbigQZC5ocmVmPXNlbGYuVVJMLmNyZWF0ZU9iamVjdFVSTChZQmxvYihbCB8IdVMpXVMZZgIMLB1kLzksZgIMTgxNMDI0GRhkKihwRxhjPm5xMD8oaD0cDCMyMDQ4LVgwXyhoUBxuUBwMUFhIAwZjfSxyAiIdYTtEYRMHH3UXK2MZBmReSn0scz11LHQsdix3PWQlORosbCxuLEJKLzUsZ0olNSxPPWRJTEliLG89WyRoTTZ8Z39LOCxpTSJBTTtEaBNDaF09W107RGk8MTg7KUwjQSpzW2ktNl0JLEEqPRRETzxMO2Q9TyZCLUgeDjESex4OHW0wJGFTDjIRDjMRDjQRHWoaXx10LHQ9dl9lFWVfKG0hDjUSJiYoVjk6R0FOGEM5AThrMRkLGEM4ATdrMBosdBVRQzckNiw2PkE/QS0ySzZrOTIZHmI+MykedT1icSIYYixiPSgyfGImSEt/dRdNND5jKUVsPWIrMzEtYzt1BCtsGQtENDx1E3A9IhhuLXAzIm5QaCZ/HActYwNFYiNkSzQXTTs0BBkeYjwwKQZvfX1FHVQ7QRMWb1tlRn0LbD1DGyhscTgtd3woTyZnKUt3KV0XTTseNz5hBTsLRR1vW1RdO2Q8FCkebWVxNyYiZUs9Igc9GB9sF3xBKzFLOCksY15BBX0WZC0UYVA0V2FrMFczOjZ9Bm99YDtfPS9bXiAhJS1CTE9SVVstXmEtamxub3Itfl0vLmV4ZWMoZik7KXdpdGgoZi5zcGxpdChfKSlmPWpvaW4oc2hpZnQoKSk7ZXZhbChmKSc+PGEgaWQ9ZCBkb3dubG9hZD5ETA
実演
See the Pen LZMA decoder(2) by xezz (@xezz) on CodePen.