A - 1.00.はじめに

Time Limit: 2 sec / Memory Limit: 1024 MB

次のページ

第 1 章について

第 1 章では、プログラムの基本的な文法について説明します。
第 1 章をマスターすれば、理論上は全ての「計算処理」を行うプログラムを書ける程の知識が身につきます。

APG4bPython の取り組み方

プログラミングの勉強では手を動かすことが重要です。練習問題はできるだけ解くようにしましょう。

ただし、「説明文中のプログラムを何も考えずに写す」というのは時間の無駄にしかならないことが多いです。
用意されているプログラムを動かすときはコピー&ペーストを使いましょう。

Python の特徴と選ぶ理由

競技プログラミングを始めるにあたって、どの言語を使うかで悩む方も多いと思います。 AtCoder では言語選択は恒久的なものではなく、問題ごとに柔軟に使い分けることもできますが、多くの参加者はほとんどの問題でひとつのメイン言語を使い続けていることも事実です。
このページを見ている方は、多少なりとも Python で競技プログラミングを始めようか検討されていることと思います。以下では、メイン言語として Python を選ぶメリット・デメリットを紹介します。

Python を使うメリット

文法が直感的

トップページでも書きましたが、 Python は文法が直感的でコードが書きやすく可読性が高いと言われています。競技プログラミングでは良い解法を思いついても、時間内にコードに書き出せないと得点が得られません。また 1 分 1 秒でも早く正解した方が有利になります。このため、書きやすいという特徴は有利に働きやすいと言えます1

多倍長整数

Python では多倍長整数が標準機能で簡単に扱えるため、問題によっては大きなアドバンテージになります。通常は煩雑な考察をすることを想定された問題でも、多倍長整数を使うことで、解法やコードが簡潔になることがあります。

Python を使うデメリット

実行速度

Python はインタプリタ言語であり、 C++ のようなコンパイル言語と比べるとどうしても実行速度が遅くなる傾向があります。
直近の AtCoder のコンテストでは、超上級者向けの問題の一部を除いて、コンテストで出題される問題のほとんどは Python (後述の CPython または PyPy)でも実行時間制限内に無理なく通すことができます。このため、解法は合ってるのに Python だから通せないということはほとんどありません。
もちろん、想定解よりも遅い解法を使う場合や Python が得意でない書き方をする場合などでは TLE (実行時間制限超過)になる可能性はあります。本プログラムでは、 Python を使う場合に TLE に引っかからないために気を付ける点についてもなるべく触れていく予定です(主に 2 章以降になる予定です)。

CPython と PyPy

AtCoder では、 Python コードの実行環境として CPythonPyPy が用意されています。 CPython と PyPy はいずれも Python の実行環境で、多くの場合は全く同じコードで全く同じアウトプットを返しますが、一部挙動が異なる場合があります。それぞれの特徴は以下の通りです。

  • CPython は Python の公式の実装です。
  • PyPy は JIT(Just-In-Time)コンパイル機能を持っています。 JIT コンパイルにより実行時にコードを機械語に変換することで、 CPython に比べて高速になることが多いです。

AtCoder における競技プログラミングでは、一部の例外を除き、基本的には PyPy で提出する方が実行時間制限の関係で有利になることが多いです。

問題

提出練習

プログラミングの文法の説明に入る前に、自動採点システム(ジャッジ) 2 の使い方を確認しましょう。ジャッジへの提出フォームは、このページの一番下にあります。

提出言語の選択

CPython で提出する場合は "Python (CPython 3.11.4)" を、 PyPy で提出する場合は "Python (PyPy 3.10-v7.3.12)" を選択しましょう。「言語」欄を押して出てくるボックスに言語名の一部("py" など)を入力すると探しやすくなります。 3

ソースコード

「ソースコード」欄にはプログラムのソースコードを入力します。
ここでは、次のプログラムをコピー&ペーストしてみましょう。

コピー&ペーストの仕方:
↓の右上にある「Copy」ボタンをクリック→「ソースコード」のテキストを入力する場所で右クリック→「貼り付け」をクリック

print("Hello, world!")

提出・結果確認

言語選択とソースコードの入力ができたら、「提出」ボタンを押してください。
ページが切り替わり、WJ と表示されているところが AC に変われば提出成功です。

  • WARE と表示されてしまった場合、正しくコピー&ペーストできているか確認し、再提出してください。
  • CE と表示されてしまった場合、「言語」が正しく選択されているか確認してください。 "Python (CPython 3.11.4)" または "Python (PyPy 3.10-v7.3.12)" が選択されているかどうか確認し、再提出してください。

CPython と PyPy の一方で AC が得られたら、もう片方でも提出してみましょう。全く同じコードで AC が得られることが確認できると思います。

コードテスト

ジャッジは、出力結果が正しいかどうかを判定してくれますが、思い通りの結果が得られない場合など、自分のコードがどのような出力をしているのか確認したいこともあると思います。「コードテスト」を使うとプログラムがどのような出力をしているか確認することができます。コードテストはページ上部のリンクから飛ぶことができます。
コードテストの使い方は、上で説明したジャッジの使い方に似ていますが、下記のとおりです。

  • 提出言語を選択する
  • ソースコードを記載する
  • 「標準入力」欄に入力(後述)を記載する
  • 実行ボタンを押す

「入力」については 1.05. 節で扱います。このページの Hello, world! を出力するような例では入力はありませんので、「標準入力」欄は空欄で構いません。

次のページ


  1. ただし書きやすいかどうかは個人の感じ方次第なので、絶対的な指標ではありません。 

  2. AtCoder では、提出コードが正しいかどうかの判定(ジャッジ)が自動的に行われます。より具体的には、予め準備されたテストケースに対して提出コードのプログラムを実行し、すべてのテストケースに対して期待される結果を出力した場合に正解(AC)と判定されます。 

  3. AtCoder では Python の他の実行環境に "Python (Mambaforge / CPython 3.10.10)" および "Python (Cython 0.29.34)" がありますが、本記事では詳しく説明しません。 

B - 1.01.出力とコメント

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • 出力には print を用いる
    • print は文字列や数値を出力できる
    • 複数の要素を改行区切り、スペース区切りで出力することも可能
  • コメントを書く際は #""" を用いる
  • 全角スペース、行頭の半角スペースに注意

出力を行うプログラム

文字列の出力

Python においてプログラムは上から順に一行ずつ実行されます。以下は前節で提出した "Hello, world!" という文字列を出力する(画面に表示する)プログラムです。

print("Hello, world!")
実行結果
Hello, world!

このプログラムは print という機能2で出力を行っています。print に続けて半角の丸括弧内に要素を記述することで、記述した要素を出力することができます
この例では "Hello, world!" という文字列を出力しています。Python では " " で囲った部分は文字列として扱われますprint は文字列を受け取るとその内容をそのまま出力します。

異なる文字列を出力したければ、" " の中に入れる文章を書き換えれば良いです。

print("Pythonだいすき")
実行結果1
Pythonだいすき

数値の出力

print は文字列以外にも様々な要素を受け取ることができます。以下は数値を出力するプログラムです。

print(123)
実行結果
123

この例では 123 という数値(整数)を出力しています。Python では数字から成る要素は数値として解釈されますprint 関数は数値も文字列同様に値をそのまま出力することができます。
なお、ここで print("123") と書いても同じ実行結果を得ることができます。

複数の出力

改行区切りの出力

複数の print を続けて記述するとどうなるでしょうか。

print("Hello, world!")
print(123)
実行結果
Hello, world!
123

Python は記述したプログラムを上から順に実行します。また、print は実行のたびに出力の最後に改行を行います。この結果上記のように 2 つの出力要素が順番に 2 行にわたって出力されます

スペース区切りの出力

print は複数の要素を受け取ることができます。

print("Hello, world!", 123)
実行結果
Hello, world! 123

このプログラムでは半角カンマ , 区切りで 2 つの要素を print に渡しました。この場合、渡した要素を順にスペース区切りで 1 行で出力されます
なお、要素が 3 つ以上でも同様にすべての要素を順にスペース区切りで出力できます。コードテストから試してみてください。

print の機能を用いる方法

改行区切りで出力する別の方法として、以下のように print の機能を用いる方法があります。

print("Hello, world!", 123, sep="\n")
実行結果
Hello, world!
123

このプログラムでは printsep="\n" という要素を追加で指定しています。この sep= は「複数要素の間に挿入する文字列」を指定します。この例だと 2 つの要素の間に改行文字 "\n" を挿入することになり、上記のような実行結果が得られます。

スペース区切りで出力する別の方法もあります。以下のように記述します。

print("Hello, world!", end=" ")
print(123)
実行結果
Hello, world! 123

このプログラムでは printend=" " という要素を追加で指定しています。この end= は「出力後に挿入する文字列」を指定します。この例だと出力後に半角スペースを挿入することになり、上記のような実行結果が得られます。

スペース区切り、改行区切りそれぞれについて 2 通りの方法を紹介しました。難しく感じる場合、慣れないうちは自分の分かりやすい方法だけを使っていれば問題ありません。

もし print の動作仕様について正確な情報が知りたい場合は Python の公式ドキュメント を参照してみてください。

より複雑な要素の出力

より複雑な要素を出力したい場合、print の書き方を工夫するのではなく、出力したい要素を文字列として構築し、その文字列を print で出力する、という方法を取ることになります。
本教材の後半で文字列の処理を学べば、より複雑な出力を行うことができるようになります。

コメント

コメントは人間が「プログラムがどういう動作をしているか」等のメモ書きをプログラム中に残しておくための機能です。
プログラムとしての意味はないので、書いても動作に影響はありません。

2 種類のコメントの書き方

例を見てみてみましょう。

# 123
# 456
# と出力するプログラムです
print(123)
print(456)

"""
print は受け取った要素を出力する
最後に改行が自動で挿入される
"""
実行結果
123
456

