○3つ、△2つ、×1つの目を持つサイコロ2個を振ったときに出る目の組み合わせで一番多いのは…ふんがっ


http://blogs.yahoo.co.jp/takutakutakutaku50/28887753.html


遅レス。 経由で。リンク先の ささださんの inject、sort_by を使った版を直訳ぎみに SqueakSmalltalk で。

| ss |
((ss := #(○ ○ ○ △ △ ×)) inject: Dictionary new into: [:result :aa |
      ss do: [:bb |
         | key |
         key := {aa. bb} copy sort.
         result at: key put: (result at: key ifAbsent: [0]) + 1]; yourself])
   associations sortBy: [:aa :bb | aa value > bb value]


Ruby の Hash は、Smalltalk では Dictionary に(ほぼ)相当。ただ、Hash.new(0) みたいなサービスはないので、指定したキーが見つからなかったタイミング(#at:ifAbsent: 起動時)で同種の処理をしています。Ruby の inject は、(少なくとも名前は)そもそも Smalltalk の #inject:into: が元なので問題なし。sort_by による シュワルツ変換については、見た目だけが似ているw通常の条件付き並べ替えでごまかしていますので、あしからず。



もっとも、SqueakSmalltalk には、この局面にぴったりな「重複を許す組み合わせ」が、ファウラーいうところいささか冗長な ヒューメインなw“コレクションクロージャメソッド”として用意されていますし(#asDigitsToPower:do: などという、ぱっと見、それとはわかりにくい名前でではありますが…)、また、要素を数え上げる場面で便利に使える a Bag もあるので、次のように書いた方が簡単です。

| bag |
bag := Bag new.
#(○ ○ ○ △ △ ×) asDigitsToPower: 2 do: [:pair | bag add: pair copy sort].
^ bag sortedCounts asArray
#(12->#(#△ #○) 9->#(#○ #○) 6->#(#× #○) 4->#(#× #△) 4->#(#△ #△) 1->#(#× #×))

余談ですが、こういうとき SqueakSmalltalk では、オブジェクトの copy を忘れて、けっこう痛い目を見ることがあるので、要注意ですね。