Category Archives: Learn to Program

犬と人間の年齢換算コード

 Rubyでプログラミング勉強中(参照)のちょっと息抜きに書いてみた。もうちょっとスッキリ書けないかなと思いつつ、現時点ではこれが精一杯。

today = Time.new
thisYear  = today.year
thisMonth = today.month
month = [1, 3, 5, 6, 7, 9, 10, 12, 13, 14, 16]
age_1 = 17
age_2 = 24
dogYear_1 = 7
dogYear   = 4
puts 'あなたのワンちゃんは西暦何年生まれですか?'
birthYear = gets.chomp.to_i
while birthYear > thisYear
puts '今年以前の西暦年を入力してください。'
birthYear = gets.chomp.to_i
end
puts 'あなたのワンちゃんは何月生まれですか?'
birthMonth = gets.chomp.to_i
if (thisYear == birthYear and thisMonth == birthMonth)
puts 'あなたのワンちゃんは生まれたばかりですね。おめでとう!'
exit
end
age_y = thisYear  - birthYear
age_m = thisMonth - birthMonth
if age_m < 0
age_m = thisMonth + (12 - birthMonth)
age_y = age_y - 1
end
if age_y == 0
puts 'あなたのワンちゃんは、月齢' + age_m.to_s + 'ヶ月です。'
age = month[age_m - 1]
elsif (age_y == 1 and age_m == 0)
puts 'あなたのワンちゃんは、' + age_y.to_s + '歳です。'
age = age_1
elsif (age_y == 1 and age_m >  0)
puts 'あなたのワンちゃんは、' + age_y.to_s + '歳と' + age_m.to_s + 'ヶ月です。'
age = age_1 + (dogYear_1 * age_m / 12)
elsif (age_y >= 2 and age_m == 0)
puts 'あなたのワンちゃんは、' + age_y.to_s + '歳です。'
age = age_2 + ((age_y - 2) * dogYear)
elsif (age_y  > 1 and age_m >  0)
puts 'あなたのワンちゃんは、' + age_y.to_s + '歳と' + age_m.to_s + 'ヶ月です。'
age = (age_2 + ((age_y - 2) * dogYear)) + (dogYear * age_m / 12)
end
puts '人間でいうと、概ね' + age.to_s + '歳です。'

メモ

  • 換算表参照 ⇒ 犬&猫 年齢換算表 e-Petfood
    • 月齢1ヶ月→1歳までは規則性がないみたい。
    • 1歳→2歳は7歳、2歳以降は4歳/年。
  • 誕生年(西暦)と誕生月を入力してもらい、取得する現在の年月と比較して、年齢(月齢)を計算・表示。
  • 月齢1ヶ月→1歳までの換算は規則性がないので、換算年齢を配列(month[])に入れこむ。
  • きっかりn歳にならない場合(例: 1歳9ヶ月とか)もあるので、大体で換算年齢を計算。

See also

A Few Things to Try on 7. Arrays and Iterators

 Rubyでプログラミング勉強中(参照)。

 Arrays(配列)とIterators(イテレータ)について学ぶ。

A Few Things to Try on 7. Arrays and Iterators

一問目

Write the program we talked about at the very beginning of this chapter.

Hint: There’s a lovely array method which will give you a sorted version of an array: sort. Use it!

7. Arrays and Iterators

『Write the program we talked about at the very beginning of this chapter』っていうのは、以下。

Let’s write a program which asks us to type in as many words as we want (one word per line, continuing until we just press Enter on an empty line), and which then repeats the words back to us in alphabetical order.

7. Arrays and Iterators

これは簡単。

word = gets.chomp
ary = []
while word != ''
ary << word
word = gets.chomp
end
puts 'Sorted by Alphabet'
puts '=================='
puts ary.sort

二問目

Try writing the above program without using the sort method. A large part of programming is solving problems, so get all the practice you can!

7. Arrays and Iterators

これは難しかった・・・。ウンウンと唸って唸ってやっとできた。

