Smalltalkのtは小文字です

id:sumim:about

オブジェクト指向の“モヤッと”の正体を知りたくなったら、id:sumim:20040525:p1id:sumim:20080415:p1 がお役に立つかも…。


 | 

2006-12-03

[][] 'SAKURA' -> 'HZPFIZ' な暗号文を復号する


熱血!平成教育学院の今夜の放送の問題より。復号(暗号化も同じ)のためのスクリプトを SqueakSmalltalk を使ったいくつかの方法で。


■対応する復号文字の ASCII コードを計算で求めて #collect:
| codeString |
codeString := 'HZPFIZ'.

^ codeString collect: [:chr |
   | asciiValue |
   asciiValue := $Z asciiValue - chr asciiValue + $A asciiValue.
   Character value: asciiValue]
=> 'SAKURA'

■あらかじめ作成したテーブルから復号文字を探して #collect:
| codeString tableDict alphabet |
codeString := 'HZPFIZ'.

tableDict := Dictionary new.
alphabet := Character alphabet asUppercase.
alphabet with: alphabet reversed do: [:key :val | tableDict at: key put: val].

^ codeString collect: [:chr | tableDict at: chr]

■ #translateWith: を用いて一括変換
| codeString tableArray alphabet start |
codeString := 'HZPFIZ'.

tableArray := Character allByteCharacters.
alphabet := Character alphabet asUppercase.
tableArray replaceFrom: (start := tableArray indexOf: $A) to: start+25 with: alphabet reversed.

^ codeString translateWith: tableArray

■ #translateWith: 版で、用いるテーブルの情報を必要最小限にして
| codeString tableArray |
codeString := 'HZPFIZ'.

tableArray := (Array new: $A asciiValue), Character alphabet asUppercase reversed.

^ codeString translateWith: tableArray

ここまでシンプルにできると、ワンライナで書いてもさほどの違和感はない。

'HZPFIZ' translateWith: (Array new: $A asciiValue), ($A to: $Z) reversed
=> 'SAKURA'

さらに短く。

'MVPPVGHF' translateWith: (Array new: 65), ($A to: $Z) reversed
=> 'NEKKETSU'

これで最短?

'HJFVZP' translateWith: (1 to: 65), ($A to: $Z) reversed   " => 'SQUEAK' "


こういうのは Perl and/or 正規表現が得意そう…なのですが、残念ながら私のほぼ無に等しい Perl 力ではワンライナで書くことはできませんでした。



コメント欄で nurse さんが Perl の tr/// 、s/// を使った例を教えてくださいました。ありがとうございます。

echo HZPFIZ | perl -pe 'tr/A-Z/ZYXWVUTSRQPONMLKJIHGFEDCBA/'
echo HZPFIZ | perl -pe 's/[A-Z]/chr 155-ord$&/ge'

前者については、Smalltalk の #reversed や Ruby の reverse のようなものが Perl にもあれば、もう一段、抽象度が上げられそうです。(…とは言っても、変数を使ったり、eval しなくてはいけなくなるので、一歩進んで二歩下がるwって感じでしょうか。って、ありますね。reverse 。Perl にも。当然。w)



さらに tociyuki さんが、このエントリーを受けて、Perl や Ruby でいろいろな方法で書いてくださっています。ありがとうございます。


私は Ruby で書いた次のものが理想像としてイメージしているのに近かったです。Range にもうちょっと融通が利いて、to_a しなくてよければよりベターなのですが…。

'HZPFIZ'.tr!("A-Z", ("A".."Z").to_a.reverse.join)

Perl のほうは、これがイメージに近いです。前述のとおり、eval が邪魔くさいですが…(^_^;)。

echo HZPFIZ | perl -pe 'eval qq{tr/A-Z/@{reverse A..Z}/};'


と書いたら、新しいコメントで、shinichiro_h さんに Ruby の [*"A".."Z"] という表現を教えていただきました。すばらしい。ただ、たしかに、表記上の冗長さが減る代わりに、新たな表現方法の解釈をしないといけなくなるので、総じて分かりやすさの面では一進一退…かもしれませんね。

