GrepBoard/매뉴얼
84 편 ·

틀린 문제를 원인별 오답 표로 정리하기

·고침 ·claude-sonnet-5-5 (ChatGPT 는 돌리지 않음) · 2026-10-20 실행·6 단계

모의고사에서 틀린 8문제를 계산 실수·개념 부족·조건 누락으로 나누고 다음 규칙까지 받는 방법입니다. 인용이 풀이 줄에 있는지, 건수가 8 인지 스크립트로 대조합니다.

틀린 문제 8개를 AI 에 통째로 붙이면 문제부터 다시 풉니다. 풀이를 잘못하면 원인도 잘못 짚습니다. 정답과 학생 답, 학생 풀이 한 줄을 같이 주고 원인 분류만 시킵니다.

[1] 입력 표를 만듭니다. 문제·정답·학생 답·학생 풀이 한 줄입니다. 수학 문제는 모두 가상입니다.

data.ko.txt
번호 | 문제 | 정답 | 학생 답 | 학생 풀이1 | 3x − 5 = 10 의 해 | x=5 | x=5/3 | 3x=10−5, x=5/32 | (−3)² − 2×(−4) 의 값 | 17 | −1 | (−3)²=−9, −9+8=−13 | 가로 8cm, 세로 5cm 직사각형의 둘레 | 26cm | 40cm | 8×5=404 | y=2x+3 에서 x=−2 일 때 y | −1 | 7 | 2×(−2)=4, 4+3=75 | 연속하는 세 자연수의 합이 51 일 때 가장 큰 수 | 18 | 17 | 51÷3=176 | 12 와 18 의 최소공배수 | 36 | 6 | 12=2×2×3, 18=2×3×3, 공통 2×3=67 | 2(x+3) − (x−4) 를 간단히 | x+10 | x+2 | 2x+6−x−4=x+28 | 시속 4km 로 30분 걸은 거리 | 2km | 120km | 4×30=120

[2] 프롬프트를 만듭니다. 분류 이름 3개에 각각 뜻을 한 줄씩 붙이고, 예시 행 하나를 넣습니다(입력 자료에 없는 문제). 원하는 분류를 입력·출력 예시로 보여 주고 참고 자료를 프롬프트 안에 직접 넣으면 모델이 틀을 따라간다는 것이 OpenAI 의 프롬프트 엔지니어링 안내에 있는 원칙입니다. 「풀이 인용」 칸은 5단계 대조용입니다.

head.ko.txt
Below is a table of the problems a student got wrong on a practice test. Classify why each one was missed. Rules:- Take the correct answer and the student's answer as given. Do not solve the problems again.- Choose exactly one cause per problem from: 계산 실수 / 개념 부족 / 조건 누락.  - 계산 실수: the method is right, but the arithmetic or a sign slipped.  - 개념 부족: the student used a wrong rule or mixed up two concepts.  - 조건 누락: the student did not answer what was asked (misread the question, ignored a unit or a condition).- In "풀이 인용", copy a piece of the student's working line character for character. It must be a substring of that line.- "다음 규칙" is one short instruction the student can follow next time, specific to this problem. Never leave it empty.- Output two Markdown tables and nothing else.  Table 1 columns: 번호 | 원인 | 풀이 인용 | 다음 규칙  Table 2 columns: 원인 | 건수- Write in Korean. Example (not part of the data below):| 번호 | 원인 | 풀이 인용 | 다음 규칙 || 0 | 계산 실수 | 7×6=48 | 곱셈은 끝나면 거꾸로 나눠 확인한다 | <wrong_answers>

[3] 프롬프트에 입력 표와 닫는 태그를 붙여 실행합니다. --tools "" 는 내장 도구를, --strict-mcp-config 는 연결해 둔 MCP 도구를 끄고, --setting-sources "" 는 내 설정·지침 파일(CLAUDE.md 등)을 읽지 않게 합니다.

console
$ (cat head.ko.txt data.ko.txt; echo "</wrong_answers>") > prompt.ko.txt$ claude -p --model claude-sonnet-5-5 --max-turns 1 --tools "" --setting-sources "" --strict-mcp-config < prompt.ko.txt > out.ko.1.txt$ cat out.ko.1.txt| 번호 | 원인 | 풀이 인용 | 다음 규칙 ||---|---|---|---|| 1 | 계산 실수 | 3x=10−5 | −5를 옮길 때는 부호가 바뀌어 +5가 되므로, 우변을 10+5로 쓴다. || 2 | 개념 부족 | (−3)²=−9 | 괄호 안의 음수를 제곱하면 (−3)×(−3)=+9이니, 괄호가 있으면 부호까지 함께 제곱한다. || 3 | 개념 부족 | 8×5=40 | 직사각형 둘레는 (가로+세로)×2이고, 가로×세로는 넓이라고 구분해서 쓴다. || 4 | 계산 실수 | 2×(−2)=4 | 음수를 곱하면 먼저 부호를 정하고, 2×(−2)=−4처럼 쓴다. || 5 | 조건 누락 | 51÷3=17 | 17은 가운데 수이므로, 구한 뒤에 문제가 묻는 "가장 큰 수"인 17+1=18까지 답한다. || 6 | 개념 부족 | 공통 2×3=6 | 최소공배수는 공통 소인수와 남은 소인수를 모두 곱하고(2×2×3×3), 공통 부분만 곱하면 최대공약수라고 구분한다. || 7 | 계산 실수 | 2x+6−x−4 | −(x−4)처럼 괄호 앞이 −이면 괄호 안 모든 항의 부호를 바꿔 −x+4로 쓴다. || 8 | 조건 누락 | 4×30=120 | 시속(km/시간)에 분을 곱하기 전에 30분을 1/2시간으로 바꾸고, 4×1/2=2km로 계산한다. | | 원인 | 건수 ||---|---|| 계산 실수 | 3 || 개념 부족 | 3 || 조건 누락 | 2 |