word = gets.chomp
ary = []
while word != ''
ary << word
word = gets.chomp
end
i = 0
while i < ary.length
j = i + 1
while j < ary.length
if ( ary[i].to_s > ary[j].to_s )
tmp = ary[i]
ary[i] = ary[j]
ary[j] = tmp
end
j = j + 1
end
i = i + 1
end
puts
puts 'Sorted by Alphabet'
puts '=================='
puts ary

三問目

Rewrite your Table of Contents program (from the chapter on methods). Start the program with an array holding all of the information for your Table of Contents (chapter names, page numbers, etc.). Then print out the information from the array in a beautifully formatted Table of Contents.

7. Arrays and Iterators

こんな感じでよいのかな。

toc = ['Chapter 1:  Numbers  ', '  page 1',
'Chapter 2:  Letters  ', ' page 72',
'Chapter 3:  Variables', 'page 181']
lineWidth = 50
puts 'Table of Contents'.center(lineWidth)
puts ''
i = 0
j = 1
while i < toc.length
puts (toc[i].ljust(lineWidth/2) + toc[j].rjust(lineWidth/2))
i += 2
j += 2
end

雑感

 練習問題二問目が手強かったけど、勉強になった。次チャプター以降から、さらに深く(そして難しく)なっていく。ついていけるかな・・・。

See also

閏年(Leap Year)判別コード

 というわけで(id:heydays:20080508:1210235785)、模範解答を参考に閏年(Leap Year)判別コードを見直してみる。こうして見直してみると、プログラム初心者丸出しで恥ずかしいことこの上ないけど、そこら辺は気にしない気にしない。

Leap Years. Write a program which will ask for a starting year and an ending year, and then puts all of the leap years between them (and including them, if they are also leap years). Leap years are years divisible by four (like 1984 and 2004). However, years divisible by 100 are not leap years (such as 1800 and 1900) unless they are divisible by 400 (like 1600 and 2000, which were in fact leap years). (Yes, it’s all pretty confusing, but not as confusing has having July in the middle of the winter, which is what would eventually happen.)

6. Flow Control

 この練習問題の僕の解答は以下だった。

puts 'Enter a start year.'
sYear = gets.chomp
puts ''
puts 'Enter an end year.'
eYear = gets.chomp
puts ''
if sYear > eYear
puts 'An end year must be equal to or greater than a start year.'
else
puts 'The leap years between ' + sYear.to_s + ' and ' + eYear.to_s + ' are listed below.'
puts ''
while sYear.to_i != (eYear.to_i + 1)
aYear = sYear.to_i % 4
bYear = sYear.to_i % 100
cYear = sYear.to_i % 400
if aYear == 0
if bYear != 0
puts sYear.to_s
else
if cYear == 0
puts sYear.to_s
end
end
end
sYear = sYear.to_i + 1
end
end

 そして、id:Kiskeさんの模範解答(id:Kiske:20070705:1183627478)は以下。

puts '開始年を入力.'
from = gets.chomp.to_i
puts '終了年を入力.'
to = gets.chomp.to_i
puts "#{from}年~#{to}年のうるう年一覧"
while from <= to
if (from % 4 == 0 and from % 100 != 0 or from % 400 == 0)
puts from.to_s + ''
end from = from + 1
end

rubyチュートリアルを試してみる その2 – note-phper

なるほどー。

こうして見ると、もう全然だめですな、僕のコードは。この練習問題のキーである閏年をいかに判別するか、っていうところが僕の書いたコードだと何かしつこい。

閏年は以下のルールから判別する。

  • 4で割り切れる
  • かつ、100で割り切れない
  • 100で割り切れる場合、400で割り切れれば、閏年

これを、if文一行で書けるってことに気付かなかった。勉強になりました。

あと、『gets.chomp』を『gets.chomp.to_i』とすることで、変数に入力した文字列を数(Integer)として扱うことができる、っていうのも気付かなかったなあ。なるほど。

 というわけで、僕の書いたコードを上記模範解答を参考にして、書き換えてみる。

