この記事はpaizaのQiitaコラボ記念として作成したZennで投稿した記事の移植版である。
目的
ここにある問題の内容は基本誰もができるので記事が存在しない。ならば作ってしまえというのが今回の主旨。
記事を作ることで、悩んでいる人が解決に向かうことを祈って。
対象
Pythonの基礎くらいはできる人。でも応用は無理な人。
持っている技術が『最初の一歩』から『Dランク獲得』までの人。
読まなくてもいいあらすじ
「せっかくpaizaのアカウント作ったから、なにかしら解いてみよう!」
そう言って早二年。そんなことよりGodotでゲーム開発じゃRustの研究じゃ子供向けの問題じゃと面倒くさくなり忘れ去られる。
しかし!
なにを思い立ったか、突然paizaを開き問題を解き始める。
たんなる暇つぶしか、はたまたAmazonのギフトカード目当てか、ともかく動機は何であれアカウントは再起動する。
ある日、他の解法がないか問題の解説を開く。そこで俺は感じた。「paizaの答え、ないやつもあんじゃねぇか・・・なら、作っちまえばいいねがたっくさん貰えるんじゃねぇのか~?」とデンジの声が聞こえてくる。脳内でインスタントヘヴンが鳴り響く。
―――結局は承認欲求である。
( ゚Д゚)<ちなみにPythonの解法はpaizaにすべてある。よって、この記事は打つだけ無駄である!
問題を解く前に
- 1
ここでは「レベルアップ問題集」を解く方法を説明しているため、paizaランクが上がることはない。ランクをとっとと上げたいなら、上にある「問題集」の隣の「スキルチェック」をやるように。
- 2
# coding: utf-8
paizaで言語を変更するときにPythonを指定するとこのコメントが先頭に出るが、決して消してはいけない!これを消すとコードが動かなくなる。
ここではおなじまいと説明しておくが、このコメントが何をしているのか知りたいなら下の「おまけ」を読むように。
- 3
深夜三時まで執筆作業、この文字数だ。
推敲する気にもなれんので、文章がところどころおかしくてもそのままになっている場合があるが無視してください。
最初の一歩
自己紹介セット
( ゚Д゚)<やぁ!
自己紹介
結局のところHello World!
である。
print()
と入力して標準出力を行えばいいのである。
print("name: 名前")
print("language: 言語")
print("hitokoto: 一言")
実際のところ、こんなんでも正解である。
print("name:")
print("language:")
print("hitokoto:")
仕組み上、ここの出力を見ているだけである。
name:
language:
hitokoto:
後でこの仕組みを使った悪用例を載せる。
標準入力サンプル問題セット
( ゚Д゚)<paizaでもAtCoderでも必須な技能。それが標準入力であるっ。
1つのデータの入力
Pythonであればinput()
を使うことで標準入力を楽に実装できる。
input_line = input()
print(input_line)
1行のデータの入力
Pythonであればinput()
だけでいいのだが、ほかの言語だとそうもいかない時がある。例としてはC言語のcharとstrの違いなのだが・・・ここの概念は君が別の言語を学ぶときに覚えよう。今はPythonだ。
input_line = input()
print(input_line)
3行のデータの入力
複数の標準入力問題である。適当にinput()
してprint()
を行えば問題はない。
A = input()
B = input()
C = input()
print(A)
print(B)
print(C)
ちなみに出力の形を見ているだけなので、こんなコードでも問題ない。
input_line = []
for _ in range(3):
input_line.append(input())
for i in input_line:
print(i)
range()
の仕様は次で解説を行う。
N行のデータの入力
さきほどの応用である。最初に数値の入力を行い、その分だけ入力を行う形になる。
この問題は配列と数値での入力が必要になる。
N = int(input())
input_line = []
for _ in range(N):
input_line.append(input())
for i in input_line:
print(i)
range()
を繰り返しと使うことで特定の回数分繰り返せる。
range()
の仕様としては、5を入力するとクラス型のrangeとしてrange(5)
と出力し、またlist(range(5))
と入力することでリスト型の[0,1,2,3,4]と出力する。
range(1,5)
と入力することで1から開始することができ[1,2,3,4]となる。また、range(1,5,2)
と入力することで2個飛ばしで数値を取得する形となり[1,3]となる。
ここで出てきたクラス型は今は覚えなくてもいい。しかし、Pythonでは非常に重要な内容のため名前だけ知っておくとよい。
ということでrange()
にNを代入することで特定の回数繰り返すことができる。
しかし、Pythonはおバカなことに入力した文字はすべて文字型に変換する(Pythonの型を知らないなら「Python 型」とでもGoogleで検索しよう)。
そのため、int()
と入力して型を指定してやらねばなるまい。
float()
でもいいし、list()
でもいい。入力した型を変換したいならこういう方法があると知っておこう。
ちなみに入力した文字をあとで変換するのも問題ない。
N = input()
N = int(N)
突き詰めていくとPythonの型はあまりにクソな仕様で動いている事が分かれば君は上級者だ!多分。
配列の入力はappend()
で行える。間違ってadd()
とでも打たないように。
ちなみに配列の長さ問題があるが、現時点では気にしなくてよろし。
ところで、Pythonにはリスト内包表記というものがある。それを使うとこのように入力ができる。
input_line = [input() for _ in range(N)]
まぁ、基本はここにある内容をコピーアンドペーストすればいいので、初心者であれば詳しく覚える必要はない。ただ、構文として覚えるとなにかと便利です。
3つのデータの入力
文字と文字の区切りに空白がある場合。空白ごとに切り分ければよい。
a,b,c = input().split()
print(a)
print(b)
print(c)
split()
を使い空白で区切るようにする。また、空白でなくともsplit()
の中に文字列を入れることでそこが区切り文字となるため覚えておくとよい。後でこれ使う。
N個のデータの入力
これもPythonは影響を受けない。他の言語で問題になる。
忘れてはいけないのが、最初に入力する文字数を入力させられるのでそれを対処すること。
N = int(input())
input_line = input().split()
for i in input_line:
print(i)
カンマ区切りの3つのデータの入力
さきほどの応用である。空白からカンマで区切るように変更する。
input_line = input().split(",")
[print(i) for i in input_line]
それから、print()
の出力をリスト内包表記で行っているが、正直これは好みの問題である。
カンマ区切りのN個のデータの入力
打つ内容がない。
N = int(input())
input_line = input().split(",")
[print(i) for i in input_line]
小話
これだけ覚えてもらいたい。
Pythonだったらinput()
ですむが、他の言語だとscanf()
やらfgets()
やら出てくるのでこんなに問題があることを頭の片隅も片隅に入れてもらいたい。決して変な使い方を進めているわけではない。
Dランクレベルアップメニュー
( ゚Д゚)<正直最初のほうはさっきのと差がないっ。
2 つの数値を出力
STEP: 1 1 つの文字列を出力
「自己紹介」の変更版。Hello World
ができれば問題なし。
print("paiza")
STEP: 2 2 つの文字列を出力
「STEP: 1 1 つの文字列を出力」の応用。
print("paiza learning")
STEP: 3 1 行の出力
「STEP: 1 1 つの文字列を出力」の応用。
print(813)
文字列として出力しても正解する。
print("813")
この問題を解いたついでにprint()
のちょっとした仕様を覚えよう。
Pythonではprint()
で標準出力を行う時、int型とstr型を同時に出力することはできない。
print(123 + "です。")
そのため、123
をstr()
で囲む必要がある。
print(str(123) + "です。")
STEP: 4 3 行の出力
連続で出力する問題。
print(8)
print(1)
print(3)
どの言語でもそうだが、標準出力で改行を行う場合は\n
を使う。
print("8\n1\n3")
Pythonの場合、強制的に改行を行うprint()
しかないため、改行したくない場合はprint("",end="")
を使う。end=""
は、後ろにある見えない\n
を別の文字列に置き換えるという認識でよい。
2 つの数値を出力
「STEP: 2 2 つの文字列を出力」の応用。
print("1 1")
もしくは数値として出力する場合ならこうなる。
print(1,1)
print()
にはカンマで区切ることによって空白区切りができる。
ちなみにpaizaの解法は下の通り。
print("{} {}".format(1, 1))
このコードを見て、ここまで出力の方法を書いてなかったのを思い出したので詳しく書いていく。
まず下のコードを見てもらいたい。
print("1 2")
print("1",end=" ");print("2")
print(str(1)+" "+str(2))
print(str(1),str(2))
print(1,2)
print(f"{1} {2}")
print("{} {}".format(1,2))
print("%d %d" % (1,2))
これらはすべて同じ出力である。
上から順番に見ていく。
一行目のprint("1 2")
だが「STEP: 2 2 つの文字列を出力」でやっている内容である。ただ単純に文字列の出力を行っているだけである。
二行目のprint("1",end=" ");print("2")
はend=" "
を行うことで、見えない\n
を半角スペースに変換し、もう一度print()
を出力するようにしている。
ちなみにセミコロンで一行にまとめられるが正直使わなくてよい。Code Golfをやらないなら覚えなくていい。
三行目はprint(str(1)+" "+str(2))
であり、文字列の連結を行っている。
input_line = "文字列を" + "こんな風に" + "繋げられる!"
四行目のprint(str(1),str(2))
と五行目のprint(1,2)
はさきほどのカンマ区切りによる半角スペース区切りでの出力である。
違いはstr型で出力するかint型で出力するかである。ちなみにend=""
とやるようにsep=""
を使うことで半角スペースを変換することができる。
六行目のprint(f"{1} {2}")
はf""
と入力することで{}
の中にある変数を出力するようにする。
input_line = "これが出力される!"
print(f"{input_line}")
七行目のprint("{} {}".format(1,2))
は昔の言語と似ている使い方をする。
" ".format()
とし、出力したい変数をformat()
の括弧の中に入れることによって{}
の部分で出力される。
初学としてPythonを学んでいくなら、よほどのことがないかぎり七行目のprint("{} {}".format(1,2))
を使うよりも、六行目のprint(f"{1} {2}")
を使うほうがいいと思われる。
八行目のprint("{} {}" % (1,2))
は正直Pythonを使うなら覚えなくてよい。この書き方は昔からある言語を世襲しているようなものである。
C言語という言語があるが、この行と同じように打ち同じ出力するときはこうする。
printf("%d %d",1,2);
ともかく後ろに変数を入れて出力するというのは、ある種昔からのならわしに近い。
代入演算 1
STEP: 1 足し算
1231と5178を足す問題。
print(1231 + 5178)
ちなみにさきほど悪用できると書いていたが、ちょうどここらへんです。
print(6409)
暗算できるならこんなんでヨシッ。
ちなみにpaizaで宣伝してくれとかいっているコードモンスターでも同じことができます。
STEP: 2 割り算
print(437326 // 9085,437326 % 9085)
こちらも適当にできます。
print("48 1246")
STEP: 3 累乗
print(((202 + 134)*107)**2)
答えを直接入力できるのはいやですか?だが私はやる!
print("1292546304")
代入演算 1
ここで初めてアルゴリズムを読んで実装する問題の登場。
N = 0
N = N + 3286
N = N * 4736
N = N % 12312
print(N)
イコールの後にNを入れなくてもこんな感じでも動く。
N = 0
N += 3286
N *= 4736
N %= 12312
print(N)
なんならこうでいい。
print(3286 * 4736 % 12312)
計算について
+
、-
、*
、/
、の四つを基本としているので、これさえ覚えれば他の言語でも何とかなる。
他の算術演算子として、**
、//
、%
がある。
数学での累乗は^
を使うが、プログラムの累乗は**
を使うため注意が必要となる。ちなみにPythonの余り出力は%
であるが―――BASICやNimなど一部の言語は代わりにmod
を使う。
ちなみにビット演算子もあるが、この時点であればまだ覚えなくてよい。
半角スペース区切りの 2 つの入力
STEP: 1 1 行の入力
「1行のデータの入力」と変わらない。
s = input()
print(s)
STEP: 2 2 行の入力
「3行のデータの入力」と変わらない。
s = input()
t = input()
print(s)
print(t)
STEP: 3 1 つの入力
「1行のデータの入力」と変わらない。
なんならさっきの一行入力と変わらない。
s = input()
print(s)
半角スペース区切りの 2 つの入力
「3つのデータの入力」の変更。
s_1,s_2 = input().split()
print(s_1)
print(s_2)
乗客人数
STEP: 1 入力された 2 つの文字列を出力
「STEP: 2 2 行の入力」の変更。
S = input()
T = input()
print(S)
print(T)
STEP: 2 引き算・掛け算
この問題は引数をint型にする必要がある。
A,B = map(int,input().split())
print(A-B,A*B)
ここで行っているmap(int,input().split())
は構文みたいなものなので覚えておくとよい。
具体的な使い方についてはDランクを卒業してからだ!
STEP: 3 代入演算 2
「代入演算 1」と「STEP: 2 引き算・掛け算」の応用。
A,B,C = map(int,input().split())
N = 0
N += A
N *= B
N %= C
print(N)
乗客人数
さきほどの「STEP: 3 代入演算 2」ができれば問題はない。
a,b,c = map(int,input().split())
print(a - b + c)
占い
STEP: 1 単純な条件分岐
初めての条件式。
文字列の長さを出力したいならlen()
を使おう。
N = input()
if len(N) == 5:
print("YES")
else:
print("NO")
STEP: 2 数値の分岐
数値での条件式。
こちらは以上と以下、未満と超えるを扱う。
N = int(input())
if N <= 100:
print("YES")
else:
print("NO")
もしくはこちらでも可能。
N = int(input())
if N < 101:
print("YES")
else:
print("NO")
ちなみに、条件式の<=
と>=
。それから<
と>
があるが、どれを使いどちらに向けるのかという派閥があるとかないとか・・・。
STEP: 3 数値演算結果で分岐
「乗客人数」と「STEP: 2 数値の分岐」の応用。
A,B,C = map(int,input().split())
if A * B <= C:
print("YES")
else:
print("NO")
占い
「STEP: 1 単純な条件分岐」と「STEP: 2 数値の分岐」の応用。
n = int(input())
if n == 7:
print("Yes")
else:
print("No")
商の余りをみるコードも可能。
n = int(input())
if n % 7 == 0:
print("Yes")
else:
print("No")
FizzBuzz
STEP: 1 ある数字までの出力 2
入力された数値分表示するという問題。
ここで注意なのはrange()
を使うとき、0から数え始めるという点である。
input_line = int(input())
for i in range(input_line):
print(i+1)
例えば5が入力されたとする。このとき、range()
には[0,1,2,3,4]の配列ができ、iに順番に格納していく。そのため、そのまま出力すると1からではなく0から開始することになるため、どこかで一を足さなければならない。
ということでprint()
の中にi + 1
の計算式を入れている。
なお、range()
は初期値を決めることができる。
input_line = int(input())
for i in range(1,input_line+1):
print(i)
range(1,input_line+1)
とすることで[1,2,3,4,5]とすることができる。
FizzBuzz
非常に有名なFizzBuzz問題。
一から数え上げていき、三の倍数なら「Fizz」、五の倍数なら「Buzz」、両方の倍数(十五の倍数)なら「Fizz Buzz」、それ以外なら直前の数値に一を足すというアルゴリズムとなる。
説明文をちゃんと読み解かないと解けない系の問題が出てきたかな。
ともかく、今までの問題を応用して解こう。
for i in range(1,101):
if i % 15 == 0:
print("FizzBuzz")
elif i % 3 == 0:
print("Fizz")
elif i % 5 == 0:
print("Buzz")
else:
print(i)
おや、これもprint()
の連続でできそうですねぇ・・・。
print()のみ
print(1)
print(2)
print("Fizz")
print(4)
print("Buzz")
print("Fizz")
print(7)
print(8)
print("Fizz")
print("Buzz")
print(11)
print("Fizz")
print(13)
print(14)
print("FizzBuzz")
print(16)
print(17)
print("Fizz")
print(19)
print("Buzz")
print("Fizz")
print(22)
print(23)
print("Fizz")
print("Buzz")
print(26)
print("Fizz")
print(28)
print(29)
print("FizzBuzz")
print(31)
print(32)
print("Fizz")
print(34)
print("Buzz")
print("Fizz")
print(37)
print(38)
print("Fizz")
print("Buzz")
print(41)
print("Fizz")
print(43)
print(44)
print("FizzBuzz")
print(46)
print(47)
print("Fizz")
print(49)
print("Buzz")
print("Fizz")
print(52)
print(53)
print("Fizz")
print("Buzz")
print(56)
print("Fizz")
print(58)
print(59)
print("FizzBuzz")
print(61)
print(62)
print("Fizz")
print(64)
print("Buzz")
print("Fizz")
print(67)
print(68)
print("Fizz")
print("Buzz")
print(71)
print("Fizz")
print(73)
print(74)
print("FizzBuzz")
print(76)
print(77)
print("Fizz")
print(79)
print("Buzz")
print("Fizz")
print(82)
print(83)
print("Fizz")
print("Buzz")
print(86)
print("Fizz")
print(88)
print(89)
print("FizzBuzz")
print(91)
print(92)
print("Fizz")
print(94)
print("Buzz")
print("Fizz")
print(97)
print(98)
print("Fizz")
print("Buzz")
これで正解になります。ナンデヤ!
ちなみにこんな記事もあります。興味があったら読んでみてね。
Dランク・スキルチェック過去問題セット
( ゚Д゚)<ここの問題ができれば、Dランクは終了っ!
Eメールアドレス
「2 つの数値を出力」の応用。
s = input()
t = input()
print(s + "@" + t)
しかし、これだと味気ないので「2 つの数値を出力」で行った出力で試しましょう。
print(s,end="@");print(t)
print(str(s)+"@"+str(t))
print(f"{s}@{t}")
print("{}@{}".format(s,t))
print("%s@%s" % (s,t))
いろいろな出力方法があって面白いですね。
【殿堂入りキャンペーン】N倍の文字列
いいよ最後の問題!これができればDランクは終了となります。
ここまでやってきたなら、今までの方法を使って解くことができます。
N = int(input())
for _ in range(N):
print("*",end="")
ちなみにこの方法がもっとも簡潔です。
N = int(input())
print("*" * N)
paizaのDランクを受けて
ここまでやってきたことはFizzBuzz問題でよく言われている「順次」「繰り返し」「分岐」の3つの制御構造と標準的な入力と出力です。
ここから先は関数やクラス、ファイルの読み込み書き込みなど、難しい内容が出てきますが、ここまでしっかりと呼んでいるのであればおそらくはできるでしょう。
最後に。
プログラムはいわゆるDIYだと覚えておいてね。日曜大工のちょっとした技術で小さな問題を解決できる、そういう認識で学んでいこう。そこから転じて本業として働く人もいるだろうけど、本質はなにかぴったり合うものを作る。それががプログラムというものだ!
おまけ
結局# coding: utf-8
ってなに?
文字コードです。
最初にUTF-8の文字コードを指定しておくことで、UTF-8で読み取ってくれます。
なぜこれを指定するのかというと、なにも指定しない場合shift-jsという文字コードで読み取る場合があるからです。
そうすると文字コードの不一致で、読み取っている文字の解釈が変わるからです。そしてコードが動かないという事が起きます。
ちなみに、今の時代よほどの理由がない限りはshift-jsで作らないでください。本当に。マジで。使ったらパソコンごと燃やすぞ。
標準入力セット
こちらのサイトにだいだい載っています。
配列の標準入力。
# 改行しながら入力
input_line = [input() for _ in range(N)]
# 文字列
a,b,c = input().split()
input_line = input().split()
input_line = list(map(str, input().split()))
# 整数
a,b,c = map(int, input().split())
input_line = list(map(int, input().split()))
おまけで配列の標準出力。
print(input_line)
[print(i) for i in input_line]
[print(i,end=",") for i in input_line]
この記事を作成して
マジで時間を無駄にした気がする。
正直ここにある内容は理解している。Pythonの仕様が破壊されたとかは一切なく、今持っている知識でどうにでもなった。
ただ、こういう記事を書くのは楽しかったからいいか。
さー二週間後には前期期末試験だ。あーあ、時間が無駄になった・・・。
あと、paizaのプログラミングスキルチェックを数問やってみたところ、こんなデータが出来ました。
1942008分52秒ってなんだ!?ちゃんちゃん。