自動添字ガチャ(Python版)
概要
マーカーを付けた箇所それぞれで -1, 0, 1 の 3 通りを自動で試し、望む結果が得られたものを出力してくれます。コードは全部 Gemini 3 が書いてくれました。
例題
アルゴリズムと数学 演習問題集 038 - How Many Guests?
解法
累積和の練習問題のようです。うろ覚えで書いてみたところ以下のようなコードになりました:
code:solution(old).py
n, q = map(int, input().split())
a = list(map(int, input().split()))
acc = 0 * n
for i in range(n):
acci + 1 = acci + ai
for j in range(q):
l, r = map(int, input().split())
print(accr - accl)
サンプルを試すと IndexError: list assignment index out of range が出るので、どうやら添字周りでミスったようです。
そこで、solution.py のズレが怪しい箇所に [[0]], [[1]], ... などと書いていき、サンプルを in01.txt, out01.txt に保存し、gacha.py を実行します:
code:solution.py
n, q = map(int, input().split())
a = list(map(int, input().split()))
acc = 0 * (n + 0)
for i in range(n + 1):
acci + 1 = acci + a[i + 2]
for j in range(q):
l, r = map(int, input().split())
print(acc[r + 3] - acc[l + 4])
code:in01.txt
10 5
8 6 9 1 2 1 10 100 1000 10000
2 3
1 4
3 9
6 8
1 10
code:out01.txt
15
24
1123
111
11137
code:gacha.py
import itertools
import subprocess
import re
import os
import glob
# --- 設定 ---
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TARGET_PY = os.path.join(BASE_DIR, "solution.py")
TEMP_PY = os.path.join(BASE_DIR, "_exec_temp.py")
def get_test_cases():
"""in*.txt とそれに対応する out*.txt のペアを取得する"""
search_path = os.path.join(BASE_DIR, "in*.txt")
input_files = sorted(glob.glob(search_path))
print(input_files)
cases = []
for in_file in input_files:
# 1. パスを「ディレクトリ」と「ファイル名」に分ける
# 例: "C:/path/to/in01.txt" -> ("C:/path/to", "in01.txt")
directory, filename = os.path.split(in_file)
# 2. ファイル名の先頭の "in" を "out" に置換する (1回だけ)
if filename.startswith("in"):
out_filename = "out" + filename2:
else:
# 万が一 "in" で始まらないファイルが混ざった場合の安全策
continue
# 3. ディレクトリ名と新しいファイル名を結合してフルパスを作る
out_file = os.path.join(directory, out_filename)
if os.path.exists(out_file):
with open(in_file, "r", encoding="utf-8") as f_in:
stdin_data = f_in.read()
# --- 追加: 入力が空(空白のみ含む)だったら読み込みを中断 ---
if not stdin_data.strip():
print(f" - Empty input detected in {in_file}. Stopping test case load.")
break
# ------------------------------------------------------
with open(out_file, "r", encoding="utf-8") as f_out:
# 比較のために前後の空白を削除
expected_stdout = f_out.read().strip()
cases.append((in_file, stdin_data, expected_stdout))
return cases
def run_with_input(code, input_str):
with open(TEMP_PY, "w", encoding="utf-8") as f:
f.write(code)
try:
res = subprocess.run(
"python", TEMP_PY,
input=input_str,
capture_output=True,
text=True,
errors="ignore",
timeout=2
)
if res.returncode != 0:
return None
return res.stdout.strip()
except Exception:
return None
def main():
if not os.path.exists(TARGET_PY):
print(f"Error: {TARGET_PY} not found.")
return
test_cases = get_test_cases()
if not test_cases:
print("No matching test cases found.")
return
print(f"Loaded {len(test_cases)} test cases.")
for name, _, _ in test_cases:
print(f" - Using: {name}")
with open(TARGET_PY, "r", encoding="utf-8") as f:
template = f.read()
marker_ids = sorted(list(set(re.findall(r"\[\(\d+)\\]", template))))
num_vars = len(marker_ids)
if num_vars == 0:
print("\n! No markers n found. Please mark offsets in solution.py.")
return
print(f"\nStarting Gacha: 3^{num_vars} = {3**num_vars} patterns...")
found_count = 0
for pattern in itertools.product(-1, 0, 1, repeat=num_vars):
current_code = template
for i, val in enumerate(pattern):
current_code = current_code.replace(f"{i}", str(val))
all_pass = True
for name, stdin_data, expected in test_cases:
actual = run_with_input(current_code, stdin_data)
if actual != expected:
all_pass = False
break
if all_pass:
found_count += 1
print(f"\n✅ SUCCESS Solution #{found_count} | Pattern: {pattern}")
print("-" * 40)
print(current_code)
print("-" * 40)
if found_count == 0:
print("\n❌ No combinations satisfied the selected test cases.")
if os.path.exists(TEMP_PY):
os.remove(TEMP_PY)
if __name__ == "__main__":
main()
すると次のような出力が得られます:
code:output.txt
Loaded 1 test cases (Limit: 1).
- Using: in01.txt
Starting Gacha: 3^5 = 243 patterns...
✅ SUCCESS Solution #1 | Pattern: (1, 0, 0, 0, -1)
----------------------------------------
n, q = map(int, input().split())
a = list(map(int, input().split()))
acc = 0 * (n + 1)
for i in range(n + 0):
acci + 1 = acci + ai + 0
for j in range(q):
l, r = map(int, input().split())
print(accr + 0 - accl + -1)
----------------------------------------
後はこのコードをそのまま提出すれば AC が得られます。
提出
Python (222 ms)
他の使用例
競技プログラミングの鉄則 演習問題集 A58 - RMQ (Range Maximum Queries)
ac-library-python も利用できます。
サンプルが弱いので、
code:in02.txt
1 2
1 1 12345
2 1 2
code:out02.txt
12345
などの際どいケースを追加してからガチャを引きましょう。
元ポスト
#邪道テク