cmp ← {cmp←1} ##.packD data ⍝ Pack char array to boolean vector.
Supplied by Veli-Matti Jantunen, this packer uses the same algorithm as packQ,
but the result is a simple boolean vector.
The algorithm is based on replacing the unique values with boolean sequences
that start with ones and end with zeros:
the most common element is replaced with 1 0
the next two with 1 0 0 and 1 1 0
the following with 1 0 0 0, 1 1 0 0 and 1 1 1 0
and so on.
The packing is efficient, if the data contains few unique elements and some of
them are used widely; normal text documents and APL code seem to pack nicely.
Because it is a boolean vector, we may decrypt the result in several ways:
encrypt decrypt
{~⍵} {~⍵}
{⌽⍵} {⌽⍵}
{⍺⌽⍵} {(-⍺)⌽⍵}
{⍵≠(⍴⍵)⍴⍺} {⍵≠(⍴⍵)⍴⍺}
For example, the following operator uses some of the methods:
crypt←{
⍝| ⍺: character set (64 elements!)
⍝| ⍺⍺: 0 = decrypt, 1 = crypt
⍝| ⍵⍵: key (positive integer)
⍝| ⍵: text
⍺←⎕D,⎕A,'+-',lcase ⎕A ⍝ default character set.
⎕IO←0 ⋄ set←⍺ ⍝ works nicer in zero origin.
key←{((⌊2⍟⍵+1)⍴2)⊤⍵}⍵⍵ ⍝ binarise key.
cry←{ ⍝ encryption:
b←{(6×⌈(⍴⍵)÷6)↑⍵,6⍴1}packD ⍵ ⍝ pack, pad with 1's if needed.
c←b≠(⍴b)⍴key ⍝ poor man's xor encryption.
set[2⊥(6,(⍴c)÷6)⍴c] ⍝ result is gibberish.
}
yrc←{ ⍝ decryption:
c←,(6⍴2)⊤set⍳⍵ ⍝ encode indices.
0 packD{(-+/∧\⌽⍵)↓⍵}c≠(⍴c)⍴key ⍝ de-xor, unpack (n.b. remove last 1's)
}
0::⍵ ⋄ ⍺⍺=1:cry ⍵ ⋄ yrc ⍵
}
- This idea may be developed further, e.g. adding characters that are not used.
- Decryption with a wrong key may crash crypt (because the result shape may be
anything, say 723572108153 0 1783823 0 0 0 0 0).
Examples:
packD 'mississippi'
0 0 0 1 0 0 1 0 0 1 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 0 0 1
0 0 0 0 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 1 0 0 1 0 1 1 0
1 1 0 1 0
{⍵≡0 packD 1 packD ⍵}'Full Circle'
1
⎕←crypted←(1 crypt 313)'mississippi'
5Na1n4ia1qmLJK
'mississippi'≡(0 crypt 313)crypted
1
See also: Data_compression
Back to: contents
Back to: Workspaces