この記事では「電脳少女プログラミング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 便利なので、適切なタイミングで使えるようにしたい。