コンピュータリテラシー演習のページへ
Rubyによるはじめてのプログラミング

同じことを繰り返してみよう

コンピュータの得意とする、繰り返しをプログラミングしてみましょう。 もしあなたが足し算を10回しろと言われれば、ちょっといやかもしれませんが、 できるでしょう。でも、1000回しろとか10000回しろと言われれば、まず断る でしょう。人間にとっては同じことを繰り返すのがとても苦痛です。 しかし、コンピュータなどの機械は文句も言わず同じことを繰り返すことができます。 むしろ、その場の状況に応じて臨機応変に対応するといったことのほうが、 コンピュータにとっては大変です。

n回繰り返してみよう

例えば、print "Hello!\n" を5回繰り返してみましょう。

loop1.rb : 決まった回数だけ繰り返すプログラム
5.times do
  print "Hello\n"
end

こんどは繰り返しを10回にしてみましょう。

10.times do
  print "Hello\n"
end

このように 回数.times という風に書けば、 do から end までで囲った文を、 その回数だけ繰り返します。

なお、以下のように、do{ に、 end} に置き換えた書き方もあります。 どちらも動作は全く同じです。
10.times {
  print "Hello\n"
}

ところで、もちろん回数のところに変数を使ってもかまいません。以下の場合10回繰り返します。

loop3.rb : 変数の回数だけ繰り返すプログラム
a = 5 + 5
a.times do
  print "Hello\n"
end

前に紹介したキーボードからデータを入力しようのテクニックを使えば、「キーボードから入力した回数だけ繰り返す」なんてプログラムも作れます。

loop4.rb : キーボードから入力した回数だけ繰り返すプログラム
print "繰り返す回数を入力してください:"
a = gets.to_i
a.times do
  print "Hello\n"
end

for文を使ってみよう

今紹介した、回数.timesという書き方は、Ruby特有のものです。 多くの言語では、繰り返しをする時に、for文やwhile文というものを使います。 ここではfor文を使ってみます。

for文を使った繰り返しは以下のようになります。

for1.rb : 簡単なfor文のプログラム
for i in 1..5
  print "Hello\n"
end

この場合、5回繰り返します。

今何回目?

なぜ、以上の書き方で5回繰り返すのでしょうか。以上のプログラムを少しだけ書き変えて見ます。

for2.rb : 簡単なfor文のプログラム
for i in 1..5
  print "今", i, "回目です\n"
end

以下のような結果が出たでしょう。

今1回目です
今2回目です
今3回目です
今4回目です
今5回目です

実は、1..5 と書いた部分が、「1から始めて5で終わる」という意味になっています。 そこで、最初は1、次は2、次は3、次は4、最後が5といった具合に変数iの値が増えているのです。

つまり、for文は、for 繰り返し用変数 in 初期値..終了値 という風になっていて、次のように動きます。

  1. 最初は繰り返し用変数を初期値にして、繰り返しを1回する。
  2. 繰り返し変数を1つ増やし、繰り返しを1回する
  3. 繰り返し変数が終了値になったら、繰り返しを1回して、終了する。

つまり、上のプログラムだと、繰り返し用変数が i 、 初期値が 1 、終了値が 5 ですから、

  1. 最初は変数iを1にして繰り返す
  2. 変数iを2にして繰り返す
  3. 変数iを3にして繰り返す
  4. 変数iを4にして繰り返す
  5. 最後に変数iを5にして繰り返し、終了する

となります。以上、よく理解してください。

初期値を変えてみよう

以上の理屈が分かったかどうかを確認するためにも、以下のプログラムを打ち込んでみましょう。 そして、実行する前にどのような結果がでるか予想してから実行してください。予想した通りだったでしょうか?

for3.rb : 簡単なfor文のプログラム
for i in 3..5
  print "今", i, "回目です\n"
end

では、次のプログラムはどうでしょうか?

for i in 7..5
  print "今", i, "回目です\n"
end

何も表示されませんでした。初期値が終了値よりも大きいと、そもそも1回も繰り返しがされないのです。

変数名を変えてみよう

今までは、for文で変数iを使いましたが、別に他の変数名でも構いません。 繰り返しのことをループといい、繰り返し用変数のことをループ変数といいます。 ループ変数の名前は、伝統的に i を使うことが多く、i 以外に必要な場合は j、 次に k、l を使います。

変数iを使っていた代わりに変数loopを使うと以下のようになります。

for loop in 1..5
  print "今", loop, "回目です\n"
end

