このブログの記事URLを可逆圧縮する仕掛け(Pure Perl)
2010-08-15-6
[Programming][Algorithm]
このブログの記事専用のURL短縮の仕掛けを作りました。
tinyurl.com や bit.ly などのURL短縮サービスの「たつをの ChangeLog」専用ロジックです。
特徴はデータベースを使っていないこと。
ロジックのみで圧縮、展開ができるのでメンテフリーで超軽量です。
このブログは chalow というブログツールを使っているのですが、各記事の URL の最後は日付+その日の通し番号となっています。
例えば
「http://chalow.net/2009-01-02-3.html」
は
「2009年1月2日の3つ目の記事」
を表しています。
このブログでは1日あたり24記事も書くことはないので、何個目の記事を表す通し番号は「時」とみなすことにします。
つまり
「2009年1月2日3時」
となります。
で、「2009年1月2日3時」を10進数の数値にします。
と、その前に chalow でのブログは2000年からなので、年は2009から2000を引いて9にしておきます。
あと計算のため月、日、時はそれぞれ1マイナスしています。
「9年0月1日2時」になります。
さて10進数にしてみます。
まあ、ユリウス通日みたいにどこかを基準にした経過日数に変換しても良いのですが、面倒だし本質ではないので上記の式でざっくりと。
これを64進数に変換します。
使う字は下記の64文字。小さい順に並べてあります。
Base64っぽい感じです。
「2009年1月2日3時」→「80378」の64進数変換結果は下記となります。
つまり、 「http://1.jp/」がURL短縮サイトとすると、
「http://chalow.net/2009-01-02-3.html」
は
「http://1.jp/Tn6」
に圧縮されます。
戻すときは今の手順を逆に進めばOKです。
データベースは不要ながら、なかなかの圧縮率です。
サンプルコードと実行例です。
■コード(tinytcl.pl):
■実行例:
tinyurl.com や bit.ly などのURL短縮サービスの「たつをの ChangeLog」専用ロジックです。
特徴はデータベースを使っていないこと。
ロジックのみで圧縮、展開ができるのでメンテフリーで超軽量です。
ロジックの解説
このブログは chalow というブログツールを使っているのですが、各記事の URL の最後は日付+その日の通し番号となっています。
例えば
「http://chalow.net/2009-01-02-3.html」
は
「2009年1月2日の3つ目の記事」
を表しています。
このブログでは1日あたり24記事も書くことはないので、何個目の記事を表す通し番号は「時」とみなすことにします。
つまり
「2009年1月2日3時」
となります。
で、「2009年1月2日3時」を10進数の数値にします。
と、その前に chalow でのブログは2000年からなので、年は2009から2000を引いて9にしておきます。
あと計算のため月、日、時はそれぞれ1マイナスしています。
「9年0月1日2時」になります。
さて10進数にしてみます。
((9 x 12 + 0) x 31 + 1) x 24) + 2 = 80378
まあ、ユリウス通日みたいにどこかを基準にした経過日数に変換しても良いのですが、面倒だし本質ではないので上記の式でざっくりと。
これを64進数に変換します。
使う字は下記の64文字。小さい順に並べてあります。
Base64っぽい感じです。
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789-_
「2009年1月2日3時」→「80378」の64進数変換結果は下記となります。
Tn6
つまり、 「http://1.jp/」がURL短縮サイトとすると、
「http://chalow.net/2009-01-02-3.html」
は
「http://1.jp/Tn6」
に圧縮されます。
戻すときは今の手順を逆に進めばOKです。
データベースは不要ながら、なかなかの圧縮率です。
コードと実行例
サンプルコードと実行例です。
■コード(tinytcl.pl):
#!/usr/bin/perl use strict; use warnings; my ($y, $m0, $d0, $h) = (2009,1,2,3); print "ID(DATE): $y, $m0, $d0, $h\n"; my $ec = clid_encode($y, $m0, $d0, $h); print "Short CODE: $ec\n"; ($y, $m0, $d0, $h) = clid_decode($ec); print "ID(DATE): $y, $m0, $d0, $h\n"; sub clid_encode { my ($y, $m, $d, $h) = @_; $m--; $d--; $h--; $y -= 2000 if $y >= 2000; my $ec = (($y * 12 + $m) * 31 + $d) * 24 + $h; my $str = ""; while ($ec > 0) { my $v = $ec %64; my $c = substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" ."abcdefghijklmnopqrstuvwxyz" ."0123456789-_", $v, 1); $str = $c.$str; $ec = int($ec / 64); } return $str; } sub clid_decode { my ($str) = @_; my $ec = 0; foreach my $c (split(//, $str)) { my $v = index("ABCDEFGHIJKLMNOPQRSTUVWXYZ" ."abcdefghijklmnopqrstuvwxyz" ."0123456789-_", $c); $ec = $ec * 64 + $v; } my $h = $ec % 24; $ec = int($ec / 24); my $d = $ec % 31; $ec = int($ec / 31); my $m = $ec % 12; $ec = int($ec / 12); $m++; $d++; $h++; $ec += 2000 if $ec < 100; return ($ec, $m, $d, $h); }
■実行例:
% ./tinytcl.pl ID(DATE): 2009, 1, 2, 3 Short CODE: Tn6 ID(DATE): 2009, 1, 2, 3
この記事に言及しているこのブログ内の記事