2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

javascriptで連長圧縮してみた。

Last updated at Posted at 2020-03-09

今回はJavaScriptを使って

“連長圧縮”
というアルゴリズムを作ってみました。(別名:ランレングス圧縮)

(*プログラムの全貌はコチラ(GitHub)

###そもそも連長圧縮って何???

(*詳しく理解したい!という方はコチラをご覧ください。)

簡単に言うと、ある文字列について、

連続する文字を数えてその個数と文字だけに置き換えて圧縮する
というものです。

。。。。。。。

「そう言われましても…」
そう思われているでしょうか。はい、僕もはじめは何言っているか分かりませんでした。笑

#####まずは例を見せたいと思います。
下の図では、「AAABBBBBCDEEFG」を入力しています。
その下のバーに出ている「3A5B-2CD2E-2FG」が圧縮された出力になります。
2020-03-09 (1).png
連続する文字の時はその連続する回数と文字自体の2文字で表現します。
(ex. AAA→3A)
不連続の文字はマイナス符号をつけた上で不連続文字の個数と文字列自体で表現します。
(ex. CDEFG→―5CDEFG)

つまり、

元の文字列に連続する文字が多ければ多いほど、圧縮率が高くなります。

ちなみに、上のスクショのHTML/CSSファイルもGitHubで公開していますので、良かったダウンロードして試してみて下さい。

####圧縮のアルゴリズム(JavaScript)
引数の配列charDataには1文字ずつ文字データが格納されています。

Rentyo.js
function doCompress(charData){ //連長圧縮
    var compressedText=[]; //圧縮した結果を格納する場所
    var contiCounter = 0; //連続する文字の回数
    var nonContiText=[]; //不連続の文字を格納する場所。
    var nonContiCounter = 0; //不連続文字の回数
    var currentChar = charData[0]; //探索する際の文字のポインタ的なもの

    for(i=0;i<charData.length;i++){
        if(currentChar==charData[i]){
            if(nonContiCounter>0){ //XYYの最後のY部分に当たる出力処理
                minusNumber = nonContiCounter * (-1);
                compressedText.push(minusNumber);
                for(j=0;j<nonContiText.length;j++){
                    compressedText.push(nonContiText[j]);
                }
                nonContiText = [];
                nonContiCounter = 0;
            }
            contiCounter++;
        }else{
            if(contiCounter>1){ //XXYの最後のYの部分に当たる出力処理
                compressedText.push(contiCounter,currentChar);
            }
            if(contiCounter==1){
                nonContiCounter++;
                nonContiText.push(currentChar);
            }
            contiCounter = 1;
            currentChar = charData[i];
        }
    }

    if(contiCounter>1){
        compressedText.push(contiCounter,currentChar); //XXXのように末尾が連続だった場合の出力処理
    
    }else{ //XYZのように末尾が不連続だった場合の出力処理
        nonContiCounter++;
        minusNumber = nonContiCounter * (-1);
        nonContiText.push(currentChar);
        compressedText.push(minusNumber);
        for(k=0;k<nonContiText.length;k++){
            compressedText.push(nonContiText[k]);
        }
    }

    var resultText = compressedText.join(""); //配列を文字列に変換
    document.getElementById("show_result").textContent = "Compressed Result: " + resultText;

}

####注意すること
文字列の頭から処理を施していくと思いますが、ある文字列の圧縮出力が確定するのはそこから2文字あとになります。

(ex. XXY において 2X の出力が確定するのは、文字のポインタがYに来ているときになります。
 また XYYにおいて -1X の出力が確定するのはやはり2つ目のYを調べているときですね!)

したがって、頭から順に調べているだけでは末尾の文字の出力が確定しないので、別に末尾の文字についての処理を設けてあげます。

次回は今回のアンサー編をお送りしたいと思います(笑)
####次回は: javascriptで連長圧縮された文字列を解凍してみた。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?