Burrows–Wheeler transform written in the ABL

Cecil

19+ years progress programming and still learning.
I had no practical reason to write this code only because I thought it would be fun to to. I saw a recent Google YouTube video
and I decided to quickly try it out in the ABL. Here is what I came up with. Copy and Paste the code into a procedure editor and run it.

Code:
/**
The Burrows–Wheeler transform (BWT, also called block-sorting compression) rearranges a character string into runs of similar characters.
This is useful for compression, since it tends to be easy to compress a string that has runs of repeated characters by techniques such
as move-to-front transform and run-length encoding. More importantly, the transformation is reversible, without needing to store any
additional data. The BWT is thus a "free" method of improving the efficiency of text compression algorithms, costing only some extra
computation.
**/

DEFINE TEMP-TABLE ttRotation
    FIELD rowNumber   AS INTEGER
    FIELD rotation    AS CHARACTER
    INDEX idxRoration IS PRIMARY
        rotation
    INDEX idxRowNumber
        rowNUmber.

/** function to transform a string using Burrows–Wheeler transform **/
FUNCTION TransformString RETURNS CHARACTER (INPUT chSourceString AS CHARACTER,
                                            OUTPUT inIndex       AS INTEGER).
   
    DEFINE VARIABLE inLoop          AS INTEGER     NO-UNDO.
    DEFINE VARIABLE inSortLoop      AS INTEGER     NO-UNDO.
    DEFINE VARIABLE chPermString    AS CHARACTER   NO-UNDO.
    DEFINE VARIABLE chLastColumn    AS CHARACTER   NO-UNDO.

    EMPTY TEMP-TABLE ttRotation.
   
    ASSIGN
        chPermString = chSourceString.
   
    /** Create a temp-table record for each permintation of the strings length with
        the last character moved to the front of the string. **/
    DO inLoop = 1 TO LENGTH(chSourceString):
   
        CREATE ttRotation.
   
        ASSIGN
            ttRotation.rowNumber = inLoop
            ttRotation.rotation  = chPermString.
   
        chPermString = SUBSTRING(chPermString, LENGTH(chPermString) ) + SUBSTRING(chPermString,1, LENGTH(chPermString) - 1).
    END.
   
    /** Re-sort the temp-table records into lex order and
        re-assign the row number relative to the new order.**/

    inSortLoop = 0.
    FOR EACH ttRotation
        BY ttRotation.rotation:
   
        inSortLoop = inSortLoop + 1.
   
        ttRotation.rowNumber = inSortLoop.
       
        IF ttRotation.rotation EQ chSourceString THEN
            ININDEX = ttRotation.rowNumber.
   
        chLastColumn = chLastColumn + SUBSTRING(ttRotation.rotation, LENGTH(ttRotation.rotation) ).
    END.

    RETURN chLastColumn.

END FUNCTION.


/** Detransform the transformed string back into it's orignal value. **/
FUNCTION DETRANSFORMSTRING RETURNS CHARACTER (INPUT chLastColumn AS CHARACTER,
                                              INPUT ININDEX      AS INTEGER):

    DEFINE VARIABLE inSortLoop  AS INTEGER NO-UNDO.
    DEFINE VARIABLE inInnerLoop AS INTEGER NO-UNDO.
    DEFINE VARIABLE inLoop      AS INTEGER NO-UNDO.

    EMPTY TEMP-TABLE ttRotation.

    /** Create a new table row array ready for detransformation. **/
    DO inLoop = 1 TO LENGTH(chLastColumn):
        CREATE ttRotation.
        ASSIGN
            ttRotation.rowNumber = inLoop.
    END.
   
   
   
    DO inLoop = 1 TO LENGTH(chLastColumn):
   
        DO inInnerLoop = 1 TO LENGTH(chLastColumn):
            FIND ttRotation
                WHERE ttRotation.rowNumber EQ inInnerLoop
                NO-ERROR.
       
            ASSIGN   
                ttRotation.rotation = SUBSTRING(chLastColumn, inInnerLoop, 1) + ttRotation.rotation .
        END.
   
        inSortLoop = 0.
        FOR EACH ttRotation
            BY ttRotation.rotation:
   
            inSortLoop = inSortLoop + 1.
   
            ASSIGN
                ttRotation.rowNumber = inSortLoop.
        END.
    END.
   
    FIND ttRotation
        WHERE ttRotation.rowNumber EQ ININDEX
        NO-ERROR.

    RETURN ttRotation.rotation.
END.

/** Main Code**/
DEFINE VARIABLE chSourceString      AS CHARACTER   NO-UNDO.
DEFINE VARIABLE chTransformedString AS CHARACTER   NO-UNDO.
DEFINE VARIABLE inIndex             AS INTEGER     NO-UNDO.


MESSAGE
    'ENTER YOUR NAME'
    UPDATE
        chYourName AS CHARACTER FORMAT "x(32)" AUTO-RETURN.
   

ASSIGN
     chSourceString      = SUBSTITUTE('&1 loves Progress OpenEdge', chYourName).
     chTransformedString = TransformString(chSourceString, OUTPUT inIndex).

MESSAGE 'Source String:' SKIP QUOTER(chSourceString) SKIP(1)
        'Transformed String:' SKIP QUOTER(chTransformedString)  SKIP(1)
        'De-transformed String:' SKIP QUOTER(DETRANSFORMSTRING(chTransformedString, inIndex ))
    VIEW-AS ALERT-BOX INFO TITLE 'Burrows–Wheeler Transform Simple Demo'.
 
Top