📌 백준 2277번 - ISBN
Bronze I · 브루트포스 / 구현 / 문자열
🔍 문제 요약
13자리 ISBN에서 훼손된 한 자리가 *로 표시되어 있다. *에 들어갈 올바른 숫자(0~9)를 찾아 출력하시오.
ISBN-13은 국제 표준 도서 번호로, 13자리 숫자로 구성됩니다. 마지막 자리는 체크기호로, 아래 공식을 만족해야 유효한 ISBN입니다.
ISBN이 abcdefghijklm 일 때,
a + 3b + c + 3d + e + 3f + g + 3h + i + 3j + k + 3l + m ≡ 0 (mod 10)
즉, 홀수 자리(1,3,5...) × 1, 짝수 자리(2,4,6...) × 3 을 모두 더한 값이 10의 배수여야 한다.
* 위치는 체크기호를 제외한 무작위 한 자리이며, 0~9 중 조건을 만족하는 숫자를 출력하면 됩니다.
입출력 예시
| 입력 | 출력 |
|---|---|
| 9788968322*73 | 2 |
🤔 어떻게 * 자리를 찾을까?
* 자리에 들어갈 수 있는 숫자는 0~9, 딱 10가지뿐이다. 모든 경우를 하나씩 대입해서 ISBN 공식을 만족하는 숫자를 찾으면 된다. → 브루트포스
🤔 가중합 계산은 어떻게?
인덱스 0부터 시작할 때, 짝수 인덱스(0,2,4...) × 1, 홀수 인덱스(1,3,5...) × 3을 적용해 합산한다.
조건식 j % 2 == 0 ? digit : digit * 3 한 줄로 깔끔하게 표현 가능하다.
🤔 * 를 숫자로 어떻게 바꾸지?
각 언어의 replace() 메서드를 사용해 * 를 0~9 숫자 문자열로 교체한 뒤 가중합을 계산한다.
단, Java·Python은 int를 바로 넣을 수 없어 문자열로 변환이 필요하고, JavaScript는 자동 변환된다.
📌 replace(target, replacement) 란?
문자열에서 target을 찾아 replacement로 교체한 새 문자열을 반환합니다.
원본 문자열은 변경되지 않으며, 이 문제에서는 "*"를 "0"~"9"로 하나씩 바꿔 후보 ISBN을 만드는 데 사용합니다.
| 언어 | 사용 방법 | 숫자 직접 전달 | 전체 교체 여부 |
|---|---|---|---|
| Java | str.replace("*", String.valueOf(i)) |
❌ 형변환 필요 | ✅ 전체 교체 |
| Python | str.replace("*", str(i)) |
❌ 형변환 필요 | ✅ 전체 교체 |
| JavaScript | str.replace("*", i) |
✅ 자동 변환 | ⚠️ 첫 번째만 |
⚠️ JavaScript replace() 주의사항
- 문자열을 대상으로
replace()를 사용하면 첫 번째 일치항만 교체됩니다. - 이 문제에서
*는 하나뿐이므로 문제없지만, 여러 개를 교체할 땐 정규식/\*/g를 사용해야 합니다. - 예:
"1*2*3".replace(/\*/g, "X")→"1X2X3"
- 손상된 ISBN 문자열 입력받기
- i = 0 ~ 9 순서로 반복
*를 i로 교체해 후보 ISBN 생성- 13자리를 순회하며 가중합 계산 (짝수 인덱스 × 1, 홀수 인덱스 × 3)
- 가중합 % 10 == 0 이면 → i 출력 후 종료
/**
* BOJ 2277 · ISBN
* 전략: 0~9 브루트포스 → ISBN-13 가중합 검증
*/
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String original = br.readLine(); // 손상된 ISBN 입력
for (int i = 0; i <= 9; i++) {
// '*'를 숫자 문자열로 교체하여 후보 ISBN 생성
// String.valueOf(i): int → String 변환 필수
String ISBN = original.replace("*", String.valueOf(i));
// ISBN-13 가중합 계산
// 짝수 인덱스(0,2,4...) × 1, 홀수 인덱스(1,3,5...) × 3
int sum = 0;
for (int j = 0; j < 13; j++) {
int digit = ISBN.charAt(j) - '0'; // 문자 → 숫자 변환
sum += (j % 2 == 0) ? digit : digit * 3;
}
// 가중합이 10의 배수 → 유효한 ISBN
if (sum % 10 == 0) {
System.out.println(i);
break;
}
}
}
}
# BOJ 2277 · ISBN
# 전략: 0~9 브루트포스 → ISBN-13 가중합 검증
original = input() # 손상된 ISBN 입력
for i in range(10):
# '*'를 숫자 문자열로 교체하여 후보 ISBN 생성
# str(i): int → str 변환 필수 (바로 넣으면 TypeError)
ISBN = original.replace("*", str(i))
# ISBN-13 가중합 계산 (제너레이터 표현식으로 간결하게)
# 짝수 인덱스 × 1, 홀수 인덱스 × 3
total = sum(
int(ISBN[j]) if j % 2 == 0 else int(ISBN[j]) * 3
for j in range(13)
)
# 가중합이 10의 배수 → 유효한 ISBN
if total % 10 == 0:
print(i)
break
// BOJ 2277 · ISBN
// 전략: 0~9 브루트포스 → ISBN-13 가중합 검증
const original = require('fs')
.readFileSync("/dev/stdin", "utf-8")
.trim(); // 손상된 ISBN 입력
for (let i = 0; i <= 9; i++) {
// '*'를 숫자로 교체 (JS는 숫자 자동 형변환)
// ⚠️ 기본 replace()는 첫 번째 일치항만 교체 → * 가 하나뿐이므로 OK
const ISBN = original.replace("*", i);
// ISBN-13 가중합 계산 (spread + reduce로 간결하게)
// 짝수 인덱스 × 1, 홀수 인덱스 × 3
const sum = [...ISBN].reduce((acc, char, j) => {
const digit = parseInt(char);
return acc + (j % 2 === 0 ? digit : digit * 3);
}, 0);
// 가중합이 10의 배수 → 유효한 ISBN
if (sum % 10 === 0) {
console.log(i);
break;
}
}
입력 9788968322*73에서 * = 2를 대입해 손으로 계산해 봅시다.
| 인덱스 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 숫자 | 9 | 7 | 8 | 8 | 9 | 6 | 8 | 3 | 2 | 2 | 2 | 7 | 3 |
| 가중치 | ×1 | ×3 | ×1 | ×3 | ×1 | ×3 | ×1 | ×3 | ×1 | ×3 | ×1 | ×3 | ×1 |
| 계산값 | 9 | 21 | 8 | 24 | 9 | 18 | 8 | 9 | 2 | 6 | 2 | 21 | 3 |
9 + 21 + 8 + 24 + 9 + 18 + 8 + 9 + 2 + 6 + 2 + 21 + 3 = 140
140 ÷ 10 = 14, 나머지 0 → ✅ 유효한 ISBN! 정답은 2
| 구분 | 복잡도 | 실제 연산 수 |
|---|---|---|
| 후보 ISBN 생성 | O(10) | 최대 10번 |
| 가중합 계산 1회 | O(13) | 13번 |
| 전체 | O(10 × 13) | 최대 130번 (사실상 O(1)) |
💬 입력이 고정 크기이므로 사실상 상수 시간
ISBN은 항상 13자리 고정이고, 탐색 범위도 0~9 딱 10가지입니다. 입력 크기에 무관하게 항상 최대 130번 연산으로 끝나므로 O(1)에 수렴합니다.
✔ 핵심 포인트
- 브루트포스: 경우의 수가 10가지뿐 → 모두 시도
- replace() 활용:
"*"를String.valueOf(i)/str(i)/i로 교체 - 가중합 조건:
j % 2 == 0 ? digit : digit * 3삼항 연산자로 간결하게 - Java·Python: int → String/str 형변환 필수 / JS: 자동 형변환
- JS replace() 주의: 기본은 첫 번째 일치만 교체, 전체 교체 시 정규식 +
g플래그 필요
'알고리즘 > 백준' 카테고리의 다른 글
| [BAEKJOON] 4134 다음 소수 (1) | 2026.02.25 |
|---|---|
| [BAEKJOON]2485 가로수 (2) | 2025.08.01 |
| [BAEKJOON] 2075 N번째 큰 수 (4) | 2025.07.29 |
| [BAEKJOON] 28278 스택 2 (1) | 2025.07.25 |
| [BAEKJOON]1735 분수 합 (1) | 2025.07.22 |