みなさん、文章ファイルを圧縮する時、どの圧縮方式を採用してますか?
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言語で書かれています。
ただし、圧縮をかけているのでコンパイルは通りません。
こちらからオリジナルをダウンロードしてください。
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
}
まとめ
・・・誤差ですね。
元に戻せなくなるデメリットを受け入れてまで使う意味はなさそうです。
あ、でもTwitterとか、自動生成されるブログ記事のURLとか・・・