読者です 読者をやめる 読者になる 読者になる

せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【アルゴリズム】例題を考えてみたけど難しすぎて挫折した。。

アルゴリズムを色々と考えてきたのですが、
3時間かかって考えたクイックソートが10要素のソートに38秒かかるとか

自分の知性を如実に反映したプログラミング結果になっていて、
お天道様も真っ青な状態です。

ま、考えてきたと言っても3日間だけだけどね。。。

 

なぜアルゴリズムをさっと書けない?

2時間も3時間もかかって、再帰関数とか書いてる状態。

なんでこんなにだめなのかなーって考えてたんだけど、
小さく書いて小さく実行が出来てないからだと、思う。

問題を見ていきなり「i,jを使って・・・再帰で・・・」なんて考えていて
自分の身の丈にあってない一発でスマートな解答を作ろうとして
こけていたんだと思われる。



 

考えた問題

こんな問題を考えてみよう

数が二つ与えられて、片方の数字を、
もう片方の数字以下の数字の組み合わせで表現する

(例)
10 と 1 ⇒[1,1,.....,1]
4 と 3 ⇒[3,1][2,2][2,1,1][1,1,1,1]
4 と 2 ⇒[2,2][2,1,1][1,1,1,1]

伝わったかな。

それでは小さく書いて小さく実行、を意識して解答してみるぞ!


 

数値クラスへの特異メソッド追加

class Fixnum
	def separate(int)
	p "jjj"
	end
end

1.separate(1)
jjj

よし。


 

引数を1で固定

class Fixnum
	def separate(int)
		results = []
		if int == 1 then
			results << {1 => self}
		end
		results
	end
end
p 10.separate(1)
[{1=>10}]

よし。


 

Fixnum特異クラスの方針を変更

class Fixnum
	attr_accessor :results
  def initialize
    @results = []  ←数値のinitializeは実行されないため、このコードは実行されない
  end
  
	def separate(int)
		if int == 1 then
			@results << {1 => self} ←nilがレシーバとなり<<メソッドを実行するためエラー
		end
		
		@results
	end
end

p 10.separate(1)  ←エラー。

数値クラスのinitializeが実行できない。
考えてもいいけど、トリッキーにもなるので、この方針はやめ。


インスタンス変数を使う

class Hoge
	attr_accessor :results
  def initialize
    @results = [] 
  end
  
	def separate(subject, int)
		if int == 1 then
			@results << {1 => subject}
		end
		
		@results
	end
end

p Hoge.new.separate(10,1)
[{1=>10}]

Hogeのインスタンスを作っているところが、煩雑なコードと言う気がするけれど、
アルゴリズムを考えたいので、今はこれで書いていく。



 

お手上げ

4時間かかっても分からなかった、、だめだ。
紙に書いたりして整理してみたけど、ステップバイステップで進めていくのは難しい。

問題が難しすぎたのかな。。
while文の中で再帰をしていたり、難解なコードになりすぎてる。

↓挫折したコード

class Hoge
attr_accessor :results
	def initialize
		@results = []
	end
	def separate(subject, int)
		int = subject if subject < int
		while int > 0
			result = []
			if int == 1
				result << {1 => subject}
			else
				i = subject / int
				while i >= 0
					_result = []
					_result << {int => i} if i != 0
					if subject - int*i != 0
						separate(subject - int*i, int-1).each do |s|
							_result << s
							@results << _result
						end
					else
						@results << _result
					end
					i -= 1
				end
				
			end
			int -= 1
		end
		result
	end
end

hoge = Hoge.new
hoge.separate(5,5)
p hoge.results

■実行結果

[[{5=>1}], [{4=>1}, {1=>1}], [{2=>1}], [{1=>2}], [{3=>1}, {1=>2}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{2=>1}], [{1=>2}], [{3=>1}, {1=>2}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{4=>1}, {1=>1}], [{2=>1}], [{1=>2}], [{3=>1}, {1=>2}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{2=>1}], [{1=>2}], [{3=>1}, {1=>2}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}], [{1=>5}], [{2=>2}, {1=>1}], [{2=>1}, {1=>3}], [{1=>5}]]


だめだ。。
師匠にヒントをもらおう。