Smalltalkのtは小文字です

id:sumim:about

Smalltalk を本格的に勉強する気はないけれど、うんちく程度に知っておきたいなら→Smalltalkをちょっとかじってみたい人のための、チュートリアルまとめ - Qiita

オブジェクト指向の“モヤッと”の正体を知りたくなったらこちらの記事が役に立つかも→id:sumim:20080415:p1 とか id:sumim:20040525:p1


 | 

2007-06-27

[] 1 から 1000 まで続けて書いてできる整数…を Squeak Smalltalk でいろいろと


 1から15まで続けて書くと123456789101112131415となる。これを1つの整数と考えると、この数は21けたで,1が8回使われている。このように、1からある整数まで続けて書いてできる整数について、次の各問いに答えよ。

(1)1から100まで続けて書いてできる整数は何けたか。

(2)1から1000まで続けて書いてできる整数は何けたか。また、その整数の中に1は何回使われているか。

灘中学校1998年2日目第1問(問題)

| stream |
stream := String new writeStream.
(1 to: 1000) do: [:each | stream nextPutAll: each printString].
^ {'桁' -> stream size. '1の数' -> (stream contents occurrencesOf: $1)}

| bag |
bag := Bag new.
(1 to: 1000) do: [:each | bag addAll: each printString].
^ {'桁' -> bag size. '1の数' -> (bag occurrencesOf: $1)}

| numOfDigits numOfOnes |
numOfDigits := numOfOnes := 0.
(1 to: 1000) do: [:each |
    | strOfInt |
    strOfInt := each printString.
    numOfDigits := numOfDigits + strOfInt size.
    numOfOnes := numOfOnes + (strOfInt occurrencesOf: $1)].
^ {'桁' -> numOfDigits. '1の数' -> numOfOnes}

| stream numOfOnes |
stream := ReadWriteStream on: String new.
(1 to: 1000) do: [:each | stream nextPutAll: each printString].
numOfOnes := 0.
stream reset; do: [:each | each == $1 ifTrue: [numOfOnes := numOfOnes + 1]].
^ {'桁' -> stream size. '1の数' -> numOfOnes}

二番目の bag のが最もしっくりくる感じ。


おまけ。

^ {'桁' -> ((#(1 2 3) * 9 polynomialEval: 10) + 4). '1の数' -> (3 * 1000 / 10 + 1)}

おまけ2。

ブックマークで Haskellワンライナーを頂いたので、これを Squeak Smalltalk に意訳。

| f q |
f := [:n | n < 10 ifTrue: [{n}] ifFalse: [(f fixTemps copy value: n // 10), {n \\ 10}]].
q := (1 to: 1000) inject: #() into: [:result :each | result, (f fixTemps copy value: each)].
^ {q size. (q select: [:each | each == 1]) size}

おまけ3。

対抗して、Squeak Smalltalk でワンライナー。

(1 to: 1000) inject: #(0 0) into: [:r :e | r + {e printString size. e printString occurrencesOf: $1}]

Haskell に直訳ぎみに意訳すると、こんな感じでしょうか。

foldl (\r e -> zipWith (+) r [length $ show e, length $ filter (=='1') $ show e]) [0,0] [1..1000]

追記。

rubyco さんに rubyco(るびこ)の日記 - 1から1000まで続けて書いてできる整数…を考える でリンクしていただきましたので、Rubyist 向けに上のワンライナーを直訳ぎみに Ruby にも意訳してみます。

(1..1000).inject([0,0]){ |(r0,r1),e| [r0 + e.to_s.size, r1 + e.to_s.count('1')] }
=> [2893, 301]

Haskell 版も無名関数の引数にパターンを使うことで、同様に書き直せますね。

foldl (\(r0,r1) e -> (r0 + (length $ show e), r1 + (length $ filter (=='1') $ show e))) (0,0) [1..1000]

逆に Haskell の zipWith 版のほうは Ruby ならこんなニュアンス?

(1..1000).inject([0,0]){ |r,e| r.zip([e.to_s.size, e.to_s.count('1')]).map{ |a,b| a+b } }

仮に Ruby にも、二つの配列の対応する要素同士の足し算の機能(仮に Array#plus )があったならば、Smalltalk とまったく同じ、かつ、#inject(#inject:into:)を用いた総和のイディオムに似た書き方ができます。例によってなんちゃって版をしつらえて書くと次のような感じ(ちなみに Smalltalk の Collection >> #+ では、ダブルディスパッチを用いたこれとは異なる実装になっています。念のため)。#+ が使えないのが痛いですね(^_^;)。

class Array
  def plus(other)
    zip(other).map{ |a,b| a+b }
  end
end

(1..1000).inject([0,0]){ |r,e| r.plus([e.to_s.size, e.to_s.count('1')]) }

追記2。

満足せる豚。眠たげなポチ。:1から1000まで続けて書いてできる整数、すげー。すばらしいですね。二つめは #count を使うともっと叙述的になっていいかも。

[*1..1000].join.count('1')

Smalltalk には #join という発想(要素の #to_s をつなげて文字列にする…)がないので、同じことをしようとすると、なんだかなーって結果に(^_^;)。

(String streamContents: [:ss | 1 to: 1000 do: [:each | ss print: each]]) occurrencesOf: $1

似たような発想でなら、次のような手で短く書けますけど、中間生成物(?)が違っちゃうし、それがなんとはなしに気持ちが悪い。答えはちゃんと出ますけれどもね。w

(1 to: 1000) asArray asString occurrencesOf: $1
=> 301

ちなみにこの方向性で桁の数を答えさせようとする場合には、こう。

(1 to: 1000) asArray asString count: [:each | each isDigit]
=> 2893

spiralspiral 2007/07/10 16:14 太宰治はいいにしても、中学生頭良すぎ

sumimsumim 2007/07/10 17:15 詰め込みなのか、ゆとりなのか…。

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

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

 | 
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 | 03 | 04 | 05 | 06 | 08 | 10 | 12 |
2013 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 11 | 12 |
2014 | 01 | 02 | 05 | 07 | 08 | 09 | 10 | 11 |
2015 | 04 | 07 | 08 | 11 | 12 |
2016 | 02 | 03 | 06 | 07 | 08 |

最近のコメント

1. 06/25 sumim
2. 06/25 山田
3. 08/29 squeaker
4. 08/29 ardbeg1958
5. 10/16 umejava

最近のトラックバック

1. 05/25 プラグインレスでSVGを表示する「SIE」開発ブログ - メッセージをや...
2. 01/30 no_orz_no_life - Erlangとジャンケン
3. 12/31 檜山正幸のキマイラ飼育記 - J言語、だってぇー?
4. 09/04 Twitter / @atsushifx
5. 07/06 みねこあ - オブジェクト指向 と FizzBuzz

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