puts 'Enter a start year.'
sYear = gets.chomp.to_i
puts ''
puts 'Enter an end year.'
eYear = gets.chomp.to_i
puts ''
if sYear > eYear
puts 'An end year must be equal to or greater than a start year.'
else
puts 'The leap years between ' + sYear.to_s + ' and ' + eYear.to_s + ' are listed below.'
puts ''
while sYear <= eYear
if (sYear % 4 == 0 and sYear % 100 != 0 or sYear % 400 == 0)
puts sYear.to_s
end
sYear = sYear + 1
end
end

んー、シンプル。

Many thanks to id:Kiske

See also

模範解答発見!

 id:Kiskeさんという方が、僕と同じようにダイアリーに練習問題の解答を記録しているのを見つけました。

 コードがシンプルで素敵です。特に、閏年(Leap Year)判別コードを見たときは、自分の書いたコード(id:heydays:20080508:1210225720)が随分と鼻タレだったということに気付き、泣き笑いしました。自分の頭で悶々と考えるのも大事だけど、ちゃんとしたコードを参考にするっていうのも同じくらい大事なんだなと、思い知る次第です。

僕は今、7. Arrays and Iteratorsに取り掛かっているところ。これからどんどん練習問題が複雑化していくなあと感じていたので、模範解答を見つけることができて、ラッキーです。とはいえ、自分の頭で練習問題コードを書ききってから、模範解答を参考にしていかねば、です。

 id:Kiskeさん、勝手に模範解答として参考にさせていただきますので、宜しくお願いします。

See also

A Few Things to Try on 6. Flow Control

 Rubyでプログラミング勉強中(参照)。

 本当は毎日ちょっとずつでもプログラムを書いて勉強していこうなんて意気込んでいたんだけど、日々のアレコレに紛れて、なかなか・・・。ま、いっか。のんびりいきましょ。

 というわけで、今日は、Chapter 6. Flow Control(参照)。BRANCHING(if文)やらLOOPING(while)が登場。これまでのChapterに比べると、ぐっと難しく、そんでもって楽しくなってきた。

A Few Things to Try on 6. Flow Control

一問目

“99 bottles of beer on the wall…” Write a program which prints out the lyrics to that beloved classic, that field-trip favorite: “99 Bottles of Beer on the Wall.”

6. Flow Control

※”99 bottles of beer on the wall”っていうのは、マザーグースの歌らしい。日本語訳(参照)に出力例が出ている。

ちょっと考えたけど、以下な感じで落ち着いた。出力例通りに出力されたので、OKかな。

beer = 99
while beer != 0
puts beer.to_s + ' Bottles of beer on the wall'
puts beer.to_s + ' Bottles of beer'
puts 'Take on down and pass it around'
beer = beer - 1
puts beer.to_s + ' Bottles of beer on the wall'
puts ''
end

二問目

Write a Deaf Grandma program. Whatever you say to grandma (whatever you type in), she should respond with HUH?! SPEAK UP, SONNY!, unless you shout it (type in all capitals). If you shout, she can hear you (or at least she thinks so) and yells back, NO, NOT SINCE 1938! To make your program really believable, have grandma shout a different year each time; maybe any year at random between 1930 and 1950. (This part is optional, and would be much easier if you read the section on Ruby’s random number generator at the end of the methods chapter.) You can’t stop talking to grandma until you shout BYE.

  • Hint: Don’t forget about chomp! ‘BYE’with an Enter is not the same as ‘BYE’ without one!
  • Hint 2: Try to think about what parts of your program should happen over and over again. All of those should be in your while loop.

    6. Flow Control

耳が遠いおばあちゃんとの会話プログラム。Hintにもあるとおり、while loopがKeyですな。『any year at random between 1930 and 1950』っていうのをどう書いたらいいのか迷ったけど、結局ここでもwhile文を使った。他に書き方あるのかな・・・。

