「プログラミング入門 - Rubyを使って -」の練習問題をやってみる

id:heydaysさんのエントリを見て興味がでたので自分もやってみる。

方針:

  • チュートリアルの進度とか無視して全力でやってみる
  • 変態的な方法も試してみる
  • へたれなので原文でなく邦訳を見る

0-6章の練習問題

以下うるう年とか知らない。

Q. 1年は何時間でしょうか?

p  1 * 365 * 24   #=> 8760

Q. 10年間は何分でしょうか?

p 10 * 365 * 24 * 60  #=> 5256000

Q. あなたが生まれてから今日まで何秒たっているでしょうか?

x = 20	#仮
p  x * 365 * 24 * 60 * 60	  #=> 630720000

Q. あなたは一生のうちいくつのチョコレートを食べたいですか?
注:この計算には多少時間がかかるかもしれません。

Thread.start{ self.how_many_want :chocolate }

Q. 私が生まれてから10億200万秒 たっているとしたら、私は今何歳でしょう?

sec = Integer("1,002,000,000".gsub(/,/, ""))
p sec / 60 / 60 / 24 / 365	#=> 31

Q. 最初に姓、次に名前を聞いて、最後にフルネームに対してあいさつをするようなプログラムを書いてみましょう。

def question(subject)
  puts "あなたの #{subject} は? "
  gets.strip
end

name   = question("氏名")
family = question("姓名")
puts "こんにちは, #{name} #{family} !"

Q. 好きな数を入力してもらい、それに1を加えて、その結果を ベターな数字として薦めるプログラムを書きましょう。 (機転の利いたサジェスチョンに努めましょう。)

puts "お好きな数字は? "
puts "#{Integer(gets).succ} もいかがですか?"

Q.「怒ったボス」のプログラムを書いてみましょう。 まず、無作法に何が望みか聞いてきます。 で、何を答えようと「怒ったボス」はそれを叫び返して、あなたを首にします。たとえば、もし給料上げてくださいとタイプしたとすると なにぃ? "給料上げてください" だとー!! おまえは首だ!! と、叫び返してきます。

puts "気に食わない目つきをしやがって。お前、何が望みだ?"
wish = gets.strip
puts "なにぃ? \"#{wish}\" だとー!! おまえは首だ!!"
puts
puts "   ま さ に 外 道"


Q. center, ljust, そして rjust を使ってもう少し何かやってみましょう。こんな感じの「目次」を表示する プログラムを書いてみてください。

               目  次                       
                                            
1章:  数                                p. 1
2章:  文字                             p. 72
3章:  変数                            p. 118
def item(nsection, title, page)
  left  = "#{nsection}章:  #{title}".ljust(34)
  right = "p. #{page}".rjust(8)
  "#{left}  #{right}"
end

puts "目 次".center(44)
puts
puts item(1, "",   1)
puts item(2, "文字", 72)
puts item(3, "変数", 118)

Q. "99本のビールが壁に..." 遠足などでよく歌われる古典的な童謡の歌詞、"99 Bottles of Beer on the Wall" を 出力するプログラムを書いてみましょう。

def beer(n)
<<EOS
#{n} Bottles of beer on the wall
#{n} Bottles of beer
Take one down and pass it around
#{n - 1} Bottles of beer on the wall
EOS
end

puts (1..99).map{|x| beer x }.reverse.join("\n")

Q. 耳の遠いおばあちゃんのプログラムを書いてみましょう。 おばあちゃんに何を言っても(何をタイプしても)、叫ばない限り (つまり、全部大文字でタイプしない限り)、 は?! もっと大きな声で話しておくれ、坊や! と返事をします。もし叫んだときは、彼女はあなたの言葉を聞いて (少なくとも聞いた気がして)、 いやー、1938年以来ないねー! と大声で返事をします。 プログラムにちょっと真実味 を持たせるため、 1930年から1950年のランダムな数字で毎回違う年を叫ぶようにしましょう。 (この部分はオプションです。メソッドの 章で、Rubyの乱数発生法の節を読んでいたら簡単でしょう。) あなたはBYEと叫ぶまでおばあちゃんとの会話から逃れられません。

loop do
  print "呼びかけ >"
  puts case gets.strip
    when "BYE" then exit
    when /\A[A-Z]+\Z/ then "いやー、19#{rand(21) + 30}年以来ないねー!"
    else "は?! もっと大きな声で話しておくれ、坊や!"
  end
end

Q. 上で作った、「耳の遠いおばあちゃんのプログラム」を拡張しましょう。 おばあちゃんはあなたに行って欲しくないのです。 あなたがBYEと叫んでもおばあちゃんは聞こえないふりをします。 BYEを3回連続で 叫ばないといけないように変更してみてください。

def counting_bye(n)
  raise ArgumentError if n < 0
  cnt = 0
  loop do
    nobye = catch(:bye) do
      yield
      true
    end
    nobye ? cnt = 0 : cnt += 1
    break if cnt == n
  end
end

def say_bye
  throw :bye, false
end

counting_bye(3) do
  print "呼びかけ >"
  case gets.strip
  when "BYE" then say_bye
  when /\A[A-Z]+\Z/ then puts "いやー、19#{rand(21) + 30}年以来ないねー!"
  else puts "は?! もっと大きな声で話しておくれ、坊や!"
  end
end


ここでうるう年のことを思い出す。

Q. うるう年。 開始の年と終わりの年を聞いて、その間にあるすべてのうるう年を (もし開始や終了の年がうるう年だったらそれも含めて)表示するプログラムを書きましょう。 うるう年は(1984年とか2004年のように)4で割り切れる数の年です。ただし、100で割り切れる年は うるう年ではなくて (たとえば1800年や1900年)、さらに、それは 400で割り切れない限り です。(つまり、1600年や2000年はうるう年です。)

# うるう年診断チャート
chart = {
  # 4 で割り切れるか?
  true  => {
    # 100 で割り切れるか?
    true  => {
      # 400 で割り切れるか?
      true  => true,
      false => false
    },
    false => Hash.new(true) #4で割り切れて100で割り切れないから後はとにかく真
  },
  false => Hash.new(Hash.new(false))  #4で割り切れないから後はとにかく偽
}
def chart.check(year)
  x, y, z = [4, 100, 400].map{|d| (year % d).zero? }
  self[x][y][z]
end

fst, last = ["開始の年 ? ", "終わりの年 ? "].map{|prompt|
  print prompt
  Integer(gets.strip)
}

fst.upto(last) do |y|
  puts y if chart.check(y)
end