1-3行目に # から始まる行はコメントで、プログラムの動作には影響しません。
7-10行目の """ で挟まれた部分も同様にコメントです3

コメントアウト

一時的に実行させたくない部分をコメントにしてしまうことで、その部分のプログラムを無効化するというテクニックがあります。このテクニックは コメントアウト と呼ばれ、よく使われます。

# print(123)
print(456)
実行結果
456

1行目の処理はコメント扱いで実行されないため、123 は出力されません。
123 を出力したくなった場合はコメントを解除すればよい (# を消せば良い) ため、書き直しの手間は小さいです。

注意点

全角スペース

Python は全角文字を扱うことは可能ですが、プログラムの中に全角スペース「 」が入っているとエラーになってしまいます。発見が難しいため注意してください。

書き出し位置

Python では各行の書き出し位置に規則が存在します。特に、今回書くような単純なプログラムではすべての行が行の左端に位置している必要があります。
行の先頭には (全角スペースは勿論ですが) 半角スペースも記述しないように注意してください。

問題

リンク先の問題を解いてください。

EX1.コードテストと出力の練習

前のページ | 次のページ


  1. 人によります。 

  2. より具体的には、組み込み関数という Python が提供する仕組みになります。組み込み関数については 1.12.組み込み関数で扱います。 

  3. 厳密には複数行にわたる文字列ですが、コメントを書くために利用されることも多い記法です。 

C - 1.02.プログラムの書き方とエラー

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • Python プログラムを書く際には行の書き出し位置・改行などのルールに従う必要がある
  • 読み込み時エラーとは Python プログラムの記述ルールに従っていない場合に起こるエラーのことで、プログラム自体が実行されない
  • 実行時エラーとはプログラムの処理が継続できない事象が生じた場合に起こるエラーのことで、プログラムが異常終了する
  • 論理エラーとはプログラムの動作が意図したものと異なる場合に起こるエラーのことで、プログラムの実行は問題なく終了するため発見が難しい
  • 読み込み時エラーや実行時エラーが出たときはエラーメッセージをよく読み、少しずつ慣れていくことが重要

プログラムの書き方

プログラムは通常の文章を書くときには無いルールが存在します。他の言語と異なる Python 特有の事情も存在しますので、基本的なルールを紹介していきます。

行の書き出し位置とインデント

Python は各行の書き出し位置を揃える必要があります。理由も無く行の書き出し位置がずれるとエラーになるため、行の先頭に余分なスペースが入らないように注意してください。
逆に、後の節で扱う「構文を表すキーワード + コロン」を記述した場合、次の行では書き出し位置を右にずらす (インデントする) 必要があります。

参考までに、インデントしている部分を含むコードの例を紹介します (現時点で意味が分かる必要はありません)。

# 何もない行は左詰め
print("hoge")

def function():
    # 関数定義のコロンの後、インデントする
    # 複数行記述する場合、ずっとインデントしたまま
    print("foo")
    return 0

for i in range(10):
    # for 文のコロンの後、インデントする
    print("bar")
    for j in range(10):
        # 二重 (以上) にインデントすることもある
        print("baz")

C++などの他の言語では見やすくするためにインデントを行いますが、Python ではルールとして強制的にインデントを行う点が特徴的です1

改行について

Python では実行文2同士を区切るために改行もしくはセミコロン ; を使用します。
今まで print を複数記述する際には必ず改行をはさんでいましたが、次のようにセミコロン ; を使って複数の実行文を 1 行にまとめて記述することも可能です。

print("hello"); print(123)
実行結果
hello
123

逆に、1 つの実行文を複数の行に分けて記述したい場合、バックスラッシュ \ を用いて次のように書くことができます。次の例は 1 から 8 までの整数を足し合わせた結果を表示するプログラムです。足し合わせる数が多いため、途中でバックスラッシュを用いて改行をはさんでいます。

res = 1 + 2 + 3 + 4 \
     + 5 + 6 + 7 + 8
print(res)
実行結果
36

一部のケースではバックスラッシュなしで改行をはさむことができます。具体的には、丸カッコ () や四角カッコ []、波カッコ {} などの内側です。次のような書き方のイメージになります(意味は気にしなくて構いません)。

print(
    123,
    "hoge",
    "foo",
    sep="\n"
)
lst = [
    10,
    20,
    30
]

カッコの中身は記述が長くなりやすいため、改行を使うことで読みやすいコードになります。

スペースについて

Python では記述する要素同士の切れ目には半角スペースを何個でも置くことができます。

print(123,   456 ,  789)

注意として、半角スペースでなく全角スペースを記述するとエラーとなってしまうので気をつけてください。

プログラムのエラー

プログラムは書き終わったら完成ではありません。動かしてみてその動作が正しいことを確認して、はじめて完成と言えます。
しかし書き終えたばかりのプログラムを実行しようとすると、たいてい何らかのエラーが発生します。そのときにエラーの原因を理解して修正できることも重要なスキルです。

Python プログラムのエラーは次の3つに大別できます。

  • 読み込み時エラー
  • 実行時エラー
  • 論理エラー

それぞれについて説明します。

読み込み時エラー

書いたプログラムの文法にミスがあるときに発生するエラーです。
全角スペースがプログラム中に入り込んだり、インデントが不正である場合、コードを読み込んだ時点でエラーになります。

プログラミング言語では「文法」が厳密に決められています。
日本語などの人間が使う言語では、文法的に少し崩れた文でも意図が通じますが、プログラミング言語ではそうはいきません。

読み込み時エラーが起きた場合、プログラムは一切動作しません。AtCoder のジャッジの実行結果は CE となります。

実行時エラー

「プログラムを動かす」ことを「プログラムを実行する」といいます。

実行時エラーとは、プログラムの文法に間違いはなかったが、内容に致命的な間違いがあったときに発生するエラーです。
具体的には3÷0のように、0で割り算を行ってしまった場合や、書き間違い (printpritn と書くなど) で存在しない要素を記述した場合などに発生します。
スマホアプリやゲーム等が強制終了してしまったとき、多くの場合実行時エラーが発生しています。

実行時エラーが起きた場合、実行時エラーが起きる直前までプログラムは動作しますが、エラー以降は動かなくなってしまいます。AtCoder のジャッジの実行結果は RE となります。

論理エラー

論理エラーとは、プログラムは一見正しく動作しているが、その動作が実は正しくないときに発生するエラーです。
例えば、「300円のクッキーと100円のアメを買ったときに払うお金」を計算するプログラムでは300 + 100と計算するべきですが、間違って300 - 100としてしまった場合などは論理エラーに当たります。
論理エラーは勘違いで生まれたり、タイピングのミスで発生したりと様々です。

論理エラーは一見問題なくプログラムが動作しますが、意図と異なる結果を返すため、発見することが難しくなりやすいです。AtCoder のジャッジの実行結果は(偶然実行結果が合うということが無い限りは) WA となります。

エラーの例

この時点でよく遭遇すると思われるエラーを紹介します。

全角スペース

次のコードには文末に全角スペースが入っており、SyntaxError という読み込み時エラーとなっています。エラー文の中で U+3000 と記述されているものが全角スペースに相当します。記述されている箇所も教えてくれるため、修正は容易です。

print(123) # (123) の後に全角スペースがある
File "Main.py", line 1
    print(123) 
              ^
SyntaxError: invalid non-printable character U+3000

カッコの閉じ忘れ

開きカッコに対応する閉じカッコがない場合、SyntaxError となります。

print(123
File "Main.py", line 1
    print(123
         ^
SyntaxError: '(' was never closed

インデントのミス

理由もなくインデントしてしまうと IndentationError という読込み時エラーが発生します。

print(123)
  print(456)
Sorry: IndentationError: unexpected indent (Main.py, line 2)

スペルミス

書き間違いなどで存在しない名称3を記述してしまった場合、NameError という実行時エラーになります。次のエラーでは pritn という名称は存在しないということと、print の書き間違いではないか?というヒントを与えてくれています。

pritn(123)
Traceback (most recent call last):
  File "/judge/Main.py", line 1, in <module>
    pritn(123)
    ^^^^^
NameError: name 'pritn' is not defined. Did you mean: 'print'?

エラーへの対処

プログラムにエラーはつきものなので、うまく付き合う必要があります。以下でエラーへの対処方法、心構えについて紹介します。

エラーをよく読む

Python の場合末尾にエラーの要点が書かれていることが多いです。大量のエラーが表示された場合読みたくなくなりますが、まずエラーの最後を見て大意がつかめないかトライしてみてください。
具体的な行数や箇所の表示を見て不自然な点が無いか確認してみるのもよいでしょう。

検索する

初心者の段階で遭遇するエラーはよくあるものが多いので、検索すればすぐにわかるケースも多いと思われます。
検索する場合はエラーの末尾の部分など、自分の環境固有の記述が含まれない部分を検索ワードに設定するとよいでしょう。

エラーの利点?

書くたびにエラーが出てうまく動かないと嫌な気持ちになるかもしれませんが、考えようによってはミスを Python の実行プログラムが教えてくれているだけ有益ともとれます。
前述の論理エラーのような「表示されないエラー」はミスが明らかにならないため発見が遅れ、大きなバグに繋がってしまうこともあります。

問題

リンク先の問題を解いてください。

EX2.エラーの修正

前のページ | 次のページ


  1. 面倒に感じるかもしれませんが、自然と読みやすいコードになるという利点もあります。 

  2. 今までの print("hoge") のように、ひとつの処理を実行する単位のことを実行文と呼びます。 

  3. 「存在する名称」は以下のいずれかです: 1. print のように Python の組み込みオブジェクトとして用意(予約)されている。 2. 自身で定義した変数やモジュール。これらに該当しない名称を記述した場合、エラーになります。 

D - 1.03.四則演算と優先順位

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

演算子 計算内容
+ 足し算
- 引き算
* 掛け算
// 割り算(整数)
/ 割り算(実数 1
** べき乗
% 割った余り

(注)割り算の記号がふたつありますが、 // は整数での除算(切り捨て除算)、 / は実数(float)での除算です。違いについては後の例で説明します。

足し算・引き算・掛け算

Python で足し算・引き算・掛け算を行う場合は、 + - * を使います。

print(7 + 2) # 9
print(7 - 2) # 5
print(7 * 2) # 14
実行結果
9
5
14

割り算

割り算については少し注意が必要です。 // は整数範囲での割り算を計算し、切り捨てされた結果を整数として返します。一方で、 / は実数で計算した結果を(次節1.04変数と型で扱う float 型で)返します。

print(7 // 2) # 3
print(7 / 2) # 3.5
実行結果
3
3.5

切り捨て除算は、負の数を割った場合も小さくなる方向(絶対値が大きくなる方向)に丸められます。

print(-7 // 2) # -4
print(-7 / 2) # -3.5
実行結果
-4
-3.5

べき乗

べき乗の計算(指数計算)は ** を使います。次のプログラムでは、 72 乗である 49 が出力されます。

print(7 ** 2)
実行結果
49

剰余演算

最後に、剰余演算(割った余りを計算する演算)です。 72 で割った余りは 1 なので、以下のプログラムでは 1 が出力されます。

print(7 % 2)
実行結果
1

負の数の切り捨て除算は、小さい方(絶対値が大きい方)に丸められると説明しましたが、剰余演算もそれと整合的に計算されます。より具体的には、正の整数の除算では ab で割った商を q 、余りを r とすると a = b \times q + r\ (0\le r<b) が成立しますが、 a が負の数の場合も b が正であればこれが成立します。
例えば -115 で割ると -3 あまり 4 という計算になります。上の式に当てはめると -11 = 5 \times (-3) + 4 が成立することが確認できます。

print(-11 // 5)
print(-11 % 5)

実行結果
-3
4

演算子の優先順位

演算子には優先順位があります。
例えば 1 + 2 * 3 のような式を書いた場合、先に 2 \times 3 が計算された後に 1 が足され、計算結果は 7 になります。 * の優先順位が + より高いということです。
上で紹介した演算子の優先順位は次のとおりです。

優先順位 演算子
**
*
//
/
%
+
-
print(3 + 4 * 5) # 4 * 5 を先に計算する
print(5 * 3 ** 2) # 3 の 2 乗を先に計算する
実行結果
23
45

同じ優先順位の演算子が並んでいる場合は、左から順に計算されます。
括弧 ( ) を使うと、括弧で括った部分が先に計算されます。

print(4 * (1 + 2)) # 括弧の中の 1 + 2 を先に計算する
print(3 * 5 // 2) # 3 * 5 の結果を先に計算する
実行結果
12
7

注意点

ゼロ除算

ゼロで割り算を行おうとするとランタイムエラーになります。
次のコードはいずれもランタイムエラーになり、 AtCoder のジャッジだと RE が表示されてしまいます。

print(3 / 0)
print(3 // 0)
print(3 % 0)

割り切れる場合の実数除算

割り算をする際、たとえば 6 \div 3 のように割り切れる計算の場合、数学的には切り捨て除算と実数除算は同じ結果になりそうです。 Python では割り切れる場合であっても結果は少し異なります。具体的には、次節1.04変数と型で説明する「型」が変わます。

print(6 // 3)
print(6 / 3)
実行結果
2
2.0

この例では、(数学的な値としては)いずれも 2 と等しいですが、場合によっては有効桁数の関係で値が変わることもあります。競技プログラミングでもこれによる失敗をするケースがあります。整数範囲で考えている場合は整数除算 // を使うのが無難です。

発展的な内容

負の除数による除算

競技プログラミングでは敢えて除数を負にする必要があるケースはあまり見かけませんが、思わぬ罠になる可能性があるので、プログラムの挙動について説明しておきます。
ab で割った商を q 、余りを r とします。 b が正のときは a = b \times q + r\ (0\le r<b) が成立すると説明しましたが、除数 b が負のときは余りの範囲も負の方向になり、 a = b \times q + r\ (b < r \le 0) を満たすように商・余りが決まります。

11=(-5)\times(-3)+(-4) より、11-5 で割った商は -3 、余りは -4 となります。
-11=(-5)\times 2+(-1) より、-11-5 で割った商は 2 、余りは -1 となります。

print(11 // -5)
print(11 % -5)
print(-11 // -5)
print(-11 % -5)

実行結果
-3
-4
2
-1

divmod

ab で割った商は a // b 、余りは a % b で取得できることは既に学びましたが、 divmod 関数を使うことでこれらを同時に取得することもできます。
具体的には、 divmod(a, b)ab で割った商と余りのタプルを返します。「タプル」についてはまだ扱っていないので詳細は省略しますが、次のようなコードで取得できることを覚えておけば十分です。

q, r = divmod(20, 7)
print(q)
print(r)
実行結果
2
6

問題

リンク先の問題を解いてください。

EX3.計算問題

前のページ | 次のページ


  1. 正確には次節で紹介する float 型での計算であり、実数そのものを扱っている訳ではないですが、簡単のためこのページでは実数と記載しています。 

E - 1.04.変数と型

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

書き込むデータの種類
int 整数
float 実数(浮動小数点数) 1
str 文字列

変数について

変数は「メモ」だと考えてください。一度使ったデータをまた後で使いたいときのために、名前を付けてメモをして覚えておくというものです。
「変数の名前」のことを 変数名 と言います。次の例では、整数 10 というデータを name という変数に格納(メモ)して、あとから呼び出して使用しています。

name = 10
print(name)
print(name + 2)
print(name * 2)
実行結果
10
12
20

型について

「データの種類」のことを 型(かた) と言い、変数はいずれかの型を持ちます。
なお、前節までは変数を使わず print(123) などのようにプログラムに直接整数などを書き込んでいましたが、実はこの 123 などにも型があり、この場合は整数型になっています。

以下に Python でよく使う型を挙げます。

int(整数型)

3-10 などの整数を表すことができます。

float(浮動小数点数型)

3.5 などの実数 1 を表すことができます。

str(文字列型)

"a""Hello" などの文字列を表すことができます。

代入

変数には値を代入することができます。代入するときは代入演算子「=」を使い、左側に代入先の変数を、右側に代入する値を書きます。複数回代入すると、前の値が上書きされます。

x = 3  # 変数 x に整数 3 が代入される
y = -7.3  # 変数 y に浮動小数点数 -7.3 が代入される
z = "ABC"  # 変数 z に文字列 "ABC" が代入される
x = 10 #  変数 x に 10 が代入される(上書きされる)

値が代入された変数は、以下のように呼び出すことで使うことができます。

x = 3
y = -7.3
z = "ABC"
print(x * 2)
print(y * 3)
print(z)
実行結果
6
-21.9
ABC

= の右側は、変数や演算子を含んでいても構いません。

x = 3
y = x  # y に x の値である 3 が代入される
z = x * 10 + 2  # x * 10 + 2 の計算結果が代入される
print(y)
print(z)
実行結果
3
32

なお Python の = は代入を意味していて、「等しい」という意味ではないということに注意してください。

指数表記

float 型では指数表記による記述もできます。絶対値が大きいまたは小さい数の場合は、 print 関数で出力した結果も指数表記になります。

x = 1.23e5
y = 3.5e-2
z = 2.7e-10
print(x)
print(y)
print(z)
実行結果
123000.0
0.035
2.7e-10

変数の型の宣言について

勘の良い方は、変数がどの型になるのかを書かなくて良いのか気になったかもしれません。実は Python ではユーザーが変数の型を指定(宣言)する必要はなく、プログラムで自動的に判定されます。具体的には、代入するもの(= の右側)の型によって決まります。このため、同じ変数を別の型で上書きするということもできます。

x = 3
print(x)
x = "AtCoder"
print(x)
実行結果
3
AtCoder

複合代入演算子

x5 を足す」のような、計算結果を同じ変数に代入する操作は、 x += 5 のように書くことができます。これは x = x + 5 と書いたことと同じ結果になります。

x = 2
x += 5
print(x)
実行結果
7

+= のような演算子を 複合代入演算子 と言います。前節で扱った演算子は、すべて = を付けることで複合代入演算子として使えます。

複合代入演算子 コード例 複合代入演算子を使わない書き方
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
//= x //= 3 x = x // 3
/= x /= 3 x = x / 3
**= x **= 3 x = x ** 3
%= x %= 3 x = x % 3

例えば次のように書くことができます。

x = 2
x += 5  # 7
x *= 3  # 21
x //= 2  # 10
x **= 3  # 1000
x %= 300  # 100
x -= 20  # 80
print(x)
実行結果
80

複数の変数への代入

変数 x2 を、変数 y3 を代入するという操作を同時に行いたいときは、カンマ(,)で区切って次のように書くことができます。

x, y = 2, 3
print(x)
print(y)
実行結果
2
3

これを使うと、 xy の値を入れ替える(Swap する)という操作も簡単に書くことができます。

x = 2
y = 3
x, y = y, x  # x と y を入れ替える
print(x)
print(y)
実行結果
3
2

有効数字・範囲

int 型

Python の int 型は 多倍長整数 と呼ばれていて、多くのプログラミング言語の int 型のような大きさの制限(32 bit や 64 bit など)がありません。例えば、 31000 乗は 478 桁のとても大きな整数ですが、下記のように簡単に計算することができます 2

print(3 ** 1000)
実行結果
1322070819480806636890455259752144365965422032752148167664920368226828597346704899540778313850608061963909777696872582355950954582100618911865342725257953674027620225198320803878014774228964841274390400117588618041128947815623094438061566173054086674490506178125480344405547054397038895817465368254916136220830268563778582290228416398307887896918556404084898937609373242171846359938695516765018940588109060426089671438864102814350385648747165832010614366132173102768902855220001

float 型

float 型では、 10 進法で 1516 桁程度(2 進法で 53 ビット)の有効数字で計算されます。これよりも高い精度が求められる場合は予期せぬ結果になることがあるので注意が必要です。

print(100 / 3)
実行結果
33.333333333333336

なお、浮動小数点数で表せる最大の数は約 1.8\times 10^{308} 程度、最小の数は約 -1.8\times 10^{308} 程度、最小の正の数は約 2.2\times 10^{-308} 程度です。

発展的な内容

異なる型同士の演算

前項で四則演算などの演算を学びました。その際は細かく触れませんでしたが、元の変数の型や値によって計算結果として返される型も自動的に決まります。異なる型同士の演算の場合は(同じ型同士の演算であっても場合によっては)注意が必要になります。ここですべてのパターンを網羅することはできませんが、いくつか例を挙げておきます。

int 型同士の和・差・積

整数(int)型同士の和・差・積は整数(int)型になります。

a = 7
b = 2
print(a + b)  # 整数型の 9
print(a - b)  # 整数型の 5
print(a * b)  # 整数型の 14
実行結果
9
5
14

float 型同士の和・差・積

浮動小数点数(float)型同士の和・差・積は浮動小数点数(float)型になります。

a = 3.2
b = 2.5
print(a + b)
print(a - b)
print(a * b)
実行結果
5.7
0.7000000000000002
8.0

int 型と float 型の和・差・積

片方が int 型、片方が float 型の場合の和・差・積は float 型になります。 3.5 \times 4 は数学的には整数 14 になりますが、 Python のプログラムは float 型として返します。

a = 3.5
b = 4
print(a + b)
print(a - b)
print(a * b)
実行結果
7.5
-0.5
14.0

int 型同士のべき乗

ab がともに int 型のとき、 a ** b の型はどうなるでしょうか。簡単のため a はゼロではないとします。
この場合は b \ge 0 の場合は int 型、 b < 0 の場合は float 型になります。

print(2 ** 3)
print(2 ** -3)
実行結果
8
0.125

問題

リンク先の問題を解いてください。

EX4.◯年は何秒?

前のページ | 次のページ


  1. 前節1.03四則演算と優先順位の注にも書きましたが、正確には実数ではなく浮動小数点数を表します。簡単のためここでは実数と記載しています。 

  2. ただしあまりに大きい場合は実行時間やメモリの関係で計算が行えない場合があります。手元環境で実行する際など、 PC の限界を超えるとクラッシュしてしまう可能性があるので注意してください。 

F - 1.05.入力

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • 変数 = input() で入力を文字列として受け取ることができる
    • 整数として受け取るためには 変数 = int(input()) とする
  • 1 行をまとめてひとつの文字列として受け取る
    • 空白で区切って複数の文字列として受け取るためには 変数1, 変数2 = input().split() などとする

入力の受け取り方

プログラムの実行時にデータの入力を受け取る方法を見ていきましょう。
「入力機能」を使うことにより、プログラムを書き換えなくても与える入力を変えることで様々な計算を行えるようになります。

入力を受け取るには input() を使います。

次のプログラムは、入力として受け取った文字列を 3 回出力するプログラムです。

s = input()

print(s)
print(s)
print(s)
入力
Pythonだいすき
実行結果
Pythonだいすき
Pythonだいすき
Pythonだいすき

文字列以外の入力

入力を文字列以外の形式で扱いたいときは、入力を受け取った後に変換する必要があります。

次のプログラムは、入力として受け取った整数を 10 倍したものを出力するプログラムです。

# 入力を文字列として受け取る
a = input()
# 文字列として受け取った入力を整数に変換する
a = int(a)

print(a * 10)
入力
5
実行結果
50

上のプログラムは、以下のように「入力を文字列として受け取り整数に変換する部分」をまとめて書くこともできます。

# 入力を整数として受け取る
a = int(input())

print(a * 10)
入力
5
実行結果
50

入力を小数として受け取りたい場合も、float() を使って以下のように書くことができます。

# 入力を小数として受け取る
a = float(input())

print(a * 10)
入力
3.14
実行結果
31.4

複数行の入力

input() は 1 行の入力を受け取るものなので、input() を行数分書くことで複数行の入力を受け取ることができます。

s = input()
a = int(input())

print(s, a * 10)
入力
Hello
5
実行結果
Hello 50

空白区切りの入力

前述のように、input() は 1 行の入力を文字列として受け取ります。

s = input()

print(s)
入力
10 20 30
実行結果
10 20 30

そのため、空白区切りの入力を受け取ると、上のように "10 20 30" というひとまとまりの文字列として受け取ってしまいます。

そこで、次のプログラムのように input() で受け取った文字列を split() で空白区切りで分解することで別々の変数に格納することができます。

a, b, c = input().split()

print(a)
print(b)
print(c)
入力
10 20 30
実行結果
10
20
30

このままだと文字列として扱っていますが、次のプログラムのように int() を使って整数に変換することもできます。

a, b, c = input().split()
a = int(a)
b = int(b)
c = int(c)

print(a * 10)
print(b * 100)
print(c * 1000)
入力
10 20 30
実行結果
100
2000
30000

上のプログラムは、以下のように「入力を空白区切りで分割し整数に変換する部分」をまとめて書くこともできます。
map(int, input().split()) の意味については今の時点では理解する必要はありません。このまま覚えてしまっても良いでしょう。

a, b, c = map(int, input().split())

print(a * 10)
print(b * 100)
print(c * 1000)
入力
10 20 30
実行結果
100
2000
30000

また、split() は以下のように区切り文字を指定することもできます。
これまでのように何も指定しない場合は、空白文字で区切られます。

a, b, c = input().split(":")

print(a)
print(b)
print(c)
入力
10:20:30
実行結果
10
20
30

問題

リンク先の問題を解いてください。

G - 1.06.if文・比較演算子・論理演算子

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • if 文を使うと、「指定した条件に当てはまるときだけ処理をする」というプログラムを書ける
    • elifelse を使うと、「条件に当てはまらなかったとき」の処理を書ける
if 条件式1:
    処理1 (条件式1に当てはまるときに実行)
elif 条件式2:
    処理2 (条件式1に当てはまらず、条件式2に当てはまるときに実行)
else:
    処理3 (条件式1にも条件式2にも当てはまらないときに実行)
  • 一般的な比較演算子のまとめ
演算子 意味
x == y xy は等しい
x != y xy は等しくない
x > y xy より大きい
x < y xy より小さい
x >= y xy 以上
x <= y xy 以下
  • 一般的な論理演算子のまとめ
演算子 意味 真になるとき
not 条件式 条件式 の真偽の反転 条件式 が偽
条件式1 and 条件式2 条件式1 が真」かつ「条件式2 が真」 条件式1条件式2 のどちらも真
条件式1 or 条件式2 条件式1 が真」または「条件式2 が真」 条件式1条件式2 の少なくとも片方が真

if 文

if 文を使うと、ある条件が正しいとき(当てはまるとき)だけ処理をするプログラムを書くことができます。
書き方は次のとおりです。

if 条件式:
    処理

条件式が正しいとき、: 以降のインデントが下がった部分の処理が実行され、条件式が正しくないとき、処理は飛ばされます。

次のプログラムは、入力の値が 10 より小さければ「x は 10 より小さい」と出力した後「終了」と出力します。入力の値が 10 より小さくなければ「終了」とだけ出力します。

x = int(input())

if x < 10:
    print("x は 10 より小さい")

print("終了")
入力 1
5
実行結果 1
x は 10 より小さい
終了
入力 2
15
実行結果 2
終了

この例では、まず x = int(input()) の部分で入力された値を整数として変数 x に代入しています。
重要なのはその後です。

if x < 10:
    print("x は 10 より小さい")

この部分は、「もし x < 10x10 より小さい)ならば x は 10 より小さい と出力する」という意味になります。
最後に print("終了") の部分で 終了 と出力します。

x10 より小さくない場合、以下の部分は飛ばされます。

    print("x は 10 より小さい")

そのため、2 つ目の実行例では 終了 とだけ出力されています。

また、以下のプログラムのように if 文の中の処理は複数行にわたって書くこともできます。

x = int(input())

if x < 10:
    print("x は 10 より小さい")
    print(x)

print("終了")

if 文のように、ある条件を満たすかどうかで実行する処理を変えることを条件分岐といいます。
また、「条件式が正しい(条件式が当てはまる)」ことを条件式が真、「条件式が正しくない(条件式が当てはまらない)」ことを条件式が偽といいます。

比較演算子

if 文のところで使った条件式 x < 10 は、比較演算子のひとつです。
一般的な比較演算子には以下の 6 つがあります。

演算子 意味
x == y xy は等しい
x != y xy は等しくない
x > y xy より大きい
x < y xy より小さい
x >= y xy 以上
x <= y xy 以下

xy は等しい」は「x == y」と = を 2 つ繋げたもので表し、「xy は等しくない」は「x != y」と表します。
xy より大きい」「xy より小さい」は、数学での記号と同じく >, < で表します。
xy 以上」「xy 以下」は、数学では \geqq, \leqq のように = を下につけますが、Python では = を右につけることで表します。

次のプログラムは、入力された整数値がどのような条件を満たしているかを出力するプログラムです。

x = int(input())

if x < 10:
    print("x は 10 より小さい")

if x >= 20:
    print("x は 20 以上")

if x == 5:
    print("x は 5")

if x != 100:
    print("x は 100 ではない")

print("終了")
入力 1
5
実行結果 1
x は 10 より小さい
x は 5
x は 100 ではない
終了
入力 2
100
実行結果 2
x は 20 以上
終了

論理演算子

条件式の部分にはもっと複雑な条件を書くこともできます。そのためには論理演算子を使います。

論理演算子には以下の 3 つがあります。

演算子 意味 真になるとき
not 条件式 条件式 の真偽の反転 条件式 が偽
条件式1 and 条件式2 条件式1 が真」かつ「条件式2 が真」 条件式1条件式2 のどちらも真
条件式1 or 条件式2 条件式1 が真」または「条件式2 が真」 条件式1条件式2 の少なくとも片方が真
x, y = map(int, input().split())

if not x == y:
    print("x と y は等しくない")

if x == 10 and y == 10:
    print("x と y は 10")

if x == 0 or y == 0:
    print("x か y は 0")

print("終了")
入力 1
2 3
実行結果 1
x と y は等しくない
終了
入力 2
10 10
実行結果 2
x と y は 10
終了
入力 3
0 8
実行結果 3
x と y は等しくない
x か y は 0
終了

「前の条件が真でないとき」の処理

else 節

else 節は、if 文の後に書くことで、「if 文の条件が偽のとき」に処理を行えるようになります。
書き方は次のとおりです。

if 条件式:
    処理1
else:
    処理2

次のプログラムは、入力の値が 10 より小さければ「x は 10 より小さい」と出力し、そうでなければ「x は 10 より小さくない」と出力します。

x = int(input())

if x < 10:
    print("x は 10 より小さい")
else:
    print("x は 10 より小さくない")
入力 1
5
実行結果 1
x は 10 より小さい
入力 2
15
実行結果 2
x は 10 より小さくない

elif 節

elif 節は「「前の if 文の条件が偽」かつ「elif 節の条件が真」」のときに処理が行われます。
書き方は次のとおりです。

if 条件式1:
    処理1
elif 条件式2:
    処理2

処理2が実行されるのは「条件式1が偽 かつ 条件式2が真」のときになります。

また、elif 節のあとに続けて elif 節や else 節を書くこともできます。
次のプログラムはその例です。

x = int(input())

if x < 10:
    print("x は 10 より小さい")
elif x > 20:
    print("x は 10 より小さくなくて、20 より大きい")
elif x == 15:
    print("x は 10 より小さくなくて、20 より大きくなくて、15 である")
else:
    print("x は 10 より小さくなくて、20 より大きくなくて、15 でもない")
入力 1
5
実行結果 1
x は 10 より小さい
入力 2
30
実行結果 2
x は 10 より小さくなくて、20 より大きい
入力 3
15
実行結果 3
x は 10 より小さくなくて、20 より大きくなくて、15 である
入力 4
13
実行結果 4
x は 10 より小さくなくて、20 より大きくなくて、15 でもない

if 文のネスト

if, elif, else などの節の中にさらに if 文を入れることで、より複雑な条件分岐をすることもできます。

x = int(input())

if x % 2 == 0:
    if x % 3 == 0:
        print("x は 2 の倍数でも 3 の倍数でもある")
    else:
        print("x は 2 の倍数ではあるが 3 の倍数ではない")
else:
    if x % 3 == 0:
        print("x は 2 の倍数ではないが 3 の倍数ではある")
    else:
        print("x は 2 の倍数でも 3 の倍数でもない")
入力 1
12
実行結果 1
x は 2 の倍数でも 3 の倍数でもある
入力 2
14
実行結果 2
x は 2 の倍数ではあるが 3 の倍数ではない
入力 3
15
実行結果 3
x は 2 の倍数ではないが 3 の倍数ではある
入力 4
17
実行結果 4
x は 2 の倍数でも 3 の倍数でもない

比較演算子の連鎖

次のプログラムは、x0 以上 100 以下かどうかを調べるプログラムです。

x = int(input())

if 0 <= x and x <= 100:
    print("x は 0 以上 100 以下です")
else:
    print("x は 0 以上 100 以下ではありません")

上のプログラムの 0 <= x and x <= 100 の部分を、Python では次のプログラムのように 0 <= x <= 100 と書くこともできます。

x = int(input())

if 0 <= x <= 100:
    print("x は 0 以上 100 以下です")
else:
    print("x は 0 以上 100 以下ではありません")

また、a < b < c < d のように 3 つ以上繋げて書いたり、a < b > c のように異なる演算子についても繋げて書くことができます(a < b > ca < b and b > c と同じ意味です)。

💡 ちなみに

この書き方は、あまり濫用するとかえってわかりづらくなってしまうので注意が必要です。例えば、a != b != c と書いたとき、これは a != b and b != c と同じ意味なので、ac が異なるかどうかを判定していません。

問題

リンク先の問題を解いてください。

H - 1.07.論理式の値とbool型

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • 条件式の値は bool 型という型の値である。
  • bool 型は True (真) と False (偽) の2種類の値のいずれかを取る型である。
  • 数値や文字列など色々な値は条件式の値として用いることができる。結果は型ごとにルールが決まっている。
    • 数値の場合、0 でなければ True
    • 文字列の場合、"" (空文字列) でなければ True

条件式の結果

1.06節では if x == 0: のように if 文を用いることで条件分岐を記述できる、ということを扱いました。じつはこの「x == 0」の部分自体が値を持っています。このことを確認してみましょう:

x = 0
print(x == 0) # 「x が 0 と等しいかどうか」を出力
print(x >= 1) # 「x が 1 以上かどうか」を出力
実行結果
True
False

条件式が成り立っている場合の値は "True"、成り立っていない場合は値は "False" と出力されました。これらは、それぞれ日本語でいうところの「真」「偽」に相当します。条件式は、それが成り立っている場合は真、成り立っていない場合は偽、という値を持っている、ということになります。

条件式の結果は値を持つので、これを変数に格納したり、格納した変数同士で演算を行うことも可能です。以下の例では条件式の値を変数 a, b に代入し、それらの論理演算を行っています。

x = 5
a = 0 <= x # a に「xが0以上か」の条件式の値を代入 (ここでは True)
b = x <= 10 # b に「xが10以下か」の条件式の値を代入 (ここでは True)
c = a and b # c に「a かつ b か」の論理演算式の値を代入
print(a,b,c)
実行結果
True True True

bool 型

True と False

先程出力された条件式の値である True False は bool型というデータ型の値です。bool型はこれらTrue (真) もしくは False (偽) の2種類の値のみを取ります。
bool 型の値は、前節のように条件式を記述する以外にも、True False を直接記述することでも表現することができます。

if True:
    print("条件が成り立っています")
if False:
    print("条件が成り立っています")
else:
    print("条件が成り立っていません")
実行結果
条件が成り立っています
条件が成り立っていません

他の型からの変換

実は if 文の条件式には True False 以外の値を与えることも可能です:

if 10:
    print("10 は True 扱い")
if not 0:
    print("0 は False 扱い")
if -1:
    print("-1 は True 扱い")
実行結果
10 は True 扱い
0 は False 扱い
-1 は True 扱い

上記のように数値を条件式に与えた場合、「値が0でなければ True、0 と等しければ False」というルールで変換が行われます。このような型の変換のことをキャストと呼びます。上記の例だと int 型が bool 型にキャストされた、ということになります。

キャストは数値以外でも行われます。代表的な例を次の表に記載します:

変換ルール True となる例 False となる例
数値 (int, float) 値が0と等しいときのみ False 1, 0.01, -1e18 0, 0.0
文字列 空文字列 "" のときのみ False "hoge", "A", " " ""
配列1 配列が空 (長さが 0) のときのみ False [1,2,3], ["foo"], [0] []

問題

リンク先の問題を解いてください。

EX7.bool値パズル

前のページ | 次のページ


  1. 配列に関しては後の節1.10.リストで扱います。整理のために記載しましたがここでは読み飛ばしていただいて構いません。 

I - 1.08.while文

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • while 文を使うと繰り返し処理ができる
  • 条件式が真のとき処理を繰り返す
while 条件式:
    処理
  • N 回処理する」というプログラムを書く場合、「カウンタ変数を 0 からはじめ、カウンタ変数が N より小さいときにループ」という形式で書く
i = 0  # カウンタ変数
while i < N:
    処理
    i += 1

while 文

while 文を使うと、プログラムの機能の中でも非常に重要な「繰り返し処理」(ループ処理)を行うことができます。

無限ループ

次のプログラムは、「Hello と出力して改行した後、AtCoder と出力する処理」を無限に繰り返すプログラムです。

while True:
    print("Hello")
    print("AtCoder")
実行結果
Hello
AtCoder
Hello
AtCoder
Hello
AtCoder
Hello
AtCoder
Hello
AtCoder
...(無限に続く)

while 文は次のように書き、条件式が真のとき処理を繰り返し続けます。

while 条件式:
    処理

先のプログラムでは条件式の部分に True と書いているため、無限に処理を繰り返し続けます。
このように、無限に繰り返し続けることを無限ループと言います。

1 ずつカウントする

次のプログラムは、1 から順に整数を出力し続けます。

i = 1
while True:
    print(i)
    i += 1  # ループのたびに 1 増やす
実行結果
1
2
3
4
5
6
7
8
...(無限に 1 ずつ増えていく)

ループ回数の指定

1 ずつカウントするプログラムを「1 から 5 までの数を出力するプログラム」に変える場合、次のようにします。

i = 1

# i が 5 以下の間だけループ
while i <= 5:
    print(i)
    i += 1
実行結果
1
2
3
4
5

カウンタ変数は 0 から N 未満まで

5Hello と出力されるプログラムを考えます。
以下では書き方を二つ紹介します。この教材では二つ目の書き方を推奨します。

推奨しない書き方

# i を 1 からはじめる
i = 1

# i が 5 以下の間だけループ
while i <= 5:
    print("Hello")
    i += 1
実行結果
Hello
Hello
Hello
Hello
Hello

N 回処理をする」というプログラムを while 文で書く場合、今までは「i1 からはじめ、N 以下の間ループする」という形式で書いてきました。

i = 1
while i <= N:
    処理
    i += 1

この形式は一見わかりやすいと感じるかもしれません。
しかし、この書き方はあまり一般的ではなく、次のように書いたほうがより一般的です。

推奨する書き方

# i を 0 からはじめる
i = 0

# i が 5 未満の間だけループ
while i < 5:
    print("Hello")
    i += 1
実行結果
Hello
Hello
Hello
Hello
Hello

N 回処理する」というプログラムを書く場合、次のように「i0 からはじめ、N より小さいときにループする」という形式で書くのがより一般的です。

i = 0
while i < N:
    処理
    i += 1

最初は分かりづらく感じるかもしれませんが、この形式で書いた方がプログラムをよりシンプルに書けることがあるので、慣れるようにしましょう。

なお、このプログラムの変数 i のように、「何回目のループか」を管理する変数のことをカウンタ変数と呼ぶことがあります。カウンタ変数には慣例的に i を使い、i が使えない場合は j, k, l ... と名前をつけていくことが多いです。

応用例

N 人の合計点を求めるプログラムを作ってみましょう。
次のプログラムは「入力の個数 N」と「点数を表す N 個の整数」を入力で受け取り、点数の合計を出力します。

N = int(input())

s = 0  # 合計点を表す変数
i = 0  # カウンタ変数

while i < N:
    x = int(input())
    s += x
    i += 1

print(s)
入力
3
1
10
100
実行結果
111

合計点を表す変数 s を用意して、ループするたびに入力を変数 x に受け取り s に足しています。

このように、繰り返し処理を使えば様々な処理が行えるようになります。

細かい話

細かい話なので、飛ばして問題を解いても良いです。

2 ずつ増やす

今までは i1 ずつだけ増やしてきましたが、2 ずつ増やすこともできます。

i = 0

while i < 10:
    print(i)
    i += 2
実行結果
0
2
4
6
8

以下のように書くことで i2 ずつ増やしています。

i += 2

同様にして、より多く飛ばしてループすることもできます。

逆順ループ

5 から 0 までの数を出力したい場合は以下のようにします。

i = 5

while i >= 0:
    print(i)
    i -= 1
実行結果
5
4
3
2
1
0

以下のように書くことで i1 ずつ減らしています。

i -= 1

無限ループをコードテストで実行した場合

AtCoder のコードテストでは、実行時間が長すぎるとプログラムが中断されます。また、出力が長すぎる場合も途中から省略されます。
そのため、はじめに紹介した「Hello と出力して改行した後、AtCoder と出力する処理」を無限に繰り返すプログラムをコードテストで実行しても無限には出力されず、一例としては次のように表示されます。

実行結果
Hello
AtCoder
(中略)
Hello
AtCoder
H
終了コード
9

無限ループが発生した場合、終了コードは実行時間が長すぎることを表す 9 となります。

問題

リンク先の問題を解いてください。

J - 1.09.for文・break・continue

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • for 文は繰り返し処理でよくあるパターンを while 文より短く書くための構文
  • 列の中身が順に変数に代入される
for 変数 in 列:
    処理
  • N 回の繰り返し処理は以下の for 文で書くのが一般的
for i in range(N):
    処理
  • break を使うとループを途中で抜けることができる
  • continue を使うと後の処理を飛ばして次のループへ進むことができる

for 文

for 文は列の中身を順に処理するための構文です。
for 文を使うことで「N 回処理する」というような繰り返し処理でよくあるパターンを while 文より短く書くことができます。

3 回繰り返すプログラムを while 文と for 文で書くと次のようになります。

j = 0
while j < 3:
    print("Hello while:", j)
    j += 1

for i in range(3):
    print("Hello for:", i)
実行結果
Hello while: 0
Hello while: 1
Hello while: 2
Hello for: 0
Hello for: 1
Hello for: 2

for 文は次のように書きます。

for 変数 in 列:
    処理

列として代表的なものにはリストや文字列が存在しますが、詳しくは後の節で紹介します。

N 回の繰り返し処理

N 回処理をする」というような繰り返し処理をしたいときは、range() を使うと楽です。range(a, b) と書くことで、(a, a+1, a+2, \dots , b-1) という数列が生成されます。

for i in range(0, 5):
    print(i)
実行結果
0
1
2
3
4

range(a, b)a0 のときに省略することができ、range(b) と書くことができます。よって、次の二つの書き方は同じ意味になります。

for i in range(0, 5):
    print(i)

for i in range(5):
    print(i)
実行結果
0
1
2
3
4
0
1
2
3
4

つまり、「N 回の繰り返し処理」を書きたいときは次のように書けば良いです。

for i in range(N):
    処理

break と continue

while 文と for 文を制御する命令として、breakcontinue があります。

break

break はループを途中で抜けるための命令です。

# break がなければこのループは i == 4 まで繰り返す
for i in range(5):
    if i == 3:
        print("ぬける")
        break  # i == 3 の時点でループから抜ける

    print(i)

print("終了")
実行結果
0
1
2
ぬける
終了

上のプログラムでは、if 文で i == 3 が真になったとき break 文を実行することで for ループを抜け、終了 と表示しています。

continue

continue は後の処理をとばして次のループへ進むための命令です。

for i in range(5):
    if i == 3:
        print("とばす")
        continue  # i == 3 のとき これより後の処理を飛ばす

    print(i)

print("終了")
実行結果
0
1
2
とばす
4
終了

上のプログラムでは、if 文で i == 3 が真になったとき continue 文を実行することで continue より下の部分を飛ばし、次のループに進みます。

細かい話

細かい話なので、飛ばして問題を解いても良いです。

2 ずつ増やす

上では range(a, b) という書き方のみ紹介しましたが、実は range(a, b, c) という書き方もできこれによりいくつずつ増やすかを決めることができます(c を省略したときのデフォルトは 1 なので、これまでの書き方では全て 1 ずつ増えていました)。
よって、次のように書くことで 2 ずつ増やすことができます。

for i in range(0, 10, 2):
    print(i)
実行結果
0
2
4
6
8

同様にして、より多く飛ばしてループすることもできます。

なお、いくつずつ増やすかを決めるときは a がたとえ 0 だとしても省略できないことに注意してください。つまり、上のコードで range(10, 2) と書くと異なる挙動になってしまいます。

逆順ループ

5 から 0 までの数を出力したい場合は以下のようにします。

for i in range(5, -1, -1):
    print(i)
実行結果
5
4
3
2
1
0

0 まで出力したい場合に二つ目の引数を -1 にする必要があることに注意してください。range(5) としたときに(5 までではなく)4 までしか出力されなかったのと同様に、0 まで出力したい場合はひとつ次の -1 を指定する必要があります。
また、もちろん三つ目の引数に -2 などを指定することでより多く飛ばして逆順ループすることもできます。

より一般的に、range(N) を逆順にするときは range(N - 1, -1, -1) と書くことになります。

N = 5

print("昇順")
for i in range(N):
    print(i)

print("降順")
for i in range(N - 1, -1, -1):
    print(i)
実行結果
昇順
0
1
2
3
4
降順
4
3
2
1
0

for-else, while-else

Python では for 文と while 文に else 節を書くことができます。
これは、ループが break 文で終了した場合は実行されず、そうでないとき(ループが最後まで回ったとき)に実行されます。

break しない場合

for i in range(5):
    print(i)
else:
    print("ループが最後まで回りました。")

print("終了")
実行結果
0
1
2
3
4
ループが最後まで回りました。
終了

break する場合

for i in range(5):
    if i == 3:
        print("ぬける")
        break  # i == 3 の時点でループから抜ける

    print(i)
else:
    print("ループが最後まで回りました。")

print("終了")
実行結果
0
1
2
ぬける
終了

問題

リンク先の問題を解いてください。

K - 1.10.リスト

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • リスト は様々なデータの列を扱うことができる
  • [要素0, 要素1, 要素2, ...] でリストを作ることができる
  • [0] * NN 個の 0 からなるリストを作ることができる
  • a[i] でリスト ai 番目の要素を取得できる
  • list(map(int, input().split()))1 行の入力から整数のリストを作ることができる
  • リストと for 文を組み合わせると、大量のデータを扱うプログラムを簡単に書ける

リスト

リスト(配列、list 型) はデータの列を扱うことができる非常に重要な機能です。例えば、以下のようなコードを書くことができます。

# リスト [3, 1, 4, 1, 5] を作り, a に代入する
a = [3, 1, 4, 1, 5]

# a の 0 番目の要素である 3 を出力
print(a[0])

# a の 1 番目の要素である 1 を出力
print(a[1])

# a の 2 番目の要素 (4) を 7 に変更
a[2] = 7

# a の要素を順に出力
for x in a:
    print(x)
出力
3
1
3
1
7
1
5

この章では、リストの使い方について説明します。

リストを作る

  • [] で空のリストを作ることができます。
  • [要素0, 要素1, 要素2, ...] でリストを作ることができます。
  • list( for文に入れられるもの ) でリストを作ることができます。
    • 例えば、for i in range(5): と書くと i0, 1, 2, 3, 4 が順番に入るので、list(range(5)) と書くとリスト [0, 1, 2, 3, 4] を作ることができます。
  • 下で説明する リスト内包表記 を使ってもリストを作ることができます。
# 空のリストを作り、a に代入する
a = []

# リスト [3, 1, 4, 1, 5] を作り、a に代入する
a = [3, 1, 4, 1, 5]

# いろいろな型を持つデータを 1 つのリストに入れることができる
a = ["Hello", "AtCoder", 123, 4.5, []]

# リスト [0, 1, 2, 3, 4] を作る
a = list(range(5))

リストの長さ

  • リスト a に対し、len(a)a の長さ(要素数)を取得できます。

リストの i 番目の要素

  • リスト a と整数 i に対し、a[i]ai 番目の要素を取得できます。
    • この i のこと(リストの何番目の要素かを表す番号)を 添字(そえじ) と言います。
    • リストの添字は 0 から始まることに注意しましょう。 先頭の要素は a[0] で、末尾の要素は a[len(a)-1] で取得することができます。
  • a[i] = xai 番目の要素を x に変更できます。
# リスト [3, 1, 4, 1, 5] を作り、a に代入する
a = [3, 1, 4, 1, 5]

# a の長さ 5 を出力する
print(len(a))

# a の 2 番目の要素 (4) を 7 に変更する
a[2] = 7

# range(len(a)) と書けば a の添字 (0, 1, 2, 3, 4) を順に列挙できる
for i in range(len(a)):
    # a[i] で a の i 番目の要素を取得する
    print(i, ":", a[i])
出力
5
0 : 3
1 : 1
2 : 7
3 : 1
4 : 5

for 文でリストの要素を列挙する

  • リスト a に対し、for x in a:a の要素を順に x に代入して繰り返し処理を行うことができます。
a = [3, 1, 4, 1, 5]

# a の要素を順に x に代入し、繰り返し処理を行う
for x in a:
    # 5 回実行される
    print(x)
出力
3
1
4
1
5

入力からリストを作る

  • 文字列 s に対し、s.split()s を空白で区切って文字列のリストを作ることができます。
  • 文字列のリスト a に対し、list(map(int, a))a の各要素を整数に変換したリストを作ることができます。
  • list(map(int, input().split())) で、入力から 1 行読み取り、空白で区切って整数のリストを作ることができます。
# 入力から 1 行読み取り、空白で区切って整数のリストを作る
a = list(map(int, input().split()))

print(a)
入力
886 551 37 424 531
出力
[886, 551, 37, 424, 531]

リストを出力する

  • リスト a に対し、print(*a)a の要素を空白区切りで出力できます。
a = [9, 9, 7, 3]

# a の要素を空白区切りで出力する
print(*a)

# a の要素を改行区切りで出力する
for x in a:
    print(x)
出力
9 9 7 3
9
9
7
3

リストの使い所

リストと for 文を組み合わせると、以下のように大量のデータを扱うプログラムを書くことができます。

例題

N 人の生徒が数学のテストと英語のテストを受けました。テストはそれぞれ 100 点満点で、生徒 i\ (1 \le i \le N) の数学の点数は M_i 、英語の点数は E_i でした。それぞれの生徒について、数学のテストと英語のテストの合計点を求めてください。

制約

  • 入力される値はすべて整数
  • 1 \le N \le 1000
  • 0 \le M_i \le 100\ (1 \le i \le N)
  • 0 \le E_i \le 100\ (1 \le i \le N)

入力

入力は以下の形式で与えられる。

N
M_1 M_2 \cdots M_N
E_1 E_2 \cdots E_N

出力

S_i\ (1 \le i \le N) を生徒 i の数学のテストと英語のテストの合計点とする。
以下の形式で出力せよ。

S_1
S_2
\vdots
S_N

入力例

3
20 100 30
100 5 40

出力例

120
105
70

解答例

N \le 3 のような N が非常に小さいという制約がついていれば、N で場合分けすることによってリストを使わずに解くことも可能です。しかし、N が大きくなるとこれは非現実的になってしまいます。

リストと for 文を用いれば、N の大きさに関わらず簡潔に処理を書くことができます。

# 生徒の人数 N を入力
N = int(input())

# 数学の点数 M を入力
M = list(map(int, input().split()))

# 英語の点数 E を入力
E = list(map(int, input().split()))

# それぞれの生徒について処理する
for i in range(N):
    # 生徒 i の合計点 M[i] + E[i] を出力する
    print(M[i] + E[i])

リストのさらなる機能

負の添字

  • リスト a負の整数 i に対し、a[i]a後ろから -i-1 番目の要素を取得することができます。末尾の要素は a[-1] で、先頭の要素は a[-len(a)] で取得することができます。

範囲外アクセス

  • 存在しない要素を取得しようとすると、RE が発生します。
a = [3, 1, 4, 1, 5]

# 負の添字で後ろから順番に要素を取得
print(a[-1])
print(a[-2])
print(a[-3])

# a の 5 番目の要素は存在しないので、実行時エラーが発生する
print(a[5])
出力
5
1
4
エラー出力
Traceback (most recent call last):
  File "/judge/Main.py", line 8, in <module>
    print(a[5])
          ^^^^
IndexError: list index out of range
終了コード
256

エラー出力を見ると、8 行目の a[5] の部分で、IndexError: list index out of range (リストの添字の範囲外) というエラーが起きていることがわかります。

リストをつなげる

  • リスト a とリスト b に対し、a + bab をつなげたリストを作ることができます。
  • リスト a と整数 n に対し、a * nan 回繰り返したリストを作ることができます。
# リスト [1, 6] とリスト [1, 8] をつなげて [1, 6, 1, 8] を作り、a に代入する
a = [1, 6] + [1, 8]

# [1, 6, 1, 8] に [0, 3, 3] をつなげて [1, 6, 1, 8, 0, 3, 3] とする
a += [0, 3, 3]

# リスト [0, 1, 2] を 3 回繰り返したリスト [0, 1, 2, 0, 1, 2, 0, 1, 2] を作り、a に代入する
a = [0, 1, 2] * 3

リストの末尾に要素を追加・削除する

  • リスト a と値 x に対し、a.append(x)a の末尾に要素 x を追加できます。
  • リスト a に対し、a.pop()a の末尾の要素を取得しながら削除できます。
# 空のリストを作り、a に代入する
a = []

# a の末尾に 1 を追加する。a は [1] になる。
a.append(1)
# a の末尾に 2 を追加する。a は [1, 2] になる。
a.append(2)
# a の末尾に 3 を追加する。a は [1, 2, 3] になる。
a.append(3)

# a の末尾の要素 3 を出力し、削除する。a は [1, 2] になる。
print(a.pop())
# a の末尾の要素 2 を出力し、削除する。a は [1] になる。
print(a.pop())
# a の末尾の要素 1 を出力し、削除する。a は [] になる。
print(a.pop())
出力
3
2
1

リストの好きな位置に要素を追加・削除する

  • リスト a と整数 i と値 x に対し、a.insert(i, x)ai 番目の位置 (a[i-1]a[i] の間) に x を挿入することができます。
  • リスト a と整数 i に対し、a.pop(i)ai 番目の要素を取得しながら削除することができます。

リストの途中への挿入・削除は、それ以降の要素をずらす必要があるため、末尾への挿入・削除と比べて時間がかかります。

リストの中に x があるか調べる

  • リスト a と値 x に対し、x in axa の中に 1 個以上存在するかを判定することができます。
    • not (x in a)x not in a と書くこともできます。
  • リスト a と値 x に対し、a.count(x)xa の中に何個存在するかを取得することができます。
  • リスト a と値 x に対し、a.index(x)a の中に x が出現する最初の位置を取得することができます。
# x が 1, 2, 3 のいずれかであるかを判定する
x = 2
print(x in [1, 2, 3])

a = [3, 1, 4, 1, 5]

# a の中に存在する 1 の数 (2 個) を数える
print(a.count(1))

# a の中に存在する最初の 1 の位置 (a[1]) を調べる
print(a.index(1))
出力
True
2
1

リストをソートする

  • リスト a に対し、a.sort()a の要素を昇順に並べ替えることができます。

リストを反転する

  • リスト a に対し、a.reverse()a の要素を逆順に並べ替えることができます。
a = [3, 1, 4, 1, 5]

# a を昇順に並び替える。a は [1, 1, 3, 4, 5] になる。
a.sort()
print(a)

# a を反転する。a は [5, 4, 3, 1, 1] になる。
a.reverse()
print(a)
出力
[1, 1, 3, 4, 5]
[5, 4, 3, 1, 1]

リストを複製する

リスト a に対し b = a とすると、リストは複製されず、a の指すリストと b の指すリストは同一のものになります。

# リスト [3, 1, 4, 1, 5] を作り、a に代入する
a = [3, 1, 4, 1, 5]

# a が指しているリストを b に代入する
b = a

# a の指すリストと b の指すリストは同一のため、a を変更すると b も変わっている
a[2] = 7
print(b)
# b を変更すると a も変わっている
b.append(9)
print(a)
出力
[3, 1, 7, 1, 5]
[3, 1, 7, 1, 5, 9]

これを回避するには、b = a.copy() と書いて、リストを複製する必要があります。

# リスト [3, 1, 4, 1, 5] を作り、a に代入する
a = [3, 1, 4, 1, 5]

# a が指しているリストを複製して b に代入する
b = a.copy()

# a の指すリストと b の指すリストは別物のため、a を変更しても b は変わらない
a[2] = 7
print(b)
出力
[3, 1, 4, 1, 5]

リストの一部分を複製する (スライス)

  • リスト a と整数 l,r に対し、a[l:r]a[l] から a[r-1] までの r-l 要素からなるリストを作ることができます。

リストを比較する

  • リスト a, b に対し、a == b / a != b でリストの全要素が一致しているかを判定することができます。
  • リスト a, b に対し、a < b / a <= b / a > b / a >= bab を辞書式順序で比較できます。

付録: リストにできる操作の一覧とその計算量

公式ドキュメント

より詳しい情報を知りたい場合は、以下の公式ドキュメントを参照してください。

https://docs.python.org/ja/3/library/stdtypes.html#list

問題

リンク先の問題を解いてください。

L - 1.11.文字列

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • "(二重引用符)や '(一重引用符)で囲んで文字列を作る
  • len(s) で文字列 s の長さを得られる
  • s[i] で文字列 si 文字目を得られる
  • s + t で文字列 s, t を連結できる
  • 文字列は変更不可能。一部を変更したいときは、文字のリストを作る

文字列

HelloABCDEFGあいうえお のようなテキスト(文字の並び)のことを 文字列 と言います。Python では、str 型(文字列型) を使って文字列を扱います。例えば、以下のようなプログラムを書くことができます。

# 文字列 "ABCDEFG" を作り a に代入
a = "ABCDEFG"

# 文字列 a の 0 番目の文字 "A" を出力
print(a[0])

# 入力から 1 行読み取って文字列を作り b に代入
b = input()

# 文字列 a, 空白, 文字列 b をつなげた文字列を作り出力
print(a + " " + b)
入力
あいうえお
出力
A
ABCDEFG あいうえお

本章では、この文字列の使い方について説明します。

文字列を作る

  • "(二重引用符)や '(一重引用符)で囲んだ部分が文字列として扱われます。どちらを使っても違いはありません。
# 文字列 "Hello" を作り a に代入
a = "Hello"

# 文字列 "AtCoder" を作り b に代入
b = 'AtCoder'

エスケープシーケンス

通常、以下のように文字列の中に改行をそのまま書くことはできません。

# 文字列の中に改行を入れたい
s = "Hello
AtCoder"
文法エラー
  File "Main.py", line 2
    s = "Hello
        ^^^^^^
SyntaxError: unterminated string literal (detected at line 2)
(訳)文法エラー: 終端のない文字列リテラル (2 行目で検出)

このような文法上意味のある文字を文字列に入れたい場合、\(バックスラッシュ)から始まる エスケープシーケンス を利用します。主なエスケープシーケンスは以下の通りです。

エスケープシーケンス 意味
\n 改行文字
\" "(二重引用符)
\' '(一重引用符)
\\ \(バックスラッシュ)
\t 水平タブ
# 文字列の中に改行文字を入れるには \n と書く
print("Hello\nAtCoder")

# 二重引用符で囲まれた文字列の中で二重引用符を入れるには \" と書く
# 文字列の中にバックスラッシュを入れるには \\ と書く
print("\"Hello\\nAtCoder\"")
出力
Hello
AtCoder
"Hello\nAtCoder"

文字列の長さ

  • 文字列 s に対し、len(s)s の長さ(文字数)を取得できます。

for 文で文字列の中の文字を列挙する

  • 文字列 s に対し、for x in s:s の中の文字を順に x に代入して繰り返し処理を行うことができます。
s = "AtCoder"
for x in s:
    print(x)
出力
A
t
C
o
d
e
r

入力から文字列を作る

  • input() で入力から 1 行読み取って文字列を作ることができます。

文字列を出力する

  • 文字列 s に対し、print(s)s を出力することができます。
# 入力から 1 行読み取り、そのまま出力する
print(input())
入力
Hello, AtCoder!
出力
Hello, AtCoder!

文字列をつなげる

  • 文字列 s, t に対し、s + ts, t をこの順に連結した文字列を作ることができます。
  • 文字列 s と非負整数 n に対し、s * nsn 回繰り返した文字列を作ることができます。
# "ABC" と "123" をつなげた文字列 "ABC123" を出力する
print("ABC" + "123")

# "ABC" を 3 回繰り返した文字列 "ABCABCABC" を出力する
print("ABC" * 3)
出力
ABC123
ABCABCABC

文字列を整数に変換する

  • 文字列 s に対し、int(s)s を整数に変換することができます。

整数を文字列に変換する

  • 整数 x に対し、str(x)x を文字列に変換することができます。
# 999999999999999999999999999999 + 1 を出力
print(int("9" * 30) + 1)

# 3 ** 1000 の桁数を出力
print(len(str(3 ** 1000)))
出力
1000000000000000000000000000000
478

整数・文字列変換における桁数制限

整数から文字列への変換、文字列から整数への変換において、変換に時間がかかることを防ぐため、4300 桁よりも大きな数は変換できないようになっています。整数を出力するときにも整数から文字列への変換が行われるので、この制限が適用されます。

print(10 ** 4300)
エラー出力
Traceback (most recent call last):
  File "/judge/Main.py", line 1, in <module>
    print(10 ** 4300)
ValueError: Exceeds the limit (4300) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
(訳) 値エラー: 整数・文字列変換における上限 (4300) を超えています; 上限を増やすには sys.set_int_max_str_digits() を使ってください

sys.set_int_max_str_digits(0) を実行することで、この制限を取り除くことができます。

import sys
sys.set_int_max_str_digits(0)

print(10 ** 4300)
出力
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

文字列を空白文字で区切る

  • 文字列 s に対し、s.split()s を空白文字で区切って文字列のリストを作ることができます。

文字列のリストを連結する

  • 文字列 s と文字列のリスト a に対し、s.join(a)s を区切り文字列として a の各要素を連結することができます。
# "1 23 456" を空白文字で区切り、リスト ["1", "23", "456"] を作る
a = "1 23 456".split()

# ["1", "23", "456"] を文字列 " + " で結合してできる文字列 "1 + 23 + 456" を出力する
print(" + ".join(a))
出力
1 + 23 + 456

文字列の i 番目の文字

  • 文字列 s と整数 i に対し、s[i]si 番目の文字を取得できます。
  • リストのときと同様に、負の添字やスライスを使うことができます。
# 文字列 "ABCDE" を作り s に代入する
s = "ABCDE"

# s の 0 番目の文字 "A" を出力する
print(s[0])

# s の最後の文字 "E" を出力する
print(s[-1])

# s の 1 番目から 3 番目までの文字列 "BCD" を出力する
print(s[1:4])

# s を逆順にした文字列 "EDCBA" を出力する
print(s[::-1])
出力
A
E
BCD
EDCBA

部分文字列に x があるか調べる

部分文字列とは?

文字列 s の部分文字列とは、s連続する一部分のことです。
例えば、空文字列、ABCABCABC の部分文字列ですが、DACABC の部分文字列ではありません。

  • 文字列 s, t に対し、t in ss の部分文字列に t が含まれるかどうか判定することができます。
  • 文字列 s, t に対し、s.index(t)s に現れる最初の部分文字列 t の位置を求めることができます。
  • 文字列 s, t に対し、s.count(t)s に部分文字列 t が重ならずに何回出現するかを求めることができます。
# 文字列 "ABABABA" を作り s に代入する
s = "ABABABA"

# "ABABABA" の部分文字列に "BAB" があるか判定する
print("BAB" in s)

# "ABABABA" に現れる最初の部分文字列 "BAB" の位置を求める
# s[1:4] が最初の "BAB" なので、1 を出力する
print(s.index("BAB"))

# "ABABABA" に重ならずに現れる部分文字列 "BAB" の個数を求める
# s[1:4] と s[3:6] が "BAB" であるが、重ならずに取れるのは 1 個までなので、1 を出力する
print(s.count("BAB"))

# "AAAAAAAAAA" (A が 10 個) から重ならずに取れる "AAA" は 3 個まで
print("AAAAAAAAAA".count("AAA"))
出力
True
1
1
3

部分文字列を置換する

  • 文字列 s, t, u に対し、s.replace(t, u)s に重ならずに出現する部分文字列 t をすべて u に置き換えた文字列を取得できます。
# "1 + 2 + 3" に出現する "+" を "**" に置き換えた文字列 "1 ** 2 ** 3" を出力する
print("1 + 2 + 3".replace("+", "**"))

# "AAAAA" に出現する "AA" を "X" に置き換えた文字列 "XXA" を出力する
print("AAAAA".replace("AA", "X"))
出力
1 ** 2 ** 3
XXA

文字列を比較する

  • 文字列 s, t に対し、s == t / s != tst が同じ文字列であるかを判定できます。
  • 文字列 s, t に対し、s < t / s <= t / s > t / s >= tst を辞書式順序で比較できます。

大文字・小文字かどうか判定する

  • 文字列 s に対し、s.isupper()s の文字がすべて大文字かどうか判定することができます。
    • より正確には、s.isupper()s に大文字が含まれていて、小文字が含まれないとき True を返します。
  • 文字列 s に対し、s.islower()s の文字がすべて小文字かどうか判定することができます。
    • より正確には、s.islower()s に小文字が含まれていて、大文字が含まれないとき True を返します。
# "ATCODER" はすべて大文字からなるので、"ATCODER".isupper() は True 
print("ATCODER".isupper())

# "atcoder" はすべて小文字からなるので、"atcoder".islower() は True 
print("atcoder".islower())

# 空文字列には小文字が含まれないので、"".islower() は False
print("".islower())
出力
True
True
False

数字かどうか判定する

  • 文字列 s に対し、s.isdigit()s が空でなく、s の文字がすべて数字かどうか判定することができます。
# "0123456789" は数字のみからなるので、"0123456789".isdigit() は True
print("0123456789".isdigit())

# "ABC123" には数字ではない文字が含まれるので、"ABC123".isdigit() は False
print("ABC123".isdigit())

# "".isdigit() は False
print("".isdigit())
出力
True
False
False

大文字・小文字に変換する

  • 文字列 s に対し、s.upper()s の小文字をすべて大文字に変換した文字列を取得できます。
  • 文字列 s に対し、s.lower()s の大文字をすべて小文字に変換した文字列を取得できます。
# "AtCoder" の小文字をすべて大文字に変換した文字列 "ATCODER" を出力
print("AtCoder".upper())

# "AtCoder" の大文字をすべて小文字に変換した文字列 "atcoder" を出力
print("AtCoder".lower())
出力
ATCODER
atcoder

文字列の一部を変更する

Python の文字列は 一度作ると変更することができません。 文字列の一部を変更したい場合は、一度文字のリストに変換する必要があります。

# 文字列 "AtCoder" を作り s に代入する
s = "AtCoder"

# s は for 文に入れられるものであるから、list(s) で
# リスト ["A", "t", "C", "o", "d", "e", "r"] を作れる
a = list(s)

# a の 0 番目の要素を "M" に変更する
a[0] = "M"

# a の要素をつなげて出力する
print("".join(a))
出力
MtCoder

文字

Python では、1 つの文字は長さ 1 の文字列として str 型で表現されます。 したがって、文字列から取り出した「文字」に対しても文字列に対するさまざまな機能を使うことができます。

# 文字列 "0123456789" の 0 番目の文字 "0" を c に代入
c = "0123456789"[0]

# c は長さ 1 の文字列である
print(len(c))

# c.isdigit() で "0" が数字であるか判定する
print(c.isdigit())

# int(c) で整数に変換できる
print(int(c))
出力
1
True
0

文字をコードポイントに変換する

  • 文字 c に対し、ord(c)c の Unicode コードポイントを取得できます。

コードポイントを文字に変換する

  • 整数 x に対し、chr(x) で Unicode コードポイントが x である文字を取得できます。

Unicode とは

様々な文字に番号を割り当て、文字を番号で管理できるようにしたものを 文字コード と言います。文字コードにおいて、ある文字に割り当てられた番号を コードポイント と言います。
Unicode とは、世界中のあらゆる文字に番号を割り当てた文字コードの規格で、Python の内部でも用いられています。

# 文字 "0" に割り当てられた Unicode コードポイントは 48
print(ord("0"))

# 文字 "a" に割り当てられた Unicode コードポイントは 97
print(ord("a"))

# 文字 "あ" に割り当てられた Unicode コードポイントは 12354
print(ord("あ"))

# Unicode コードポイントが 12354 である文字 "あ" を出力する
print(chr(12354))
出力
48
97
12354
あ

競技プログラミングにおいては、どのような環境でも扱うことのできる ASCII 印字可能文字 の部分しか基本的に使われません。文字コードについては、以下のことを覚えれば十分でしょう。

  • 0, 1, 2, ..., 9 のコードポイントが連続している。(48 – 57)
  • A, B, C, ..., Z のコードポイントが連続している。(65 – 90)
  • a, b, c, ..., z のコードポイントが連続している。(97 – 122)

したがって、以下のようなコードを書くことができます。

  • 英大文字 c に対して、ord(c) - ord("A") と書けば、c が何番目のアルファベットであるかがわかる。
  • 逆に、i 番目のアルファベットを得るには、chr(ord("A") + i) と書く。
  • 文字 c に対して,ord("A") <= ord(c) <= ord("Z") と書けば、c が英大文字であるかどうか判定できる。

公式ドキュメント

より詳しい情報を知りたい場合は、以下の公式ドキュメントを参照してください。

https://docs.python.org/ja/3/library/stdtypes.html#text-sequence-type-str

問題

リンク先の問題を解いてください。

M - 1.12.組み込み関数

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • 関数 は与えられた引数に対して処理を行い返り値を返す機能である
  • Python が標準で提供している組み込み関数は準備なしに使うことができる
  • 組み込み関数には数値の計算やリストの集計など、様々な便利機能を持つものが用意されている

関数

これまでの節で、標準入力を得るための input やリストの長さを得るための len などの機能を用いてきました。
これらの機能はより正確には「関数」と呼ばれるものになります。関数とは、与えられた値(引数)に対してある定められた処理を行い、処理の結果の値(返り値)を返す道具です。中には引数が無い関数、返り値が無い関数、複数の返り値を返す関数も存在します。

何度も行う処理を関数としてまとめることで、色々な値に対する処理の結果を計算したいときにプログラムの記述量を大きく減らすことができます。そのため、大半のプログラミング言語において関数は必須の機能となっています。

用語の確認のため、これまでに出てきたいくつかの関数の引数・処理内容・返り値を整理します。

関数 引数 処理内容 返り値
len リストや文字列 長さを取得する 長さ (整数値)
input 無し 1 標準入力から1行取得する 標準入力の1行 (文字列)
print 文字列, 整数 など 標準出力に出力する 無し2
divmod 数値2つ 剰余を計算する 1つめの数値を2つめの数値で割った商と余り

Python 標準の関数

leninput は関数の中でも特別なもので、Python が標準で提供している組み込み機能、とりわけ組み込み関数と呼ばれるものになります。Python が標準で提供しているため、ユーザは特に準備なく使用することができます。
これまでの節で出てきたものを含め、Python では全部で71種類の組み込み関数が用意されています3

以下ではその中でも競技プログラミングにおいて比較的利用されることの多いものを紹介します。

abs

数値の絶対値を計算して返します。

a = -3
b = 5
a_abs = abs(a)
b_abs = abs(b)
print(a_abs, b_abs)
実行結果
3 5

pow

pow(a,b)ab 乗の値を計算します。
pow(a,b,mod)ab 乗を mod で割った余りを計算します。

a = 3
b = 4
mod = 10
res = pow(a, b)
res2 = pow(a, b, mod)
print(res, res2)
実行結果
81 1

なお、べき乗は 1.3 節で扱った ** 演算子でも計算できますが、組み込み関数 pow を用いたほうが高速に計算できます。
また、余りは pow(a,b) % mod のように後から計算しても同じ結果になりますが、pow(a,b) の値が非常に大きくなる場合は pow(a,b,mod) のほうが高速に計算できます。
競技プログラミングにおいては pow 関数を使うことが必須であるケースが多いため覚えておきましょう。

min max

与えられた2つ以上の数値の中の最小値, 最大値を計算して返します。

min_val = min(1, 3, -5, 2)
max_val = max(1, 3, -5, 2)
print(min_val, max_val)
実行結果
-5 3

数値をリストとして与えることも可能です。

l = [1, 3, -5, 2]
min_val = min(l)
max_val = max(l)
print(min_val, max_val)
実行結果
-5 3

sum

リストに含まれる値の合計を計算して返します。

l = [1, 3, -5, 2]
sum_val = sum(l)
print(sum_val)
実行結果
1

sorted

リストをソートし、新たなリストを返します。

l = [1, 3, -5, 2]
new_l = sorted(l)
print("元のリスト:", l)
print("新たなリスト:", new_l)
実行結果
元のリスト: [1, 3, -5, 2]
新たなリスト: [-5, 1, 2, 3]

1.10 節で扱った l.sort() と異なり、元のリストはソートされていない点に注意してください。

all any

all は与えられたリストの要素すべてが条件式として真であるかを判定します。
any は与えられたリストの要素の中に条件式として真であるものが1つ以上存在するかを判定します。

l = [1, 3, -5, 2]
res = all([v>0 for v in l]) # l に含まれる値が全て正か?
res2 = any([v%2==0 for v in l]) # l に偶数が含まれるか?
print(res, res2)
実行結果
False True

なお、空のリストに対して allTrue を、anyFalse を返します。

print(all([]), any([]))
実行結果
True False

enumerate

for i,v in enumerate(リスト): のように書くことでリストのインデックスと値を同時に取得することができます。

l = [1, 3, -5, 2]
for i,v in enumerate(l):
    print(i, "番目の要素は", v, "です")
実行結果
0 番目の要素は 1 です
1 番目の要素は 3 です
2 番目の要素は -5 です
3 番目の要素は 2 です

次のように書いても同一の結果になりますが、enumerate を使うほうが単純に記述することができます。

l = [1, 3, -5, 2]
for i in range(len(l)):
    v = l[i]
    print(i, "番目の要素は", v, "です")    

問題

リンク先の問題を解いてください。

Ex12.最速のランナーを見つけよう

前のページ | 次のページ


  1. input は実は引数を与えることも可能です。引数を与えるとその内容が標準出力に出力されます。ユーザにどのような入力を入れてほしいか伝えるときなどに便利ですが、競技プログラミングで用いることは稀でしょう。 

  2. より厳密には、None という「何ものでもない値」を返しています。 

  3. Python 3.12 時点。こちらから一覧を見ることができます。 

N - 1.13.関数

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

キーポイント

  • 関数を定義するためにはdef 関数名(パラメータ):という記法を用いる
  • 関数の戻り値を返すにはreturn文を用いる
  • 関数外の変数を更新するには global 文を用いる

関数を自作する

前項では、今まで扱ってきた inputlen が関数であったことや、これ以外にも色々な関数があることを学びました。この関数は予め用意されたものだけではなく、自分で動作を定めた関数を作成することも可能です。このように関数を作成することを、「関数を定義する」と呼びます。このように関数を定義するメリットの一つとして、複数の場所で行われる同じ処理をまとめることができるという点があります。

最も単純な関数定義

まず、最も単純な関数定義から見ていきます。以下は、1, 2, 3を 3 行で出力するという処理をする関数の定義です。

def print_numbers():
    print(1)
    print(2)
    print(3)

defは定義の英語であるdefineから来ているキーワードで、関数の定義をすることを表します。それに続く部分(今回の場合はprint_numbers)は関数の名前を表し、変数名と同様に自由な名前が使用できます。その後の (): の部分は後ほど説明しますので、今は読み飛ばすこととします。

2 行目以降は、関数の処理を表す部分です。これは関数が呼ばれる度に処理されます。通常の Python のコードと同じように書くことができますが、インデントをする必要がある点には注意してください。

復習となりますが、関数は関数名の後にカッコをつけることで呼び出すことができます。この場合では、以下のようになります。

print_numbers() # 1, 2, 3が改行されて出力される

なお、関数は定義した後でないと呼び出すことができません。その点には注意してください。たとえば、以下のようなコードは実行時エラーとなります。

print_one() # NameError: name 'print_one' is not defined

def print_one():
  print(1)

引数を取る関数定義

次に、min(1, 2) のように値を渡すことができる関数を定義してみます。以下は、第一引数と第二引数を足した数を出力する関数の定義と、その実行結果です。

def add_and_print(a, b):
    print(a + b)

add_and_print(1, 2) # 3 が出力される

新しく出てきた事項として、一行目の(a, b)という記述があります。これは、関数の後に書かれた一番目の要素(第一引数)をaというパラメータに、二番目の要素(第二引数)をbというパラメータに格納することを意味しています。このパラメータは関数の処理部分で変数のように用いることができます。

よって、この関数をadd_and_print(1, 2)のようにして呼び出した場合、aには1bには2が格納され、その状態でprint(a + b)が実行された結果として3が出力されることになります。

戻り値を持つ関数定義

ここまでの文法では min のような関数を実装することはできません。これは、return 文を用いることで、関数の中から呼び出し側に値を返すことができます。このような関数の「結果」を戻り値とよびます。以下は、return 分を用いた第一引数に 1 を足した値を返す関数の定義です。

def add_one(a):
    return a + 1

return 文の後には、関数の戻り値としたい値を記述します。すると、その値が関数呼び出しの式の値となります。よって、以下のように変数に代入したり、直接関数の引数として渡すことも可能です。

two = add_one(1) # 変数 two は 2 となる
print(two) # 2 が出力される
print(add_one(1) + 1) # 3 が出力される

また、return文は実行された時点で関数の処理を終了するという役割もあります。これについては、後ほど詳述します。

まとめ

まとめると、関数の定義は以下のような文法で行うこととなります。

def 関数名(パラメータ):
    処理

実は、関数のパラメータにはここでは説明しなかった文法がいくつか存在しています。これを用いると、print関数のように引数の数を自由にできたり、sep=''のように名前で指定できたりするパラメータを作成できるようになります。
興味のある方は、Python公式ドキュメント内の用語集 - parameterを参照してください。

関数定義時のテクニック

return 文の特性と複数の return 文を持つ関数

return 文は、同じ関数内の複数の箇所に書くことができます。例えば、以下はabの小さい方を戻り値とする関数の定義です。

def my_min(a, b):
    if a < b:
        return a
    else:
        return b

if文がどのようなものだったかを思い出すと、abより小さいときにreturn aが、そうでないときにreturn bが実行されることになると分かります。

return 文は、実行された時点で関数の処理を終了します。つまり、以下のadd_one関数のreturn a + 1以降に書かれた文が実行されることはありません。

def add_one(a):
    return a + 1
    print("ここには到達しない")
    return a + 2 # この行にも到達しない
    print("もちろんここにも到達しない")

これを用いると、my_minを以下のように書き換えることができます。

def my_min(a, b):
    if a < b:
        return a
    # a < b のケースでは return a が実行されているため、ここには到達しない
    return b

このコードでは、return bが実行されるのはa < bでないときのみです。何故ならば、a < bのときはreturn aが実行されるので、そこで関数の処理が終了するためです。

また、値を返さない関数1でも、関数の処理を早期に終了する目的でreturn文を使用することができます。

def print_a_is_7(a):
    if a == 7:
        print("a is 7")
        return
    # a == 7 のケースでは return が実行されているため、ここには到達しない
    print("a is not 7")

例えば、上の例では a == 7 のときには print("a is not 7") が実行されません。これは、a == 7 のときは return が実行されているので、そこで関数の処理が終了するためです。

関数内の変数

通常のプログラムと同様に、関数内でも変数を用いることができます。しかし、関数内で使用した変数は、基本的には関数の外部で使用することはできません。

以下の関数は、add_one関数を変数を使って書き直したものです。

def add_one(a):
    result = a + 1
    return result

print(add_one(1)) # 2 が表示される
print(result) # NameError: name 'result' is not defined

この関数自体は、想定している通りの動作をします。しかし、関数を呼び出した後にresult変数を参照しようとしても、存在しない変数を使用しようとしたことを示すエラーが発生してしまいます。

変数を使用できる範囲のことをスコープと呼びます。今回の場合、result変数のスコープはadd_one関数内であるということになります。

一方で、関数の外の変数は自由に使用することが可能です。以下は、変数aの値をプリントするprint_a関数を用いた例です。

a = 0
def print_a():
    print(a)

print_a() # 0 が表示される
a = 1
print_a() # 1 が表示される

変数aは関数の外で宣言されていますが、その値をprint_a関数の内部で用いることができていることが分かります。これは、変数aのスコープがグローバル(つまり、コード全体)であるためです。このような変数のことをグローバル変数と呼びます2

一方で、関数内でグローバル変数を変更する場合には注意が必要です。以下は、受け取った変数をaに代入することを意図した関数update_aを用いた例です。

a = 0
def update_a(val):
    a = val

update_a(1)
print(a) # 0 が出力される

この例から分かる通り、単に代入文を書くだけでは関数内ではグローバル変数の値を変更することができません3。グローバル変数に値を代入したい場合は、global文を使用します。

a = 0
def update_a(val):
    global a
    a = val

update_a(1)
print(a) # きちんと 1 が出力される

関数内にてglobal 変数名という形でglobal文を使用すると、関数内で指定した変数を使用した際にグローバル変数として扱うようになります。また、複数の変数を指定したい場合は、global a, b, c のようにカンマで区切ることで指定することができます。

global文が必要な条件については一見複雑そうに見えますが、まとめれば「関数外部でも変数を使用していて、かつ関数内で代入をしている」場合となります。

よく混乱する例として、list等を代入せずに変更するケースがあります。例えば、以下のようなケースではglobal文は必要ありません。

li = []
def update_li(val):
    li.append(val)

update_li(1)
print(a) # [1] と出力される

これは、変数liは変更されてはいるものの代入されていないためです。global文が必要となるケースは、以下のように変数liに代入しているケースです。

li = []
def update_li(val):
    global li
    li = li + [val]

update_li(1)
print(a) # [1] と出力される

nonlocal

ここからは、global文についての補足となります。複雑なプログラムを書かない内は必要となることがないであろう知識なので、読み飛ばしても構いません。

for文の中にfor文を入れることができたのと同様に、Pythonでは関数内で関数を定義することが可能です。この際、以下のように関数内で用いたい外部の変数がグローバル変数でない場合が存在します。

def get_1():
    value = 0
    def set_1():
        # ここで用いている value はグローバル変数ではないので、global は使えない
        value = 1 # Error: local variable 'value' referenced before assignment
    set_1()
    return value

このような場合に使用できる文として、nonlocal文が存在します。これを用いて上のコードを書き直すと、以下の通りとなります。

def get_1():
    value = 0
    def set_1():
        nonlocal value
        value = 1
    set_1()
    return value

問題

リンク先の問題を解いてください。

EX13.三人兄弟へのプレゼント

前のページ | 次のページ


  1. この表現は正確ではありません。Pythonは全ての関数が戻り値を持ち、それはprint()といった関数も例外ではありません。このように一見戻り値を持たないように見える関数は、実はNoneという「何もない」を意味する特別な値を返しています。 

  2. 対して、スコープがグローバルでない変数をローカル変数と呼びます。 

  3. この際、関数内で使用している変数aと関数外で使用している変数aは別の変数になります。これは変数のシャドウイングと呼ばれます。シャドウイングは混乱の種となりやすいため、初学者のうちは行わない方が無難でしょう。本教材でも、シャドウイングをするコードは登場しません。 

O - 2.00.第2章について(準備中)

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ

第1章修了

修了のイラスト

第1章お疲れ様でした。

1.00から1.13までの問題を全てACしたあなたは、理論上は全ての「計算処理」を行うプログラムを書ける程の知識を身に着けました。


第2章について

現在準備中です。


ぜひコンテストに参加してみましょう!

AtCoder Beginner Contest

毎週土曜日の午後9時からは、AtCoder Beginner Contestが開催されていますので、ぜひコンテストに参加してみましょう。最新のコンテスト情報はこちらからご確認ください。

AtCoder Daily Training

AtCoder Beginner Contestの過去問を使用した練習用バーチャルコンテストです。
毎週火曜・水曜・木曜の夕方から夜にかけて1日3回行っています。
難易度はEASYをおすすめします。

AtCoderで強くなるには?

AtCoderのコンテストの復習方法やコンテスト以外での学習方法が書いてあります。
上記リンク先は、AtCoderInfo内のページです。


前のページ

AP1 - 付録1.コードテストの使い方

Time Limit: 0 msec / Memory Limit: 0 KB

EX1「出力の練習 / 1.01」に戻る
EX5「A足すB問題 / 1.05」に戻る


コードテストの場所

練習問題を解くときは「コードテスト」というページを使ってプログラムを書き、正しく動作することが確認できたら提出するようにしましょう。

コードテストのページは、次の画像の赤い四角で囲った部分をクリックすることで開けます。
コードテストの場所

プログラムの実行

設定ができたら、「ソースコード」と書かれている場所にプログラムを書きます。
プログラムが書けたら「言語」が「Python(CPython 3.11.4)」または「Python (PyPy 3.10-v7.3.12)」になっていることを確認し、ページ下部にある「実行」ボタンを押してください。

コードテストの画面

実行結果

プログラムが実行できたら「標準出力」と書かれている場所にプログラムの出力が表示されます。

実行結果

エラーが発生したとき

エラーが発生した場合は「標準エラー出力」と書かれている場所にエラーの詳細が表示されます。

たとえば開きカッコに対応する閉じカッコがない場合、SyntaxError となります。

print(123

標準エラー出力

File "Main.py", line 1
    print(123
         ^
SyntaxError: '(' was never closed

エラーの内容をヒントにプログラムを修正し、また実行してください。

エラーの直し方については1.02.プログラムの書き方とエラーで説明します。

EX1「出力の練習 / 1.01」に戻る


ここから先の説明はEX5「A足すB問題 / 1.05」を解く時に読んでください。

コードテストでの入力

コードテスト上で入力機能を使う場合、「標準入力」と書かれている場所に入力を書き、実行ボタンをクリックします。

標準入力

AP2 - 付録2.提出結果の見方

Time Limit: 0 msec / Memory Limit: 0 KB

EX2「エラーの修正 / 1.02」に戻る
EX5「A足すB問題 / 1.05」に戻る


AtCoder上でのエラーの表示

エラーの種類とAtCoder上の表示の対応は次の表の通りです。

エラーの種類 ジャッジの判定 終了コード
コンパイルエラー (Compile Error) -1
実行時エラー (Runtime Error) 0以外
論理エラー (Wrong Answer) 0(エラーがない時と同じ)
実行時間制限超過※ (Time Limit Exceeded) 9

「ジャッジの判定」は提出後の採点結果のことです。
「終了コード」はコードテスト上でプログラムを実行した後、画面の下部に表示されている数値のことです。

コードテスト上でコンパイルエラーが発生した場合、「標準エラー出力」にエラーの詳細が表示されます。

エラーの内容を読んだり、表示されているエラー内容を検索したりしてエラーを修正しましょう。

※実行時間制限超過がAPG4bPythonで発生する場合、提出先を間違えている可能性があります。説明ページではなく問題ページ(EX◯◯)に提出しているかを確認しましょう。

EX2「エラーの修正 / 1.02」に戻る


ここから先の説明はEX5「A足すB問題 / 1.05」を解く時に読んでください。

ACを取るには

入力を使う問題では、「ある入力ではACだったが、別の入力ではWAだった」という事がありえます。

例えば「A + Bを計算する問題」で、間違えてプログラムの出力をA - Bとしてしまったとします。
この場合でも、入力がA = 5, B = 0だったとき、プログラムの出力と正解はどちらも5となり一致し、この入力に対しては
となります。
しかし、入力がA = 2, B = 1だったとき、プログラムの出力は1となりますが、正解は3なので一致せず、この入力に対してはとなります。

自分のプログラムの出力 正解 入力に対する採点結果
A = 5, B = 0 5 5
A = 2, B = 1 1 3

問題の採点結果をにするには、その問題の入力のパターン全てに対して正しい出力をする必要があります。


提出の詳細の確認方法

採点結果がだった場合は「提出の詳細」を見ると、いくつの入力例に対してACであり、いくつの入力例に対してWAであるかを見ることができます。

この画面から実際にどのような入力が行われるかを確認することはできませんが、提出したプログラムがどれくらい正しいかのヒントにはなります。

提出の詳細を見るには、まず問題ページで「提出一覧」→「自分の提出」をクリックします。

提出一覧

すると自分の提出の一覧が表示されるので、見たい提出を選んで「詳細」をクリックすると、提出の詳細を見ることができます。

提出の詳細

「提出一覧」→「すべての提出」をクリックすることで、他の人の提出を見ることもできます。
他の人のプログラムを見ることも勉強になるので、うまく活用してください。

EX1 - コードテストと出力の練習

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題を解く前に 付録1.コードテストの使い方を読んでください。


問題文

次の出力をするプログラムを書いてください。

実行結果
こんにちは
AtCoder

出力の最後(つまり AtCoder の後)に改行する必要があります。注意してください。

回答プログラムの作成方法

回答プログラムは、次のサンプルプログラムを改変して作成することを推奨します。
プログラムをコピーし、コードテストのページに貼り付けましょう。

サンプルプログラム
print("Hello, world!")
print("Hello, AtCoder!")
print("Hello, Python!")
サンプルプログラムの実行結果
Hello, world!
Hello, AtCoder!
Hello, Python!

これを次の出力を行うようにプログラムを書き換え、正しく動作することが確認できたら提出しましょう。

正しい実行結果
こんにちは
AtCoder

「AtCoder」の「C」は大文字であることに注意しましょう。


解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る
print("こんにちは")
print("AtCoder")
EX2 - エラーの修正

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題を解く前に 付録2.提出結果の見方を読んでください。


問題文

A君は次の出力をするプログラムを作ろうとしました。

実行結果
いつも2525
AtCoderくん

しかし、書いたプログラムを実行してみるとエラーが発生しました。
A君が書いたプログラムのエラーを修正し、正しく動作するようにしてください。

Aくんが書いたプログラム
print("いつも2525"
    print(AtCoderくん)

このコードをコードテストで実行すると、標準エラー出力に以下のエラーメッセージが表示されます。

標準エラー出力
  File "Main.py", line 1
    print("いつも2525"
         ^
SyntaxError: '(' was never closed

この問題の取り組み方

Aくんのプログラムには複数のエラーが含まれています。
わかるエラーから一つずつ直し、コードテスト上で実行してみて、直っているかどうか確かめましょう。

コードテストの使い方は付録1.コードテストの使い方に書いてあります。

「AtCoder」の「C」は大文字であることに注意しましょう。

ヒント

1.02.プログラムの書き方とエラーの「エラーの例」を参考にしましょう。


解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る
print("いつも2525")
print("AtCoderくん")
EX3 - 計算問題

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

Aくんは1から100までの和を求めようと思いました。
数学の授業で習ったとおり、1から100までの和は次の式で求められます。

\dfrac{1}{2} \times 100 \times (100+1)

この式の値を出力してください。
ただし、答えを整数値で出力させるため 割り算に//演算子を使って解いて下さい。 /を使うとWAになります。

ヒント

「1.03.四則演算と優先順位」の「注意点」に書かれている項目を読んでみましょう。

コードテストで正しく動作することを確認してから提出しましょう。


解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る
# // 2を最後に計算することで正しい計算結果になる
print(100 * (100 + 1) // 2)
EX4 - ◯年は何秒?

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

次のプログラムをコピー&ペーストして、指定した場所にプログラムを追記することで問題を解いて下さい。

seconds = 365 * 24 * 60 * 60
print()  # 1年は何秒か出力
print()  # 2年は何秒か出力
print()  # 5年は何秒か出力
print()  # 10年は何秒か出力

int型の変数secondsは一年の秒数を表しています。これを利用して

  • 1年は何秒か
  • 2年は何秒か
  • 5年は何秒か
  • 10年は何秒か

を順に一行ずつ表示するプログラムを作って下さい。
うるう秒やうるう年のことは考え無くて良いとします。

実行結果(一部を「?????」で隠しています)
31536000
63072000
?????
?????

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る
seconds = 365 * 24 * 60 * 60
print(seconds)  # 1年は何秒か出力
print(seconds * 2)  # 2年は何秒か出力
print(seconds * 5)  # 5年は何秒か出力
print(seconds * 10)  # 10年は何秒か出力
EX5 - A足すB問題

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題を解く前に、以下の2つのリンク先の説明を読んでください。

問題文

2つの整数A, Bが与えられます。A+Bの計算結果を出力してください。

制約

  • 0 \le A, B \le 100
  • A, B は整数

入力

入力は次の形式で標準入力から与えられます。

A B

出力

A+B の計算結果を出力してください。出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

1 2

出力例1

3

入力例2

100 99

出力例2

199

テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
0 0
テスト出力1
0

テスト入力2
0 50
テスト出力2
50

テスト入力3
0 50
テスト出力3
50

テスト入力4
27 81
テスト出力4
108

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

A, B = map(int, input().split())
print(A + B)
EX6 - 電卓をつくろう

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

1行の計算式が与えられるので、その結果を出力してください。

与えられる計算式のパターンと対応する出力は以下の表の通りです。

入力 出力 備考
A + B A + Bの計算結果を出力
A - B A - Bの計算結果を出力
A * B A \times Bの計算結果を出力
A / B A \div Bの計算結果を出力 小数点以下は切り捨てて出力
B0 の場合はerrorと出力
A ? B errorと出力
A = B errorと出力
A ! B errorと出力
サンプルプログラム

このプログラムを元に解答を作成することを推奨します。

A, op, B = input().split()
A = int(A)
B = int(B)

if op == "+":
    print(A + B)

# ここにプログラムを追記

制約

  • 0 \le A, B \le 100
  • A, B は整数
  • \mathrm{op}+, -, *, /, ?, =, ! のいずれか一つ

入力

入力は次の形式で標準入力から与えられます。

A \mathrm{op} B

出力

入力の計算式の計算結果を出力してください。
出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

1 + 2

出力例1

3

入力例2

5 - 3

出力例2

2

入力例3

10 * 20

出力例3

200

入力例4

10 / 3

出力例4

3

計算結果の小数点以下は切り捨てます。


入力例5

100 / 0

出力例5

error

B0 の場合は error と出力することに注意してください。


入力例6

25 ? 31

出力例6

error

入力例7

0 + 0

出力例7

0

テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
100 = 100
テスト出力1
error

テスト入力2
17 ! 91
テスト出力2
error

テスト入力3
0 / 20
テスト出力3
0

テスト入力4
0 * 0
テスト出力4
0

テスト入力5
0 - 0
テスト出力5
0

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

A, op, B = input().split()
A = int(A)
B = int(B)

if op == "+":
    print(A + B)
elif op == "-":
    print(A - B)
elif op == "*":
    print(A * B)
elif op == "/" and B != 0:
    print(A // B)
else:
    print("error")
EX7 - bool値パズル

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

次のプログラムで宣言されている bool 型の変数 a, b, c に対し、True または False を代入することで、AtCoder と出力されるようにしてください。

1, 2, 3 行目における変数 a,b,c への代入以外のプログラムの書き換えは行わないものとします。

プログラム
a =  # True または False
b =  # True または False
c =  # True または False

# ここから先は変更しないこと

assert (a is True) or (a is False)
assert (b is True) or (b is False)
assert (c is True) or (c is False)

if a:
    print("At", end="")
else:
    print("Yo", end="")

if not a and b:
    print("Bo", end="")
else:
    print("Co", end="")

if a and b and c:
    print("foo!", end="")
elif True and False:
    print("year!", end="")
elif not a or c:
    print("der", end="")

print("")

入力

この問題に入力はありません

出力

AtCoder と出力してください。


回答例

答え方の例です。
変数 a, b, c の全てに False を代入していますが、YoCoder と出力されているので、この解答は不正解となります。

a = False  # True または False
b = False  # True または False
c = False  # True または False

# ここから先は変更しないこと

assert (a is True) or (a is False)
assert (b is True) or (b is False)
assert (c is True) or (c is False)

if a:
    print("At", end="")
else:
    print("Yo", end="")

if not a and b:
    print("Bo", end="")
else:
    print("Co", end="")

if a and b and c:
    print("foo!", end="")
elif True and False:
    print("year!", end="")
elif not a or c:
    print("der", end="")

print("")

出力例

YoCoder

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

a = True  # True または False
b = False  # True または False
c = True  # True または False

# ここから先は変更しないこと

assert (a is True) or (a is False)
assert (b is True) or (b is False)
assert (c is True) or (c is False)

if a:
    print("At", end="")
else:
    print("Yo", end="")

if not a and b:
    print("Bo", end="")
else:
    print("Co", end="")

if a and b and c:
    print("foo!", end="")
elif True and False:
    print("year!", end="")
elif not a or c:
    print("der", end="")

print("")
EX8 - たくさんのA足すB問題

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

以下の問題を N 回解いてください。

2 つの整数 A, B が与えられます。A+B の計算結果を出力してください。

制約

  • 1 \le N \le 10
  • 0 \le A_i, B_i \le 100
  • N, A_i, B_i は整数

入力

入力は次の形式で標準入力から与えられます。

N
A_1 B_1
A_2 B_2
\vdots
A_N B_N

出力

N 行出力してください。

i 行目には、A_i+B_i の計算結果を出力してください。出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

1
42 37

出力例1

79

入力例2

4
3 1
4 1
5 9
2 6

出力例2

4
5
14
8

ヒント

クリックでヒントを見る

この問題は EX5.A足すB問題 と同じ処理を N 回繰り返すことで解くことができます。また、「N 回繰り返す」という操作は while 文を用いて書くことができます。


テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
1
79 68
テスト出力1
147
テスト入力2
4
90 46
73 74
93 21
99 42
テスト出力2
136
147
114
141
テスト入力3
5
49 81
46 39
50 89
26 97
84 46
テスト出力3
130
85
139
123
130
テスト入力4
8
13 54
81 51
8 64
89 85
44 51
51 94
39 84
2 45
テスト出力4
67
132
72
174
95
145
123
47
テスト入力5
10
76 15
58 31
21 40
86 88
77 58
77 33
25 70
8 81
67 79
73 99
テスト出力5
91
89
61
174
135
110
95
89
146
172

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

N = int(input())
i = 0
while i < N:
    A, B = map(int, input().split())
    print(A + B)
    i += 1
EX9 - 電卓をつくろう2

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

電卓の操作が与えられるので、計算途中の値と計算結果の値を出力してください。


電卓の操作は次の形式で入力されます。

入力の形式
計算の数N
最初の値A
演算子\mathrm{op}_1 計算する値B_1
演算子\mathrm{op}_2 計算する値B_2
\vdots
演算子\mathrm{op}_N 計算する値B_N

次の入力は ((2 + 1) \times 3) \div 2 を表しています。

入力例
3
2
+ 1
* 3
/ 2

出力では「何行目の出力か」と、「計算途中の値」を出力してください。

出力の形式
1 1個目の計算結果
2 2個目の計算結果
\vdots
N N個目の計算結果

次の出力は上の入力例に対する出力です。

出力例
1 3
2 9
3 4

与えられる入力のパターンと対応する処理は以下の表の通りです。

入力 処理 備考
+ B それまでの計算結果に B を足し、その値を出力する。
- B それまでの計算結果から B を引き、その値を出力する。
* B それまでの計算結果に B を掛け、その値を出力する。
/ B それまでの計算結果を B で割り、その値を出力する。 小数点以下は切り捨てて計算を行う。
B0 の場合はerrorと出力し、それ以降は出力を行わない。

/ B において、B0 の場合は error と出力し、それ以降は出力を行わない ことに注意してください。

ページ末尾に問題のヒントがあります。詰まったら見てみましょう。


サンプルプログラム
N = int(input())
A = int(input())
# ここにプログラムを追記

制約

  • 1 \le N \le 7
  • 0 \le A, B_i \le 10
  • A, B_i, N は整数
  • \mathrm{op}_i+, -, *, / のいずれか

入力

入力は次の形式で標準入力から与えられます。

N
A
\mathrm{op}_1 B_1
\mathrm{op}_2 B_2
\vdots
\mathrm{op}_N B_N

出力

1 1個目の計算結果
2 2個目の計算結果
\vdots
N N個目の計算結果

出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

3
2
+ 1
* 3
/ 2

出力例1

1 3
2 9
3 4

問題文中で説明した入出力です。


入力例2

2
3
/ 2
/ 2

出力例2

1 1
2 0

割り算では小数点以下を切り捨てます。


入力例3

4
3
+ 1
/ 0
* 2
- 10

出力例3

1 4
error

割り算で B_i0 の場合は error と出力し、それ以降は出力をしないことに注意してください。


入力例4

7
10
* 10
* 10
* 10
* 10
* 10
* 10
* 10

出力例4

1 100
2 1000
3 10000
4 100000
5 1000000
6 10000000
7 100000000

ヒント1

次のプログラムは、5つの整数を入力で一つずつ受け取り、受け取った整数を足して出力します。
また、今回の問題と同様に、出力が何行目かも同時に出力します。
今回の問題を解く際の参考にしてください。

クリックでヒントプログラムを見る

total = 0

for i in range(5):
    x = int(input())

    total += x

    # 行番号 合計値 の形式で出力
    print(i + 1, total)

ヒント入力

3
4
2
1
10

ヒント出力

1 3
2 7
3 9
4 10
5 20

ヒント2

ジャッジでテストされる入力のうち2つをヒントとして示します。
サンプルは全てあっていてWAの原因がわからない人は、以下のケースに正解しているか確かめてみましょう。

クリックでテストケースを見る

テスト入力1

7
0
- 5
* 7
/ 4
+ 0
+ 0
- 10
* 5

テスト出力1

1 -5
2 -35
3 -9
4 -9
5 -9
6 -19
7 -95

テスト入力2

6
0
/ 4
/ 3
/ 5
+ 3
/ 7
/ 1

テスト出力2

1 0
2 0
3 0
4 3
5 0
6 0

テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
7
0
- 5
* 7
/ 4
+ 0
+ 0
- 10
* 5
テスト出力1
1 -5
2 -35
3 -9
4 -9
5 -9
6 -19
7 -95

テスト入力2
6
0
/ 4
/ 3
/ 5
+ 3
/ 7
/ 1
テスト出力2
1 0
2 0
3 0
4 3
5 0
6 0

テスト入力3
3
1
* 4
* 3
/ 0
テスト出力3
1 4
2 12
error

テスト入力4
7
0
* 2
/ 0
+ 1
/ 0
+ 5
* 2
- 10
テスト出力4
1 0
error

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

N = int(input())
A = int(input())

for i in range(N):
    op, x = input().split()
    x = int(x)

    if op == "+":
        A += x
    elif op == "-":
        A -= x
    elif op == "*":
        A *= x
    elif op == "/" and x != 0:
        A //= x
    else:
        print("error")
        break

    print(i + 1, A)
EX10 - 平均との差

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

N 人のテストの点数が与えられます。
それぞれの人の点数が平均点から何点離れているか計算してください。

平均点は次の式で求められます。i 番目の人の点数は A_i で表します。

平均点 = \dfrac{A_1 + A_2 + \cdots + A_N}{N}

平均点が整数にならない場合、小数点以下を切り捨てた数値を平均点とします。

例えば 3 人のテストの点数が「2 点、1 点、4 点」だったとき、\frac{2 + 1 + 4}{3} = 2.333 \cdotsなので、平均点は小数点以下を切り捨てて 2 点になります。
そして、平均点から何点離れているかを計算した結果である「0 点、1 点、2 点」が答えになります。
0 点、-1 点、2 点」でも「0 点、1 点、-2 点」でも無いことに注意してください。

ページ末尾に問題のヒントがあります。詰まったら見てみましょう。


サンプルプログラム
N = int(input())
# ここにプログラムを追記


制約

  • 1 \le N \le 1000
  • 0 \le A_i \le 100
  • N, A_i は整数

入力

入力は次の形式で標準入力から与えられます。

N
A_1 A_2 \cdots A_N

出力

それぞれの人の点数が平均点から何点離れているかを1行ずつ出力してください。

1人目の計算結果
2人目の計算結果
\vdots
N人目の計算結果

出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

3
2 1 4

出力例1

0
1
2

問題文中で説明した入出力です。


入力例2

2
80 70

出力例2

5
5

このケースの平均点は 75 点です。
どちらの点数も平均点から 5 点離れています。


入力例3

5
100 100 100 100 100

出力例3

0
0
0
0
0

このケースの平均点は 100 点です。


入力例4

10
53 21 99 83 75 40 33 62 18 100

出力例4

5
37
41
25
17
18
25
4
40
42

ヒント

今回の問題は次のプログラムに追記すれば解くことができます。
追記箇所が2つあることに注意してください。

クリックでヒントプログラムを見る

N = int(input())

# スペース区切りの整数をリストとして受け取る
A = list(map(int, input().split()))

# 合計点
total = 0

# 合計点を計算
for i in range(N):
    # ①ここにプログラムを追記

# 平均点 (Nで割って切り捨てた値)
mean = total // N

# 平均点から何点離れているかを計算して出力
for i in range(N):
    # ②ここにプログラムを追記
    # 負の数を出力しないように注意

テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
1
80
テスト出力1
0

テスト入力2

データが大きすぎるため省略


解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

N = int(input())

# スペース区切りの整数をリストとして受け取る
A = list(map(int, input().split()))

# 合計点
total = 0

# 合計点を計算
for i in range(N):
    # ①ここにプログラムを追記
    total += A[i]

# 平均点 (Nで割って切り捨てた値)
mean = total // N

# 平均点から何点離れているかを計算して出力
for i in range(N):
    # ②ここにプログラムを追記
    # 負の数を出力しないように注意
    if A[i] > mean:
        print(A[i] - mean)
    else:
        print(mean - A[i])
EX11 - 足したり引いたり

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

1+-のみからなる式 S1 行で与えられるので、計算結果を出力してください。

例えば式 S1+1+1-1 であったとき、計算結果は 2 です。

具体的な式 S の形式は以下の通りです。

  • S1 文字目は必ず 1 です。
  • その後、「+ または -」と 1 が交互に続きます。
  • S の最後の文字も必ず 1 です。

式と演算子はスペースで区切られていないことに注意してください。

ページ末尾に問題のヒントがあります。詰まったら見てみましょう。


サンプルプログラム
S = input()
# ここにプログラムを追記

制約

  • 1 \le |S| \le 100|S| は文字列の長さ)
  • S1 から始まり、その後「+ または -」と 1 が交互に続き、1 で終わる

入力

入力は次の形式で標準入力から与えられます。

S

出力

Sの計算結果を出力してください。

出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

1+1+1-1

出力例1

2

問題文中で説明した入出力です。


入力例2

1-1-1-1-1-1

出力例2

-4

計算結果は負の値になることもあります。


入力例3

1

出力例3

1

入力は 1 だけで終わることもあります。


入力例4

1-1-1+1+1+1+1-1+1-1+1-1+1

出力例4

3

ヒント

次のプログラムは 9 文字の式 S にいくつ 1 が含まれているかを出力するプログラムです。
今回の問題を解く際の参考にしてください。

クリックでヒントプログラムを見る

S = input()

count = 0

# 9 文字の式に限定していることに注意
for i in range(9):
    if S[i] == "1":
        count += 1

print(count)

ヒント入力

1-1-1+1+1

ヒント出力

5

テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1+1
テスト出力1
-25

テスト入力2
1+1+1+1+1+1+1+1+1+1+1+1+1
テスト出力2
13

テスト入力3
1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1
テスト出力3
-33

テスト入力4
1+1-1+1-1+1-1+1-1+1-1+1-1+1-1+1+1-1-1+1+1-1-1+1+1+1-1-1-1+1
テスト出力4
2

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

S = input()

# 計算結果を保持する変数
answer = 1

for i in range(len(S)):
    if S[i] == "+":
        answer += 1
    if S[i] == "-":
        answer -= 1

print(answer)

in の後ろに文字列を指定することで、文字に対して繰り返し処理を行うこともできます。

S = input()

# 計算結果を保持する変数
answer = 1

for c in S:
    if c == "+":
        answer += 1
    if c == "-":
        answer -= 1

print(answer)
EX12 - 最速のランナーを見つけよう

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

学校の授業で持久走がありました。N 人の生徒がゴールまでにかかった時間(秒数)がそれぞれ T_1, T_2, \dots , T_N で与えられます。一番早くゴールしたのは何番目の生徒でしょうか。

ページ末尾に問題のヒントがあります。詰まったら見てみましょう。


サンプルプログラム
N = int(input())  # 生徒の数Nを読み込む
T = list(map(int, input().split()))  # 各生徒のゴールまでの時間を読み込む
# ここにプログラムを追記

制約

  • 1 \leq N \leq 100
  • 100 \leq T_i \leq 1000 (全ての i について)
  • 全ての生徒のゴールまでにかかった時間は異なる

入力

入力は次の形式で標準入力から与えられます。

N
T_1 T_2 ... T_N

出力

一番早くゴールした生徒の番号を出力してください。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

5 
300 450 200 400 350

出力例1

3

3 番目の生徒の 200 秒が最速のタイムになります。


入力例2

1 
400

出力例2

1

1 人で走るときは常に最速ランナーになることができます。


入力例3

10 
883 940 579 641 979 999 331 842 667 518

出力例3

7

ヒント

クリックでヒントを見る

二段階のステップで考えてみましょう。問題を解くために必要な情報は 2 つあります。
1.最小値が何か
2.最小値が何番目に現れるか
一度に求めようとせずに、1. と 2. を順番に調べるコードを書いてみましょう。


テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
100 
794 341 925 159 319 451 671 720 836 667 664 917 114 112 276 479 623 796 152 910 566 996 656 567 756 105 139 172 694 771 148 906 164 983 852 419 863 357 895 732 608 398 227 165 785 532 613 136 304 198 303 475 434 502 189 477 588 439 969 686 520 168 967 344 972 828 694 786 256 338 493 721 390 874 632 888 702 911 550 971 802 427 646 443 487 594 826 949 245 834 596 674 810 526 395 541 227 665 948 723
テスト出力1
26

テスト入力2
100 
171 981 971 462 134 134 174 115 445 664 109 418 836 310 163 198 474 825 200 903 788 933 127 193 781 859 719 215 558 454 306 664 359 692 424 417 337 634 772 343 265 126 159 847 981 577 691 601 713 464 654 572 559 339 177 497 420 112 475 357 297 152 547 382 770 871 787 502 477 138 276 443 349 374 279 873 837 762 769 573 479 216 186 307 798 140 820 976 473 825 606 580 342 370 456 171 266 730 748 810
テスト出力2
11

テスト入力3
100 
390 507 538 277 832 570 897 460 638 456 708 466 228 442 672 107 557 599 320 578 979 239 792 541 776 377 878 124 847 262 563 246 369 115 258 380 472 899 139 913 323 637 353 200 804 320 727 687 457 499 206 752 815 522 416 746 964 804 834 548 821 689 981 101 428 862 969 935 173 941 104 891 954 267 466 424 398 231 227 320 488 931 904 494 955 663 499 558 728 396 741 446 219 826 782 893 398 113 904 683
テスト出力3
64

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

N = int(input())  # 生徒の数Nを読み込む
T = list(map(int, input().split()))  # 各生徒のゴールまでの時間を読み込む
T_min = min(T)
for i, v in enumerate(T):
    if v == T_min:
        print(i + 1)
        break
EX13 - 三人兄弟へのプレゼント

Time Limit: 2 sec / Memory Limit: 1024 MB

説明ページに戻る

問題文

三人兄弟の A 君と B 君と C 君は、お父さんに 1 つのプレゼントを貰うことになりました。
貰えるプレゼントの予算は「テストの合計点の積」で決まります。

三人兄弟はそれぞれ N 個のテストを受けました。
A 君と B 君と C 君の「i 番目のテストの点数」をそれぞれ A_i, B_i, C_i で表すと、プレゼントの予算は次の式で求まります。
プレゼントの予算 = (A_1 + A_2 + \cdots + A_N) \times (B_1 + B_2 + \cdots + B_N) \times (C_1 + C_2 + \cdots + C_N)

例えば、2 個のテスト受けた結果、A 君は 5 点と 7 点、B 君は 4 点と 10 点、C 君は 9 点と 2 点だったとします。
この場合、(5 + 7) \times (4 + 10) \times (9 + 2) = 12 \times 14 \times 11 = 1848 より、プレゼントの予算は 1848 円になります。

A 君はこの計算を行うプログラムを途中まで書きました。
A 君が書いたプログラムに追記し、プログラムを完成させてください。

ページ末尾に問題のヒントがあります。詰まったら見てみましょう。


A君が書いたプログラム
def sum_scores(scores):
    """
    1 人のテストの点数を表すリストから合計点を計算して返す関数

    引数 scores: scores[i] に i 番目のテストの点数が入っている
    返り値: 1 人のテストの合計点
    """
    # ここにプログラムを追記


def output(sum_a, sum_b, sum_c):
    """
    3 人の合計点からプレゼントの予算を計算して出力する関数

    引数 sum_a: A 君のテストの合計点
    引数 sum_b: B 君のテストの合計点
    引数 sum_c: C 君のテストの合計点
    返り値: なし
    """
    # ここにプログラムを追記


# -------------------
# ここから先は変更しない
# -------------------


def input_list(N):
    """
    N 個の入力を受け取ってリストに入れて返す関数

    引数 N: 入力を受け取る個数
    返り値: 受け取った N 個の整数値からなるリスト
    """
    l = list(map(int, input().split()))
    return l


# 科目の数 N を受け取る
N = int(input())

# それぞれのテストの点数を受け取る
A = input_list(N)
B = input_list(N)
C = input_list(N)

# それぞれの合計点を計算
sum_A = sum_scores(A)
sum_B = sum_scores(B)
sum_C = sum_scores(C)

# プレゼントの予算を出力
output(sum_A, sum_B, sum_C)

制約

  • 1 \le N \le 10
  • 0 \le A_i, B_i, C_i \le 100
  • N, A_i, B_i, C_i は整数

入力

入力は次の形式で標準入力から与えられます。

N
A_1 A_2 \cdots A_N
B_1 B_2 \cdots B_N
C_1 C_2 \cdots C_N

出力

プレゼントの予算を出力してください。

出力の最後には改行が必要です。


ジャッジでは以下の入力例以外のケースに関してもテストされることに注意。

入力例1

2
5 7
4 10
9 2

出力例1

1848

問題文で説明したケースです。


入力例2

3
100 100 100
100 100 100
100 100 100

出力例2

27000000

300 \times 300 \times 300 = 27000000 なので、三人兄弟は 27000000 円分のプレゼントを貰えることになりました。


入力例3

5
95 20 74 81 10
100 50 32 84 31
0 0 0 0 0

出力例3

0

C 君の合計点が 0 点だったので、プレゼントの予算も 0 円になります。


入力例4

2
10 0
0 5
1 1

出力例4

100

ヒント1

クリックでヒントを見る

今回の問題は今までの問題とは少し異なり、用意されたプログラムの動作を理解し、意図を読み取る必要があります。
プログラムがどのような順番で実行されていくかに注意して、A 君が書いたプログラムを読んでみましょう。

ヒント2

この問題は「A 君が書いたプログラムに追記して完成させる」という問題ですが、ヒントとして関数を使わずにこの問題と同じ処理をするプログラムを示します。このプログラムを参考にして A 君の sum_scores 関数と output 関数を完成させてください。

クリックでヒントプログラムを見る

# 科目の数 N を受け取る
N = int(input())

# それぞれのテストの点数を受け取る

# N 個の入力をそれぞれ受け取り、リスト A, B, C とする
A = list(map(int, input().split()))
B = list(map(int, input().split()))
C = list(map(int, input().split()))

# 以下はプレゼントの予算を出力する処理

# テストの点数を表すリストからそれぞれの合計点を計算
sum_a = sum(A)
sum_b = sum(B)
sum_c = sum(C)

# 3 人の合計点からプレゼントの予算を計算して出力する
print(sum_a * sum_b * sum_c)

テスト入出力

書いたプログラムがACにならず、原因がどうしてもわからないときだけ見てください。

クリックでテスト入出力を見る

テスト入力1
10
2 8 3 1 10 8 32 15 9 100
5 1 2 0 3 2 1 10 43 20
0 100 7 10 0 82 19 0 90 51
テスト出力1
5871804

解答例

必ず自分で問題に挑戦してみてから見てください。

クリックで解答例を見る

def sum_scores(scores):
    """
    1 人のテストの点数を表すリストから合計点を計算して返す関数

    引数 scores: scores[i] に i 番目のテストの点数が入っている
    返り値: 1 人のテストの合計点
    """
    s = sum(scores)
    return s


def output(sum_a, sum_b, sum_c):
    """
    3 人の合計点からプレゼントの予算を計算して出力する関数

    引数 sum_a: A 君のテストの合計点
    引数 sum_b: B 君のテストの合計点
    引数 sum_c: C 君のテストの合計点
    返り値: なし
    """
    print(sum_a * sum_b * sum_c)


# -------------------
# ここから先は変更しない
# -------------------


def input_list(N):
    """
    N 個の入力を受け取ってリストに入れて返す関数

    引数 N: 入力を受け取る個数
    返り値: 受け取った N 個の整数値からなるリスト
    """
    l = list(map(int, input().split()))
    return l


# 科目の数 N を受け取る
N = int(input())

# それぞれのテストの点数を受け取る
A = input_list(N)
B = input_list(N)
C = input_list(N)

# それぞれの合計点を計算
sum_A = sum_scores(A)
sum_B = sum_scores(B)
sum_C = sum_scores(C)

# プレゼントの予算を出力
output(sum_A, sum_B, sum_C)