Help us understand the problem. What is going on with this article?

Python2で競技プログラミングする時に知っておきたいtips(制御構造編)

More than 1 year has passed since last update.

Python2で競技プログラミングする時に知っておきたいtipsの,制御構造についての部分を分割しました.

Pythonのバージョンは2.7.5(Python3では,入出力などの仕様が大きく異なるので,他の記事を参照することをおすすめします).

条件分岐

条件式に変数を渡す

個人的にはあまり好きではないが,コード量削減のために,

while 1:
    a = input()
    if not a: 
        break
    # ...   

みたいに,if文,while文などの条件に変数を渡すことが多い気がする.

PythonでIf文に変数を入れたときの結果 - LIFE WITH PYTHON

結果
int 0ならFalse,それ以外ならTrue
float 0.0ならFalse,それ以外ならTrue
str ''(空文字)ならFalse,それ以外ならTrue
list []ならFalse,それ以外ならTrue
tuple ()ならFalse,それ以外ならTrue
dict {}ならFalse,それ以外ならTrue
set set()ならFalse,それ以外ならTrue
None False

処理を途中で終了したい

入力の終わりを表す記号や,コーナーケースが入力された場合など,途中でスクリプトの実行を終了してしまった方が楽な場合がある.
このような場合は,quit()またはsys.exit()を使うとよい.

a = input()
if a == 0:
    quit()
# ...
import sys

a = input()
if a == 0:
    sys.exit()
# ...  

繰り返し

range()とxrange()

2. 組み込み関数 — Python 2.7ja1 documentation

Pythonで「○○をn回行う」と言った単純な繰り返しを実装する場合は,

n = 5

for i in range(n):
  print i
# 0
# 1
# 2
# 3
# 4

または,

n = 5

for i in xrange(n):
  print i
# 0
# 1
# 2
# 3
# 4

のように書くのが一般的.

ここで,range(n)xrange(n)は,それぞれ,0からnまでの整数を昇順に並べたlistオブジェクト,xrangeオブジェクトを返す.
xrangeオブジェクトは,遅延評価を用いることで,値が必要とされるときに取り出すことの出来るオブジェクト.
nが非常に多くなる場合,range(n)ではリストを生成してからループを行うため,メモリ使用量が大きくなってしまうが,xrange(n)ではそれが避けられる.
また,速度についても,一部の場合を除いてxrange()の方が高速.
python - Should you always favor xrange() over range()? - Stack Overflow

また,(x)rangeでは,第2,第3引数を用いたり,reversed()を用いることで,いろいろな範囲の表現ができる.

# range(start, stop)で,startからstop-1までの整数すべてを昇順に並べたリストを返す
print range(2, 6) # [2, 3, 4, 5]

# range(start, stop, step)で,startからstepおきに値を増やしていって得られる整数の内,stop-1までのすべてのものを昇順に並べたリストを返す
print range(5, 30, 5) # [5, 10, 15, 20, 25]

# reversed()でリストを逆順にできる
for i in reversed(range(5)):
    print i
# 4
# 3
# 2
# 1
# 0

for文での変数の展開

for文で,

l = [1, 2, 3, 4, 5]
for e in l:
    print e
output
1
2
3
4
5

のように,リストの各要素を展開できるが,これは,

l = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
for i, e in l:
    print '#{0}: #{1}'.format(i, e)
output
0: a
1: b
2: c
3: d

のようにもできる.

enumerate

forループを回す際,リストのインデックスと値が同時に取得できるといい場合がある.

enumerate()は,引数のリストに対して,インデックスとその値を持つイテレータを返す.

l = ['a', 'b', 'c', 'd']
for elem in enumerate(l):
    print elem
# (0, 'a')
# (1, 'b')
# (2, 'c')
# (3, 'd')

# 上のコードは下記のコードと等価
for i in range(len(l)):
    print (i, l[i])

for-else,while-else文

Pythonでは,for文,while文にelse節を加えることができる.
この際,else節は,ループ終了までに一度も内部でbreakされなかった場合のみ呼び出される.

a = [1, 2, 3, 4, 5]
b = [1, 2, 4, 5]
x = 3

def find_val(l, x):
    for i in range(len(l)):
        if l[i] == x:
            print i
            break
    else:
        print 'Not found...'

# 上のfind_val()と等価なコード
def find_val2(l, x):
    flag = False
    for i in range(len(l)):
        if l[i] == x:
            print i
            flag = True
            break
    if not flag:
        print 'Not found...'

find_val(a, x) # 2
find_val(b, x) # Not found...

「xを探せ.見つからなかった時は'hoge'を出力しろ」みたいな設問の際,フラグを持つ必要が無いため,非常に書きやすくて便利.
ただし,ループが多重になる場合はかえって見通しが悪くなるため,使わない方がよい.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away