puts 'Hi, Granma.'
iSay = gets.chomp
while iSay != iSay.upcase
puts 'HUH? SPEAK UP, SUNNY!'
iSay = gets.chomp
end
while iSay != 'BYE'
rYear = 1
while rYear <= 1930
rYear = (rand(1951))
end
puts 'NO, NOT SINCE ' + rYear.to_s + '!'
iSay = gets.chomp
end
puts 'Okay.... bye for now...'

三問目

Extend your Deaf Grandma program: What if grandma doesn’t want you to leave? When you shout BYE, she could pretend not to hear you. Change your previous program so that you have to shout BYE three times in a row. Make sure to test your program: if you shout BYE three times, but not in a row, you should still be talking to grandma.

6. Flow Control

BYEを三回連続で叫ばないと耳の遠いおばあちゃんとの会話が終わらないように二問目のコードを変更する。この『三回連続』っていうとこで、ちょっとはまった。二回連続で言った後に、BYE以外の言葉を言ったら、カウントがリセットされるっていうのが漏れてて、悩んだ。で、結局以下のようなコードに。

puts 'Hi, Granma.'
iSay = gets.chomp
while iSay != iSay.upcase
puts 'HUH? SPEAK UP, SUNNY!'
iSay = gets.chomp
end
while iSay != 'BYE'
rYear = 1
while (rYear <= 1930)
rYear = (rand(1951))
end
puts 'NO, NOT SINCE ' + rYear.to_s + '!'
iSay = gets.chomp
end
iBye = 1
while iBye != 3
puts 'HUH? WHAT DID YOU SAY?'
iSay = gets.chomp
if iSay == 'BYE'
iBye = iBye + 1
else
iBye = 0
end
end
puts 'Okay.... bye for now...'

四問目

Leap Years. Write a program which will ask for a starting year and an ending year, and then puts all of the leap years between them (and including them, if they are also leap years). Leap years are years divisible by four (like 1984 and 2004). However, years divisible by 100 are not leap years (such as 1800 and 1900) unless they are divisible by 400 (like 1600 and 2000, which were in fact leap years). (Yes, it’s all pretty confusing, but not as confusing has having July in the middle of the winter, which is what would eventually happen.)

6. Flow Control

入力した年と年の間の閏年を一覧出力するプログラム。閏年の算出って結構ややこしいってことは知ってたけど、これをプログラムに落とすっていうのはなかなか頭を使った。まずは、『入力した年と年の間のう閏年を一覧出力』を考える前に、閏年判別プログラムを書いてみる。

(注: 以下の回答はかなりへタレ。模範解答を参考に書き直した ⇒ id:heydays:20080508:1210237624)

puts 'Enter a year.'
iYear = gets.chomp
aYear = iYear.to_i % 4
bYear = iYear.to_i % 100
cYear = iYear.to_i % 400
if aYear == 0
if bYear != 0
puts iYear.to_s + ' is the leap year.'
else
if cYear == 0
puts iYear.to_s + ' is the leap year.'
else
puts iYear.to_s + ' is NOT the leap year.'
end
end
else
puts iYear.to_s + ' is NOT the leap year.'
end

うむ、いい感じ。で、『入力した年と年の間のう閏年を一覧出力』するプログラムは、以下な感じで。一応、『start year <= end year』チェックを入れてみた。

puts 'Enter a start year.'
sYear = gets.chomp
puts ''
puts 'Enter an end year.'
eYear = gets.chomp
puts ''
if sYear > eYear
puts 'An end year must be equal to or greater than a start year.'
else
puts 'The leap years between ' + sYear.to_s + ' and ' + eYear.to_s + ' are listed below.'
puts ''
while sYear.to_i != (eYear.to_i + 1)
aYear = sYear.to_i % 4
bYear = sYear.to_i % 100
cYear = sYear.to_i % 400
if aYear == 0
if bYear != 0
puts sYear.to_s
else
if cYear == 0
puts sYear.to_s
end
end
end
sYear = sYear.to_i + 1
end
end

