“その二乗値が1〜9を過不足なく含む整数の列挙”を Squeak Smalltalk で


2009-11-09 経由で。

2乗した結果に1から9までの数字が1度ずつ現れる整数をすべて挙げよ

Haskell再び、簡単なところから - yarbの日記


sort = '123456789' あたりをなんかヒネれないものか 30ナノ秒ほど考えましたが断念しました。^^;

(1 to: 987654321 sqrt) select: [:x | (x * x) asString sort = '123456789'] thenCollect: [:x | x -> (x * x)]
=> {11826->139854276 . 12363->152843769 . 12543->157326849 . 14676->215384976 . 15681->245893761 . 
15963->254817369 . 18072->326597184 . 19023->361874529 . 19377->375468129 . 19569->382945761 . 
19629->385297641 . 20316->412739856 . 22887->523814769 . 23019->529874361 . 23178->537219684 . 
23439->549386721 . 24237->587432169 . 24276->589324176 . 24441->597362481 . 24807->615387249 . 
25059->627953481 . 25572->653927184 . 25941->672935481 . 26409->697435281 . 26733->714653289 . 
27129->735982641 . 27273->743816529 . 29034->842973156 . 29106->847159236 . 30384->923187456}


似たような方針の Ruby 版も。

(1..Math.sqrt(987654321)).select{ |x| (x**2).to_s.split(//).sort.join == "123456789" }.collect{ |x| [x, x**2] }
=> [[11826, 139854276], [12363, 152843769], [12543, 157326849], [14676, 215384976], [15681, 245893761], 
[15963, 254817369], [18072, 326597184], [19023, 361874529], [19377, 375468129], [19569, 382945761], 
[19629, 385297641], [20316, 412739856], [22887, 523814769], [23019, 529874361], [23178, 537219684], 
[23439, 549386721], [24237, 587432169], [24276, 589324176], [24441, 597362481], [24807, 615387249], 
[25059, 627953481], [25572, 653927184], [25941, 672935481], [26409, 697435281], [26733, 714653289], 
[27129, 735982641], [27273, 743816529], [29034, 842973156], [29106, 847159236], [30384, 923187456]]


が、どうにも sort = '123…' の部分が引っかかるので、こんなのをヒネり出してみました。

(1 to: 987654321 sqrt) select: [:x | (x * x) asString includesAllOf: ($1 to: $9)] thenCollect: [:x | x -> (x * x)]


私にとっての Smalltalk らしさはやっぱり、ざっと流し読みをしたとき、あるいは音読したときに何がしたいのかが分かること、なので、サイズチェックを省略した根拠がコードにしるされていない気持ち悪さを差し引いたとしても、こちらのほうがしっくり来ます。

もっとも、'123…' がリテラルなのに対して、$1 to: $9 なる文字の配列の動的生成はいかにも効率が悪そうだけれども…とか思いきや、じつは #includesAllOf: のおかげで実行速度はこちらのほうが遙かに速いという嬉しいオマケも。