この記事では「電脳少女プログラミング2088 ─壊レタ君を再構築─」のBランク問題「一番通りの繁華街」の解答コードをResultとChatGPTを使ってリファクタリングしていきます。
方針
- 縄張りの形状は正方形なので、縄張りの座標リストから組み合わせをして、絶対値分下に同じx座標のアジトがあるか判定する。
- 以下の順で処理:
- 標準入力からグリッドのサイズ
nを取得 - 標準入力からアジトの座標リスト
aを取得 - 縄張りの数
ansを作成 - 同じy座標の建物をリストから2つ抽出
- 組み合わせには
itertools.combinations()を使用
- 組み合わせには
- 抽出した建物の距離
d分離れたy座標に建物があるか判定し、あればansに+1 - 標準出力に
ansを出力
- 標準入力からグリッドのサイズ
import itertools
n = int(input())
a = []
for i in range(n):
t = {i for i, x in enumerate(list(input())) if x == '.'}
a.append(t)
ans = 0
for i in range(n):
for x1, x2 in itertools.combinations(a[i], 2):
d = abs(x1 - x2)
if i + d >= n: continue
if {x1, x2} <= a[i+d]:
ans += 1
print(ans)
Reference: enumerate() | list() | abs() | combinations() | list
改善
ChatGPTを使って可読性や効率を意識してみる:
import itertools
n = int(input())
pos = [{i for i, x in enumerate(input()) if x == '.'} for _ in range(n)]
num_territories = sum(
1
for i in range(n-1)
for x1, x2 in itertools.combinations(pos[i], 2)
if i + (distance := abs(x1 - x2)) < n and {x1, x2} <= pos[i + distance]
)
print(num_territories)
改善点:
- ループ最後は正方形が成立しないので
range()をnからn-1にした - リスト内包表記を使用して
posを1行にまとめた - 必要のない
list()の削除 - 変数名の最適化
-
a→pos -
ans→num_territories -
length→distance
-
- セイウチ演算子(
:=)を使用し、再計算する無駄を省いた - リファクタリング前は
ansにインクリメントしていく形式だったが、sum()を使用することでカウント処理が簡潔になった。
終わりに
itertools 便利なので、適切なタイミングで使えるようにしたい。