プログラミング準備運動のメニューを決める
トラックバックで準備運動のメニュー案をもらったので、実際にやってみました。
実際にやってみたもの
回文判定
ABCDEFを並べ替えてできる文字列を辞書順で出力する
再帰メソッドでカウントダウン
再帰メソッドでカウントアップ
全ての目が出るまでサイコロを振り続ける
両替をする
ファイルの各行に行番号を右揃えでつけて出力する
標準入力の各行に行番号を右揃えでつけて出力する
回文判定
def palindrome?(seed) str=seed.downcase.split(//) until str.length <= 1 return false unless (str.shift == str.pop) end true end p palindrome?("abcdeedcba") #=>true p palindrome?("abcdeecba") #=>false p palindrome?("detartrated")#=>true #日本語の場合は辞書を作らないとダメかもしれない。
ABCDEFを並べ替えてできる文字列を辞書順で出力する
ABCDEFの並び替えてできる文字列は6!で120通りあるので、ABCDだけにします。
class A def initialize seed @result = [] @seed = seed.sort! end def run f([], @seed) return @result end def f(content, rest) if rest.size == 1 @result << (content.concat(rest)).join return end rest.each do |e| r = rest.dup c = content.dup c << (r.delete e) self.f(c,r) end end attr_reader :result end a=A.new(%w{ A B C D}) a.run p a.result #=>["ABCD", "ABDC", "ACBD", "ACDB", "ADBC", "ADCB", "BACD", "BADC", "BCAD", "BCDA", "BDAC", "BDCA", "CABD", "CADB", "CBAD", "CBDA", "CDAB", "CDBA", "DABC", "DACB", "DBAC", "DBCA", "DCAB", "DCBA"
もうちょっときれいに書けそうな気がするんだけど…、分かりません><
再帰メソッドでカウント(アップ/ダウン)
def coutdown(n, to=0) return if n <= to puts(n) coutdown(n-1, to) end def coutup(n, to) return if n > to puts(n) coutup(n+1, to) end
全ての目が出るまでサイコロを振り続ける
これは意外と楽しかったです。(classを作る練習にもなるかもしれません)
class Dice def initialize() @count = 0 @result = [] @content = (1..6).to_a end def roll if @game_set puts "already the game was end (count=#{@count})" return false end @count += 1 shuffle x = @content.first check(x) return x end private def check(x) @result << x unless @result.find{ |e| e == x} game_set(x) if @result.size == 6 end def game_set(x) print "game-set! last is .." @game_set = true end def shuffle @content.each_index do |i| j = rand(i+1) @content[i], @content[j] = @content[j], @content[i] end end end s = Dice.new while x=s.roll print "#{x}, " end s.roll s.roll #=> # 3, 4, 5, 6, 6, 5, 3, 5, 3, 6, 2, game-set! last is ..1, already the game was end (count=12) # already the game was end (count=12) # already the game was end (count=12)
両替をする
ハッシュで返した方がいいのかな?
class Exchanger def initialize @kinds = [10000, 1000, 500, 100, 50, 10, 5, 1] end def exchange(money) result = Array.new(@kinds.size,0) @kinds.each_with_index do |e, i| next if money < e result[i] = money / e money = money % e end Hash[*(@kinds.zip result).flatten!] end end ec = Exchanger.new p ec.exchange(379) p ec.exchange(5772234) #=> # {5=>1, 500=>0, 50=>1, 1=>4, 100=>3, 10000=>0, 10=>2, 1000=>0} # {5=>0, 500=>0, 50=>0, 1=>4, 100=>2, 10000=>577, 10=>3, 1000=>2}
各行に行番号を右揃えでつけて出力する
def f str seed = str.split("\n") max_width = seed.sort_by{ |e| e.length}.last.length seed.each_with_index{ |e,i| puts e.concat(" "*(max_width-e.length)).concat(i.to_s)} end #=> # aiueo 0 # kakikukekosasisuseso1 # tatituteto 2 # naninuneno 3 # yayuyo 4
さすがにこれだと効率が悪そう。
(特に最大の文字数をみつける処理に無駄が多すぎ)
ということこんな感じに変更。
def f2 str max_width = search_max(str) str.each_with_index{ |e, i| puts e.gsub(/\n/){(" "*(max_width - e.length)).concat(i.to_s+$&)}} end def search_max(str) str.inject(0){ |max, e| max = e.length if max < e.length; max} end
でも、日本語にすると文字数がおかしくなりそう。(番号の位置がおかしくなる)
意外と難しいです><
追記
日本語じゃなくても番号の位置がおかしくなっている…
右揃えの意味を勘違いしていました><
def f3(str) max_length = str.inject(0){ |re, e| re += 1}.to_s.length str.each_with_index{|e, i| puts "#{" "*(max_length - i.to_s.length)}#{i}: #{e}"} end #=> # 0: aiueo # 1: kakikukekosasisuseso # 2: tatituteto # 3: naninuneno # 4: yayuyo
やってみて分かったこと
- 一度実際に書いてみないと、それが準備運動のメニューに適しているかどうか分からない。
- 簡単に見えるものでも、意外といろいろなことに気づく。
- 簡単そうなものでもやってみるとけっこう時間がかかる。
- メニューは2つに分けられるかもしれない。
- 言語固有の内容
- 汎用的な内容(思考能力を問うような問題)
後で付け足す