文章を非可逆圧縮して容量削減を図る


みなさん、文章ファイルを圧縮する時、どの圧縮方式を採用してますか?

zip圧縮でしょうか?lzh圧縮でしょうか?

確かにそれらのアルゴリズムは非常に便利なものです。
しかしzipやlzhに代表される可逆圧縮方式には圧縮効率の面において限界があります。

  可逆圧縮 方式 非可逆圧縮 方式
圧縮の効率
元データの復元 ×

そこで、文章ファイルの非可逆圧縮を試みてみます。

cmprss

というわけで、文章を非可逆圧縮するコマンドを作りました。

 

cmprss
https://github.com/kurehajime/cmprss

 

例えば、「hello world!」という文字列をcmprssに通すと・・・


$ echo hello world! | cmprss

HlloWrld!

HlloWrld!

見事に圧縮されました。
元に戻すには?・・・戻せません。非可逆圧縮ですから!

ちゃんとテキストファイルも圧縮できます。


$ cmprss ThinkDifferent.txt

Hre’sToTheCrzyOns.TheMsfts.TheRbls.TheTroublmkrs.TheRoundPgsInTheSquareHls.
TheOnsWhoSeeThngsDffrntly.Thy’reNotFndOfRls.AndThyHveNoRspctForTheSttsQuo.
YouCanQuoteThm,DsgreeWthThm,GlrfyOrVlfyThm.
AboutTheOnlyThngYouCn’tDoIsIgnreThm.BcauseThyChngeThngs.ThyInvnt.ThyImgne.
ThyHeal.ThyExplre.ThyCreate.ThyInspre.ThyPshTheHmnRceFrwrd.
MybeThyHveToBeCrzy.
HowElseCanYouStreAtAnEmptyCnvsAndSeeAWrkOfArt?OrSitInSlnceAnd
HearASngTht’sNvrBeenWrttn?OrGzeAtARedPlntAndSeeALbrtryOnWheels?
WeMkeToolsForThseKndsOfPeople.
WhleSmeSeeThmAsTheCrzyOns,WeSeeGnius.BcauseThePeopleWhoAreCrzyEnough
ToThnkThyCanChngeTheWrld,AreTheOnsWhoDo.


なんとなく何が書いてあるかわかりますよね?
スティーブジョブズの声で脳内再生されますよね?

kwsk

このプログラムでは以下のような処理を施して文章を圧縮しています。

  • 子音に挟まれた母音は省略する。
  • 2文字以上連続する母音は省略しない。
  • 3文字以下の単語は省略しない。
  • 大文字は省略しない。
  • 文章中のスペースを省略し、すべての単語の頭を大文字にする。

子音に挟まれた母音は省略する。

message → Mssge
Markdown → Mrkdwn
Yahweh → Yhwh

子音に挟まれた母音はバッサリ省略します。
割と読めてしまうものです。

2文字以上連続する母音は省略しない。

neet → Neet
week → Week
weak → Weak

子音に挟まれていても、2文字以上母音が連続する場合は省略しません。
省略するとneetとnetの区別が付かなくなってしまいます。

3文字以下の単語は省略しない。

say → Say
soy → Soy

これも省略しません。収拾がつかなくなります。

大文字は省略しない。

NATO → NATO

大文字は略称の可能性が高いので省略しません。

文章中のスペースを省略し、すべての単語の頭を大文字にする。

stay hungry stay foolish → StyHngryStyFoolsh

スペースは省きます。かわりに、頭を大文字にして視認性を確保します。

ソース

プログラムのソースです。
Go言語で書かれています。
ただし、圧縮をかけているのでコンパイルは通りません。
こちらからオリジナルをダウンロードしてください。

cmprss.go
PckgeMain
Imprt(
    "Fmt"
    "Strngs"
    "Rgxp"
    "Os"
    "Io/Ioutl"
)
FncMain(){
    VrTxtStrng
    Txt,Ok:=ReadPpe()
    IfOk==Flse{
        Txt,Ok=ReadFleByArg()
        IfOk==Flse{
            Os.Ext(1)
        }
    }
    S:=Cmprss(Txt)
    Fmt.Prntln(S)
}
//CnvrtShrtStrng
FncCmprss(InptStrng)Strng{
    Re1,_:=Rgxp.Cmple("([BcdfghjklmnpqrstvwxwyzBCDFGHJKLMNPQRSTVWXWYZ])[Aiueo]([Bcdfghjklmnpqrstvwxwyz])")
    Lns:=Strngs.Splt(Inpt,"\N")
    FrL:=0;L<Ln(Lns);L++{
        Wrds:=Strngs.Splt(Lns[L],"")
        FrI:=0;I<Ln(Wrds);I++{
            Wrd:=Strngs.Ttle(Wrds[I])
            IfLn(Wrd)>3{
                Wrd=Re1.RplceAllStrng(Wrd,"$1$2")
                Wrd=Re1.RplceAllStrng(Wrd,"$1$2")
            }
            Wrds[I]=Wrd
        }
        Lns[L]=Strngs.Join(Wrds,"")
    }
    RtrnStrngs.Join(Lns,"\N")
}
//ReadTxtByPpe
FncReadPpe()(Strng,Bool){
    Stts,_:=Os.Stdn.Stt()
    IfStts!=Nil&&(Stts.Mde()&Os.MdeChrDvce)==0{
        Byts,Err:=Ioutl.ReadAll(Os.Stdn)
        IfErr!=Nil{
            Fmt.Prntln(Err.Errr())
            Rtrn"",Flse
        }
        RtrnStrng(Byts),True
    }Else{
        Rtrn"",Flse
    }
}
//ReadTxtByFle
FncReadFleByArg()(Strng,Bool){
    IfLn(Os.Args)<2{
        Rtrn"",Flse
    }
    Cntnt,Err:=Ioutl.ReadFle(Os.Args[1])
    IfErr!=Nil{
        Fmt.Prntln(Err.Errr())
        Rtrn"",Flse
    }
    RtrnStrng(Cntnt),True
}

まとめ

zip圧縮との比較結果を載せておきます。

・・・誤差ですね。
元に戻せなくなるデメリットを受け入れてまで使う意味はなさそうです。

あ、でもTwitterとか、自動生成されるブログ記事のURLとか・・・