한 번 더 돌린 out.ko.2.txt 는 1번을 「개념 부족」으로 분류해 건수가 2·4·2 로 달랐습니다. 나머지 7행은 원인이 같았습니다. 다음 규칙은 말투만 달랐습니다.

[4] 대조 스크립트를 만듭니다. 세 가지를 봅니다. 「풀이 인용」이 그 번호의 풀이 줄 안에 글자 그대로 있는지, 「다음 규칙」이 비어 있지 않은지, 두 번째 표의 건수 합이 입력 행 수(8)와 첫 번째 표의 원인별 개수에 맞는지. 인용을 찾는 방식은 요약 인용 검증 과 같습니다.

check.py
#!/usr/bin/env python3"""usage: check.py data.txt out.txt"""import syswork = {l.split(" | ")[0]: l for l in open(sys.argv[1], encoding="utf-8").read().splitlines()[1:]}tabs, cur = [], []for l in open(sys.argv[2], encoding="utf-8").read().splitlines() + [""]:    if l.startswith("|"): cur.append([c.strip() for c in l.strip("|").split("|")])    elif cur: tabs.append([r for r in cur[1:] if not set("".join(r)) <= set("-: ")]); cur = []t1, t2 = tabs[:2]bad = 0for n, cause, quote, rule in t1:    ok = quote in work.get(n, "").split(" | ")[-1] and rule != ""    bad += not ok    print(("OK  " if ok else "BAD ") + f"{n}: {cause} / {quote}")cnt = {c: sum(r[1] == c for r in t1) for c, _ in t2}total = sum(int(k) for _, k in t2)print(f"rows {len(t1)}/{len(work)}, table2 total {total}, matches table1: {cnt == {c: int(k) for c, k in t2}}, bad {bad}")sys.exit(0 if len(t1) == len(work) == total and cnt == {c: int(k) for c, k in t2} and not bad else 1)

[5] 돌립니다. 두 번 모두 종료 코드 0 입니다. 원인이 달라도 형식은 맞으니 스크립트는 둘 다 통과시킵니다.

console
$ python3 -I check.py data.ko.txt out.ko.1.txt | tail -1; echo "exit ${PIPESTATUS[0]}"rows 8/8, table2 total 8, matches table1: True, bad 0exit 0

실패 출력은 4행 인용을 손으로 2×(−2)=−4 로 바꾼 out-bad.ko.txt 로 낸 것입니다(모델이 만든 오류가 아닙니다).

console
$ python3 -I check.py data.ko.txt out-bad.ko.txt | grep -v '^OK'; echo "exit ${PIPESTATUS[0]}"BAD 4: 계산 실수 / 2×(−2)=−4rows 8/8, table2 total 8, matches table1: True, bad 1exit 1

[6] 스크립트가 통과해도 분류가 맞다는 뜻은 아닙니다. 3번을 보세요. 학생은 둘레를 묻는데 넓이를 구했으니 「조건 누락」이라고 보는 쪽이 자연스럽습니다. 모델은 두 번 모두 「개념 부족」이라고 했습니다. 정의 두 줄이 겹쳐서 생기는 일입니다.

규칙 한 줄을 더했습니다.

text
- If the student computed a different quantity from the one asked (for example area instead of perimeter), choose 조건 누락, not 개념 부족.

다시 두 번 돌리자 3번은 두 번 모두 「조건 누락」이 됐습니다. 그런데 다른 행은 실행마다 움직였습니다.

번호처음 두 번규칙 추가 후 1회규칙 추가 후 2회
1계산 실수 · 개념 부족계산 실수개념 부족
3개념 부족 · 개념 부족조건 누락조건 누락
6개념 부족 · 개념 부족개념 부족개념 부족
7계산 실수 · 계산 실수계산 실수개념 부족

건수 표는 처음 두 번이 3·3·2 와 2·4·2, 규칙 추가 후 1회가 3·2·3, 2회가 1·4·3(계산 실수·개념 부족·조건 누락 순)이었고 어느 쪽도 합계는 8 이었습니다. 합계가 맞아도 칸 안의 내용이 바뀐 것입니다. 1번은 규칙을 더하기 전부터 실행마다 갈렸습니다.

그래서 사람이 할 일은 둘입니다. 같은 프롬프트를 두 번 돌려 원인이 다르게 나온 행부터 학생 풀이 줄과 정답을 직접 봅니다. 두 번 같게 나온 행도 풀이 줄·원인 이름·다음 규칙은 훑어야 합니다. 같은 모델이 자기와 일치한다고 맞는 것은 아닙니다(3번은 두 번 같은 이름이 나왔는데도 규칙을 더해야 했습니다). 그리고 「다음 규칙」 칸을 학생이 실제로 따라 할 수 있는 문장으로 고칩니다(「주의하자」 같은 말은 규칙이 아닙니다).

#wrong-answers#error-analysis#study#prompt