雑感

 ふー。今回は、前回までのそれと比べて、随分と頭を使った。おかげで随分と理解が深まった。四問目で書いた『閏年判定プログラム』は、実際に意外と役立つプログラムだったりするので、何だか小さな達成感。けど、もっと上手に書くことが出来るような気がしないでもない。慣れてきてから振り返ってみるか。

See also

A Few Things to Try on 5. More About Methods

 Rubyでプログラミング勉強中(参照)。

 今日は、Chapter 5. More About Methods(参照)でMethodの基礎を学ぶ。ObjectとMethodについての理解がちょっとだけ深まった。以下のくだりが個人的には非常に分かりやすかったかな。

So far we’ve seen a number of different methods, puts and gets and so on (Pop Quiz: List all of the methods we have seen so far! There are ten of them; the answer is below.), but we haven’t really talked about what methods are. We know what they do, but we don’t know what they are.

But really, that is what they are: things that do stuff. If objects (like strings, integers, and floats) are the nouns in the Ruby language, then methods are like the verbs. And, just like in English, you can’t have a verb without a noun to do the verb. For example, ticking isn’t something that just happens; a clock (or a watch or something) has to do it. In English we would say, “The clock ticks.” In Ruby we would say clock.tick (assuming that clock was a Ruby object, of course). Programmers might say we were “calling clock’s tick method,” or that we “called tick on clock.”

5. More About Methods

 というわけで、以下、このChapterの練習問題記録。

A Few Things to Try on 5. More About Methods

一問目

• Write an Angry Boss program. It should rudely ask what you want. Whatever you answer, the Angry Boss should yell it back to you, and then fire you. For example, if you type in I want a raise., it should yell back WHADDAYA MEAN “I WANT A RAISE.”?!? YOU’RE FIRED!!

5. More About Methods

これは、簡単やね。別にupcase methodを使う必要もないのだけど、ObjectとMethodの理解を深めるために蛇足と知りつつ、使ってみた。

puts 'I said..'
iSay = gets.chomp
puts 'Whaddaya mean '.upcase + '"' + iSay.upcase + '"?!? ' + 'You\'re fired!!'.upcase

二問目

• So here’s something for you to do in order to play around more with center, ljust, and rjust: Write a program which will display a Table of Contents so that it looks like this:

5. More About Methods

Table of Contents
Chapter 1:  Numbers                        page 1
Chapter 2:  Letters                       page 72
Chapter 3:  Variables                    page 118

これも、このChapterをきちんと読めば楽勝。

lineWidth = 50
puts ''
puts 'Table of Contents'.center (lineWidth)
puts ''
puts 'Chapter 1:  Numbers  '.ljust (lineWidth/2) + '  page 1'.rjust (lineWidth/2)
puts 'Chapter 2:  Letters  '.ljust (lineWidth/2) + ' page 72'.rjust (lineWidth/2)
puts 'Chapter 3:  Variables'.ljust (lineWidth/2) + 'page 181'.rjust (lineWidth/2)

雑感

 このChapter 5. More About Methodsまでで、基本の基本の基本部分を終えたという感じ。次回は、Flow Control(制御構造)。if文とかwhile文が登場して、さらに楽しくなっていきそう。

See also

A Few Things to Try on 4. Mixing It Up

 Rubyでプログラミング勉強中(参照)。

 NumbersLettersVariables and Assignmentと学び、それらをMix Upした内容が、Chapter 4. Mixing It Up。まだまだ基本中の基本中の基本の段階です。以下、この章の練習問題記録。

A Few Things to Try on 4. Mixing It Up

一問目

Write a program which asks for a person’s first name, then middle, then last. Finally, it should greet the person using their full name.

4. Mixing It Up

小細工せず、素直に書く。