'HZPFIZ'.tr!("A-Z", [*"A".."Z"].reverse!.join)


kounoike さんから、Golfed 'SAKURA' => 'HZPFIZ' | Typemiss.net にて、Perl ゴルファーの心得に添えて Perl の別解などをいただきました。ありがとうございます。(言われて気づいたのですが、上の Squeak の Smalltalk の例は、ルール1を前提にしちゃっていますから Perl や Ruby の例と同列に扱ってはいけなかったですね…(^_^;)。まあ、ハンデだと思ってご勘弁を。)


で、いただいた別解はこちら。

#!perl
print+(A..CL)[-ord]for<>=~/./g

一瞬、なぜこれでうまく動くのか分かりませんでした。w Squeak の Smalltalk で書くと、このような内容でしょうか。

'HZPFIZ' collect: [:chr |
   ($A to: (Character value: $A asciiValue + $Z asciiValue)) atWrap: chr asciiValue negated]


まとめ(とりあえず…。あと順不同。)


▼ Squeak の Smalltalk
'HJFVZP' translateWith: (1 to: 65), ($A to: $Z) reversed

(1 to: 65), が意味不明 and/or #translateWith: に渡すテーブルの構造を知らないとダメなのがダサい(ソース嫁?ってのもねぇ… orz)。


▼ Perl
echo HZPFIZ | perl -pe 'eval qq{tr/A-Z/@{reverse A..Z}/};'

イメージどおりだが、いかんせん展開に eval 必須なのが玉に瑕。


▼ Ruby
'HZPFIZ'.tr!("A-Z", [*"A".."Z"].reverse!.join)
'HZPFIZ'.tr!("A-Z", ("A".."Z").to_a.reverse.join)

to_a or not to_a ...。(あるいは、Range のバ〜カ ;-p)w あと、Smalltalk みたいに、String が Array 型なら(あるいは、Array を String の代わりに使えたら)よかったのに。

nursenurse 2006/12/04 02:51 正攻法ですと、trを使って、echo SAKURA | perl -pe’tr/A-Z/ZYXWVUTSRQPONMLKJIHGFEDCBA/’ですかねぇ。
でもecho SAKURA | perl -pe’s/[A-Z]/chr 155-ord$&/ge’の方が短いな。。。

sumimsumim 2006/12/04 10:25 『おお。そうです。そういうのが知りたかったのです。ありがとうございます。やはり Z-A みたいなのは使えないのですね…。あれば究極に短く、かつ、抽象化されていて分かりやすい、と思ったのですが(^_^;)。もっとも、Perl や正規表現に“読み下し易さ”を求めている時点でオレは負け組か。w』

shinichiro_hshinichiro_h 2006/12/04 14:01 自分とこ (http://shinh.skr.jp/m/?date=20061204#p11) に書きましたが、 Range=>Array は [*”A”..”Z”] でできますです。わかりやすいかはあやしいですが。

sumimsumim 2006/12/04 16:13 ありがとうございます。ここから先、さらに短くするほうは、ゴルファーたちにお任せします。w

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。

トラックバック - http://d.hatena.ne.jp/sumim/20061203/p2
 | 
2004 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 |

最近のコメント

1. 10/02 sumim
2. 10/02 shiro
3. 10/01 sumim
4. 10/01 shiro
5. 10/01 sumim

最近のトラックバック

1. 01/05 no_orz_no_life - Erlangとボウリングの点数とリストのパターンマッ...
2. 12/30 None is None is None - ソニーからの挑戦状をPythonで解いてみた
3. 05/25 プログラマ―ズログ - オブジェクト指向言語が流行した必然性につい...
4. 10/11 プログラマ―ズログ - オブジェクト指向言語が流行した必然性につい...
5. 10/01 cozeの勉強日記 - 素数ジェネレータ

この日記のはてなブックマーク数
1011085