繰り返しの中で繰り返してみる

繰り返しの中で繰り返すことができます。このような繰り返しを2重ループといいます。

double_loop.rb : 2重ループのプログラム
for i in 1..5
  for j in 1..3
    print "i=", i, "j=", j, "\n"
  end
end

変数iを使ったループが外側のループ、変数jを使ったループが内側のループです。 2重ループの場合、内側のループをぐるぐると繰り返し、 それが終わったらそれが外側を1回繰り返したことになります。

以下のプログラムの結果を見て理解してください。

double_loop2.rb : 2重ループのプログラム
for i in 1..5
  print "外側のループ", i, "回目\n"
  # ここから内側のループ開始
  for j in 1..3
    print "内側のループ", j, "回目 iは", i, "\n"
  end
  # ここで内側のループ終了
end

ループは何重にもできます。以下は3重ループの例です。2重以上のループのことを多重ループといいます。 練習で「10重に挑戦!」などするのは構いませんが、実際には、多重にすればするほど分かりづらいプログラムになるので、 必要以上に何重にもしないほうがいいでしょう。

triple_loop.rb : 3重ループのプログラム
for i in 1..4
  for j in 1..3
    for k in 1..2
      print "i=", i, "j=", j, "k=", k, "\n"
    end
  end
end

while文を使ってみる

while文はある条件が成り立つ限り繰り返すという文で、for文に比べて単純です。 例えば、1から5まで繰り返すプログラムをwhile文で書くと以下のようになります。

while1.rb : 簡単なwhile文のプログラム
i = 1
while i <= 10
  print "今", i, "番目です。\n"
  i = i + 1
end

復習すると、これと同じことを行うfor文は以下のようになります。

for i in 1..10
  print "今", i, "番目です。\n"
end

while文はfor文に比べ単純な分、プログラムが長くなりがちです。 しかし、初期状態を作る(上記例: i = 1)、 繰り返す時に何かの値を変える(上記例: i = i + 1) といった処理が必要でない繰り返しの場合には、while文が適しています。

以下のプログラムを見てください。

inf_loop.rb : 無限ループのプログラム
while true
  print "あー"
end

while文の条件がtrueなので、永遠に繰り返します。実行したら、Control-C を押して止めてください。

このようなプログラムは意味がないと思うかもしれません。しかし、サーバのプログラムは24時間365日動きっぱなしが普通です。そのようなプログラムは基本的には無限ループです。

無限ループを止めてみる

サーバで無限ループを使うとはいっても、例えば「止まれ」という指令が来たら終了する、 といったことが必要になってきます。ループを途中で止めるにはbreak文を使います。

例えば、以下のようなキーボードから文字列を入力して、それを表示することを永遠に繰り返すプログラムがあったとしましょう。

break1.rb : 入力した文字列を永遠に表示するプログラム
while true
  s = gets.chop
  print s, "\n"
end

キーボードから入力した文字列が "end" であれば、繰り返しを終了するには以下のようなプログラムを書きます。

break2.rb : break文を使ったプログラム
while true
  s = gets.chop
  if (s == "end") then
    break
  end
  print s, "\n"
end

入力した文字列が "end" であれば、if文の条件が成り立ち、break文が実行されます。すると、ループが終了します。この場合、プログラムの最後に行くのでプログラムも終了します。

応用

あまり解説はしません。プログラムをよく読んで理解するように心がけてください。

九九を表示する

kuku.rb : 九九を表示するプログラム
for i in 1..9
  for j in 1..9
    print i*j, " "
  end
  # 改行する
  print "\n"
end

行の最後だけ改行しているところがミソです。 ただし、これでは数字がそろっていません。どうすればきちんと揃うか考えてみてください。ヒントは数値が1桁か2桁かということです。

文字で三角をつくる

triangle1.rb : * で三角を表示するプログラム
for i in 1..10
  # 内側のループで*をi個表示
  for j in 1..i
    print "*"
  end
  # 改行する
  print "\n"
end

これも行の最後だけ改行しているところがミソです。 内側のループの終了値に変数iを使っています。 このため終了値が刻々と変わることに注目してください。

合計を求める

5つの整数値の合計を求めるプログラムを考えてみましょう。 一番単純なのは、電卓のように使ってみることです。

print 50+70+65+100+45, "\n"

しかし、数値をキーボードから入力するためにはどうしたら良いのでしょうか? まずは変数を5つ用意してみます。

