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