はじめに
Python学習歴1か月くらいの自分が「え!こんな書き方あるの?」と驚いたものをまとめました。学習記録寄りのtipsです。
本記事のターゲット
・Pythonを始めて数か月〜1年くらいの人
・文法はある程度知ってるけど「もっと Python らしい書き方したい」人
・Paiza BランクやAtCoder初級に挑戦中の人
今回登場するテクニック
- 逆順: s[::-1]
- 出現回数: Counter.most_common()
- 集合の共通部分: set(A) & set(B)
- 範囲選択(スライス): [l-1:r]
※本記事は問題例と解答を5問分紹介します。
解説や初心者っぽいコード例はありません。
初心者、博識な方関係なく、余力がある方はコメント欄にご自身のコードや解説解釈を載せて頂けると喜びます。
きっかけとしては、PaizaのBランク相当の問題をすらすらと解けるように、またAランク突破の練習として、chatGPTに問題を生成してもらっていました。解答解説を見ると、意味の分からないコードばかり。記述できないばかりか、初見で挙動が分からないのは気になります。そこでそのままchatGPTに質問しました。
自分の質問:
こんなのどこで学ぶの?
その辺の入門書のPython文法とかには載ってないよね。
辞書的な公式ドキュメンを端から読んで暗記するなんて、
普通の人はやらないだろうし。
経験で学んでいくの?
ChatGPT:
いい質問ですね 👍
おっしゃる通り、
s[::-1](逆順)
Counter.most_common()(最頻値)
set(A) & set(B)(集合の共通部分)
みたいな書き方って 公式の文法書や教科書にはあまり体系的に載っていないんです。
ではどうやって身につけるか?大きく3つのルートがあります。
1. 経験で学ぶ
多くの人は「競技プログラミング」「実務の課題」「AtCoder/Paiza/LeetCode」などを解いているうちに、
「もっと楽に書ける方法ないかな?」と調べて → 発見して → 吸収します。
例:「文字列逆順にしたいな…」→ forで書こうとする
→ 「Python reverse string」で検索 → s[::-1] を発見!
こういう 必要に迫られて調べる学び方 が多いです。
2. 公式ドキュメントは辞書的に使う
確かに最初から全部読むのは無理。
でも「気になる関数や挙動が出てきたとき」だけ調べるのが普通です。
逆順 → 「Python string slice」
出現回数 → 「Python count most common element」
集合の共通部分 → 「Python set intersection」
というように キーワード検索してたどり着く。
(公式ドキュメントは「検索で引っかかったら読む」くらいで十分。)
3. 他人のコードを読む(模倣)
これ、めちゃくちゃ効果的です。
GitHub
AtCoderの解説コード
Qiitaの記事
Stacなどを見て「え、こんな短く書けるの!?」と驚いて、真似して覚える。
これを繰り返すと、自分の引き出しがどんどん増えていきます。
💡つまりまとめると:
最初は経験ベース(問題を解きながら必要に応じて調べる)
中盤から模倣ベース(他人のコードを読んで吸収する)
後半は応用(複数の書き方を知っていて、自分の好みや状況で選びます。
なるほど。やはりこういった地道なサイクルでいくしかないか、ということで、本日の学習をまとめました。
問題1:文字列の回文判定
与えられた文字列が回文(前から読んでも後ろから読んでも同じ)か判定せよ。
入力:
level
出力:
YES
入力:
python
出力:
NO
解答コード
s = input().strip()
if s == s[::-1]: # 文字列を逆順にして比較
print("YES")
else:
print("NO")
問題2:頻度カウント(最多出現文字)
文字列が与えられる。最も多く出現する文字を出力せよ。
入力:
banana
出力:
a
解答コード
from collections import Counter
s = input().strip()
counter = Counter(s)
# 出現回数が最大の文字を取得
most_common = counter.most_common(1)[0][0]
print(most_common)
問題3:リストの重複削除
整数列が与えられる。順序を保ちながら重複を削除して出力せよ。
入力:
5
1 2 2 3 1
出力:
1 2 3
解答コード
N = int(input())
nums = list(map(int, input().split()))
seen = set()
result = []
for n in nums:
if n not in seen:
seen.add(n)
result.append(n)
print(" ".join(map(str, result)))
問題4:区間和(累積和)
整数列と区間 [l, r] が与えられる。l 番目から r 番目までの総和を出力せよ。
入力:
5
1 2 3 4 5
2 4
出力:
9
解答コード
N = int(input())
nums = list(map(int, input().split()))
l, r = map(int, input().split())
# Pythonはスライスのインデックスに慣れるのも大事
print(sum(nums[l-1:r]))
問題5:集合の共通部分
2つの整数列が与えられる。両方に含まれる数を昇順で出力せよ。
入力:
3
1 3 5
4
2 3 4 5
出力:
3 5
解答コード
N = int(input())
A = list(map(int, input().split()))
M = int(input())
B = list(map(int, input().split()))
common = sorted(set(A) & set(B))
print(" ".join(map(str, common)))
以上になります。
非常に抽象的だと思いました。
単体では意味の分からない単語のようですが、意味さえ分かれば便利だなと思いました。
そして、マクロな処理が分かりやすく、階層的に読んでいけるのは脳のメモリを節約できて良いですね。