a = gets.to_i
b = gets.to_i
c = gets.to_i
d = gets.to_i
e = gets.to_i
print a+b+c+d+e, "\n"

しかし、これが100個、1000個の合計となるとどうでしょう。100個、1000個の変数を用意しなければならないのでしょうか。実はこのプログラムは変数1個で作ることができます。

a = gets.to_i
a = a + gets.to_i
a = a + gets.to_i
a = a + gets.to_i
a = a + gets.to_i
print a, "\n"

aにキーボードから入力した値を順に加えていくのです。それは結果的に合計値となります。

つぎにこれを繰り返しを使ってプログラムを作ってみましょう。 繰り返しを使うためには、同じことを繰り返すようにするとうまくいきます。 しかし、上のプログラムでは、最初の1回目の入力だけ、a = a + gets.to_iでなく、a = gets.to_iになっています。 これは、以下のように最初に a = 0 としてaの値をクリアしておくと、うまくいきます。

a = 0
a = a + gets.to_i
a = a + gets.to_i
a = a + gets.to_i
a = a + gets.to_i
a = a + gets.to_i
print a, "\n"

これなら、for文を使った繰り返しに変えられそうです。

a = 0
for i in 1..5
  a = a + gets.to_i
end
print a, "\n"

100個の合計でも、1000個の合計でも、5を100に、あるいは1000に変えるだけでうまくいくことに注目してください。

課題

  1. 1から10までの整数値の二乗と三乗の値を表示するプログラムを作成せよ。 ヒント:以下の1から10までの整数値を表示するプログラムが参考になる
    for i in 1..10
      print i
    end
  2. 以下のように、0から20までの整数値を順に表示するプログラムを作成せよ。 数値の間はカンマで区切り、最後に改行を入れる(ただしカンマを入れない)ことに注意せよ。
    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
  3. 10の階乗(10!)を求めるプログラムをfor文、もしくはwhile文を使って作成せよ。 なお、nの階乗とは、1×2×3×…×n である。
  4. キーボードから整数値を10個入力していき、最後にその合計値を表示するプログラムを作成せよ。
  5. 課題4のプログラムで、合計値と合わせて平均値も表示するようにせよ。
  6. 以下のプログラムでは、ウインドウに41本の線を描画する。 これをもう間隔を空けて以下の実行例のように11本の線を描画するように書き変えよ。
    require "tkclass"
    
    c = Canvas.new
    c.pack
    for i in 0..40
      Line.new(c,10,5*i+30,210-5*i,30)
    end
    Tk.mainloop

    なお、Line.new(c,x1,y1,x2,y2)でcという場所の(x1,y1)から(x2,y2)の座標に直線を引いている。
  7. 以下のような九九の表を表示するプログラムを作成せよ。
     1  2  3  4  5  6  7  8  9
     2  4  6  8 10 12 14 16 18
     3  6  9 12 15 18 21 24 27
     4  8 12 16 20 24 28 32 36
     5 10 15 20 25 30 35 40 45
     6 12 18 24 30 36 42 48 54
     7 14 21 28 35 42 49 56 63
     8 16 24 32 40 48 56 64 72
     9 18 27 36 45 54 63 72 81
    ヒント:九九の数値は、1桁の場合と2桁の場合があるが、 以前示したプログラムでは、どちらも1文字しか空白を入れていない。 数値が1桁の場合は空白2文字を、2桁の場合は空白1文字を入れるようにすればよい。
  8. 以下に示す図形のうち、最低2つを表示するプログラムを作成せよ。
    ※ なるべく難しいものに挑戦することが望ましい
    ただし、文字の個数(幅と高さ)は、整数型の変数n に入れておき、nを変える と幅や高さが変わるようにせよ。
    ※ 以下の例は n=5 の場合である
    *****       *            *           *           *    
     *****      **          ***         ***         ***   
      *****     ***        *****       *****       *****  
       *****    ****      *******     *******     ******* 
        *****   *****    *********   *********   *********
                ****                  *******    **** ****
                ***                    *****     ***   ***
                **                      ***      **     **
                *                        *       *       *
  9. キーボードから整数値を10個入力していき、その中の最大値と最小値を 表示するプログラムを作成せよ。
  10. 西暦1900年から2100年までの間のうるう年をすべて表示するプログラムを作成せよ。 うるう年の定義等については「キーボードからデータを入力する」の課題9を参照せよ。

東京情報大学情報システム学科
大見 嘉弘(Yoshihiro OHMI)
<ohmi@rsch.tuis.ac.jp>