puts 'What\'s your first name?'
fName = gets.chomp
puts 'My first name is ' + fName + '.'
puts ''
puts 'What\'s your middle name?'
mName = gets.chomp
puts 'My middle name is ' + mName + '.'
puts ''
puts 'And what\'s your last name?'
lName = gets.chomp
puts 'My last name is ' + lName + '.'
puts ''
puts 'Thank you, nice to meet you, ' + 'Mr./Ms. ' + fName + ' ' + mName + ' ' + lName + '.'

二問目

Write a program which asks for a person’s favorite number. Have your program add one to the number, then suggest the result as a bigger and better favorite number. (Do be tactful about it, though.)

4. Mixing It Up

これも素直に書く。

puts 'What is your faivorite number?'
fNum = gets.chomp
puts 'My faivorite number is ' + fNum + '.'
puts ''
puts 'Hmmm, I think that ' + (fNum.to_i + 1).to_s + ' is more suitable number for you.'

雑感

 先にも書いたけど、まだまだ基本中の基本中の基本の段階。つまずく要素も全くなし。それでも結構楽しい。

See also

A Few Things to Try on 1. Numbers

 30過ぎて始めたプログラムの勉強(参照)の先生&テキストであるLearn to Programには、いくつかのチャプターの最後に『A Few Things to Try』(練習問題)が用意されている。ただチュートリアルを読むだけではなく、実際に頭を使ってコードを書くのは、それが身につくだけではなく、なかなかに楽しい。

 ただ、その『A Few Things to Try』(練習問題)には回答が用意されていない。コードを書いて実行した結果を見て、その結果が合っていることは分かるとしても、そのコードがシンプルに正しく、言い換えれば美しく書かれているのか、というのは正直分からない。なので、ここに晒してみることにした。もしかしたら、誰かの突込みをもらえるかもしれないし、後になって自分で見て、恥ずかしくも微笑ましい気持ちになれるかもしれない。

 というわけで、Chapter 1. Numbersの『A Few Things to Try』のMy回答。

A Few Things to Try on 1. Numbers

Write a program which tells you:

  • how many hours are in a year?
  • how many minutes are in a decade?
  • how many seconds old are you?
  • how many chocolates do you hope to eat in your life?
    Warning: This part of the program could take a while to compute!

Here’s a tougher question:

  • If I am 1001 million seconds old, how old am I?

1. Numbers

How many hours are in a year?

簡単簡単。

puts 24 * 365

How many minutes are in a decade?

これも簡単。

puts 60 * 24 * 365 * 10

How many seconds old are you?

こんな感じで。

puts 60 * 60 * 24 * 365 * 32

If I am 1001 million seconds old, how old am I?

むむむ。こんな感じか。

puts 1001000000 / (60 * 60 * 24 * 365)

See also

Getting Started

 『何事も始めるのに遅すぎるということはない』と誰かが言っている通り、プログラミングを30歳超えて始めるのも遅すぎるなんてことはない、ということだ。

 というわけで、Rubyの勉強を始めた。プログラミングは、もう8年近く前にほんのちょっとかじった程度なので、ほとんど素人・初心者である。そんな30過ぎ男に最適なテキストはないか、と検索してみると、Learn to Program, by Chris Pineが見つかった。簡単な英語で書かれているので、原文のままでも十分勉強できるけど、とても良質な日本語訳(参照)もあるので、原文をベースに、ちょっと理解しづらいような部分を日本語訳と照らし合わせながら勉強している。このGW休みは、ちょっとしたハプニングがあり出かけることができないので、家で読書かDVDかプログラム。そんな休日も悪くない。というか、プログラミング、楽しい。

 とはいえ、ただ勉強していても続かない。なので、何かアプリを作る、というのを一応ゴールにしている。勉強した先に作りたいアプリのアイデアがいくつかある(プチアプリばかりだけど)ので、それらを作るまでは続けていく。というよりも、そのアイデアのいくつかを思いついたから、プログラムを書きたくなった、という感じ。

 ま、いずれにしても、飽きるまでプログラム楽しんでいこうと思う。

See also