range
for文やwhile文を使って、何らかの問題を解く際に、インデックスをうまく動かす必要がある。そうすることで配列の値をうまく動かせるので、インデックスとは仲良くないといけない。とりあえず簡単にrangeの使い方をまとめておく。以降、ここではlen_array
は5
とする。
5回繰り返したいのであれば、range()
に数値ないし数値が入っている変数を入れればよい。そうすれば0,1,2,3,4とインデックスが動き、5回の繰り返しが行われる。
len_array = 5
for i in range(len_array):
print('i={}'.format(i), end=' ')
i=0 i=1 i=2 i=3 i=4
このように指定しても、0,1,2,3,4とインデックスが動き、5回の繰り返しが行われる。インデックス0からインデックス4まで、1間隔で繰り返したいというような意味。
for i in range(0, 5, 1):
print('i={}'.format(i), end=' ')
i=0 i=1 i=2 i=3 i=4
この数字の渡し方を反対にして、間隔を-1
にすると、4,3,2,1,0とインデックスを逆から動かせる。i
とj
なんかのインデックスがあるループを考えた際に、これを使えばi
は大きくなるけど、j
は小さくなる、みたいなインデックスの動かし方ができる。
for i in range(4, -1, -1):
print('i={}'.format(i), end=' ')
i=4 i=3 i=2 i=1 i=0
while文
while文の基礎をまとめておく。while文は判定条件にあわせてループし続ける。1個目のものはi < len_array
という条件なので、i
がlen_array
よりも小さい間はループし続けるということになる。ループの度にインクリメントされるので、0,1,2,3,4で判定がFalse
となりループが終了する。
i = 0
while i < len_array:
print('i={}'.format(i), end=' ')
i += 1
i=0 i=1 i=2 i=3 i=4
while True:
if i >= len_array:
break
print('i={}'.format(i), end=' ')
i += 1
i=0 i=1 i=2 i=3 i=4
while文とfor文の使い分けはこんな感じなのだろうか。
- ある入力が行われるまで繰り返す
- ある値に達するまで繰り返す
- 無限に繰り返す
breakとcontinue
こんなwhile文があったとして、途中でループを抜けたい、ループ途中で処理を飛ばしたい場合にbreak
やcontinue
が役立つ。i >= len_array
という条件が満たされるとループが終了するし、i == 3
の場合、print()
が実行されないので、0,1,2,4とインデックスが動く。
i = 0
while True:
if i >= len_array:
break
if i == 3:
i += 1
continue
print('i={}'.format(i), end=' ')
i += 1
i=0 i=1 i=2 i=4
while else
while else
は、while文が終了した際に実行される。この場合、インデックスが0,1,2,3,4とループが終了した後に、While Else Exec
というprint()
が実行される。
i = 0
while i < len_array:
print('i={}'.format(i), end=' ')
i += 1
else:
print('While Else Exec')
i=0 i=1 i=2 i=3 i=4 While Else Exec
break
が実行された場合、インデックスが0,1,2,3でループが終了する。
i = 0
while i < len_array:
if i == 4:
break
print('i={}'.format(i), end=' ')
i += 1
else:
print('While Else Exec')
i=0 i=1 i=2 i=3
インデックスと仲良くなる
基本的なおさらいが終わったので、ここからが本題。インデックスと仲良くなる。while文でfor文を表すことができるし、逆にfor文でwhile文を表すことができるので、2重のfor-for
をfor-while
で書き直し、色んなパターンでやっていく。いろんな書き方できると思うけど、あくまでも一例。
2重ループ
2重ループをfor文とwhile文でやっていく。
for i in range(len_array):
print('i={}'.format(i), end=' ')
for j in range(len_array):
print('j={}'.format(j), end=' ')
print()
i=0 j=0 j=1 j=2 j=3 j=4
i=1 j=0 j=1 j=2 j=3 j=4
i=2 j=0 j=1 j=2 j=3 j=4
i=3 j=0 j=1 j=2 j=3 j=4
i=4 j=0 j=1 j=2 j=3 j=4
j = 0
を初期化する場所はi
のループの中にする。
i = 0
while i < len_array:
print('i={}'.format(i), end=' ')
j = 0
while j < len_array:
print('j={}'.format(j), end=' ')
j += 1
i += 1
print()
i=0 j=0 j=1 j=2 j=3 j=4
i=1 j=0 j=1 j=2 j=3 j=4
i=2 j=0 j=1 j=2 j=3 j=4
i=3 j=0 j=1 j=2 j=3 j=4
i=4 j=0 j=1 j=2 j=3 j=4
ド頭でi
と一緒に初期化するとうまく行かない。j
がi
の1回目のループで5までインクリメントされるので、i
の2回目のループで、j < len_array
がFalse
になってしまうので。
i = 0
j = 0
while i < len_array:
print('i={}'.format(i), end=' ')
while j < len_array:
print('j={}'.format(j), end=' ')
j += 1
i += 1
print()
i=0 j=0 j=1 j=2 j=3 j=4
i=1
i=2
i=3
i=4
内側jのwhile文の回数を外側iのfor文の値で制御
内側のループの回数を外側のループの値で制御する。i
のループの度に、j
のループの回数を減らす。
for i in range(len_array):
print('i={}'.format(i), end=' ')
for j in range(len_array - i):
print('j={}'.format(j), end=' ')
print()
i=0 j=0 j=1 j=2 j=3 j=4
i=1 j=0 j=1 j=2 j=3
i=2 j=0 j=1 j=2
i=3 j=0 j=1
i=4 j=0
while文の部分でlen_array - i
とすると、i
がインクリメントされる度に、j
の終了条件が小さくなるので、このようなインデックスの動きになる。j
のインデックスは大きくしていきたいので、j += 1
でインクリメントする。
for i in range(len_array):
print('i={}'.format(i), end=' ')
j = 0
while len_array - i > j:
print('j={}'.format(j), end=' ')
j += 1
print()
i=0 j=0 j=1 j=2 j=3 j=4
i=1 j=0 j=1 j=2 j=3
i=2 j=0 j=1 j=2
i=3 j=0 j=1
i=4 j=0
さきほどのj
のインデックスが大きい方から始まる版。
for i in range(len_array):
print('i={}'.format(i), end=' ')
for j in range(len_array-i-1, -1, -1):
print('j={}'.format(j), end=' ')
print()
i=0 j=4 j=3 j=2 j=1 j=0
i=1 j=3 j=2 j=1 j=0
i=2 j=2 j=1 j=0
i=3 j=1 j=0
i=4 j=0
ここではj = len_array-i-1
として、i
がインクリメントされる度に、j
の条件を小さくする。j
のインデックスは小さくしていきたいので、j -= 1
でデクリメントする。
for i in range(len_array):
print('i={}'.format(i), end=' ')
j = len_array-i-1
while j >= 0:
print('j={}'.format(j), end=' ')
j -= 1
print()
i=0 j=4 j=3 j=2 j=1 j=0
i=1 j=3 j=2 j=1 j=0
i=2 j=2 j=1 j=0
i=3 j=1 j=0
i=4 j=0
似たような感じなので説明はなし。
for i in range(len_array):
print('i={}'.format(i), end=' ')
for j in range(i + 1):
print('j={}'.format(j), end=' ')
print()
i=0 j=0
i=1 j=0 j=1
i=2 j=0 j=1 j=2
i=3 j=0 j=1 j=2 j=3
i=4 j=0 j=1 j=2 j=3 j=4
for i in range(len_array):
print('i={}'.format(i), end=' ')
j = 0
while j <= i:
print('j={}'.format(j), end=' ')
j += 1
print()
i=0 j=0
i=1 j=0 j=1
i=2 j=0 j=1 j=2
i=3 j=0 j=1 j=2 j=3
i=4 j=0 j=1 j=2 j=3 j=4
さきほどはj
が0始まりだったけど、こっちはお尻のインデックス始まり。
for i in range(len_array):
print('i={}'.format(i), end=' ')
for j in range(i, -1, -1):
print('j={}'.format(j), end=' ')
print()
i=0 j=0
i=1 j=1 j=0
i=2 j=2 j=1 j=0
i=3 j=3 j=2 j=1 j=0
i=4 j=4 j=3 j=2 j=1 j=0
for i in range(len_array):
print('i={}'.format(i), end=' ')
j = i
while j >= 0:
print('j={}'.format(j), end=' ')
j -= 1
print()
i=0 j=0
i=1 j=1 j=0
i=2 j=2 j=1 j=0
i=3 j=3 j=2 j=1 j=0
i=4 j=4 j=3 j=2 j=1 j=0
剰余とかもつかってみる
割り算のあまりである剰余を使うと、特定の規則的を使いつつインデックスを操作できる。例えば、j
のループはj % 2 == 0
がTrue
のときだけ実行する。
for i in range(len_array):
print('i={}'.format(i), end=' ')
j = i
while j >= 0 and j % 2 == 0:
print('j={}'.format(j), end=' ')
j -= 1
print()
i=0 j=0
i=1
i=2 j=2
i=3
i=4 j=4
他にも、while文のループはi
つまりj % 2 == 0
がTrue
のときだけ実行する。
for i in range(len_array):
print('i={}'.format(i), end=' ')
j = i
if j % 2 == 0:
while j >= 0:
print('j={}'.format(j), end=' ')
j -= 1
print()
i=0 j=0
i=1
i=2 j=2 j=1 j=0
i=3
i=4 j=4 j=3 j=2 j=1 j=0
for文とwhile文の使い分け
例えば複利の計算で下記のように計算するとプログラムが強調される部分が異なる。for文の場合は「10年後」という何年繰り返すという条件が強調されている。つまり、回数指定が行われている繰り返し。
amount = 10000
year = 10
for i in range(10):
amount *= 1.05
print('10 years later it will be {} yen.'.format(int(amount)))
10 years later it will be 16288 yen.
一方で、while文の場合は「20000円を超えるまで」が強調されているのがわかるのと、20000円を超えるのに何年ループさせればよいのかがわからないので(私はパッとわからない…泣)、このような場合はwhile文のほうが適している。つまり、回数指定がない繰り返しの場合。
amount = 10000
year = 0
while amount <= 20000:
year += 1
amount *= 1.05
print('It will be over 20000 yen in {} years.'.format(year))
It will be over 20000 yen in 15 years.
f(x)=0になるようなxを求めるアルゴリズムであるニュートン法なんかのプログラムを見ると、近似解を求めるために、誤差が許容範囲内になるまで繰り返すように記述されていたりするので、どんだけ繰り返せばよいのかわからないので、for文ではなくwhile文が適している。