솔브닥 스트릭을 연명하기 위해 문자열 브론즈 문제를 풀다가 고안한 토글 코드를 살펴보고 활용법을 이야기해 보겠다.
신용카드 판별
| 시간 제한 | 메모리 제한 |
|---|---|
| 1 초 | 128 MB |
문제
신용카드는 총 16자리의 숫자로 구성되어 있다. 언뜻 보기에는 무작위로 된 숫자로 구성되어 있는 것 같이 보이지만 그 속에는 하나의 수학적 비밀이 숨겨져 있다. 그중 하나가 카드 번호가 유효 한지 유효하지 않은 지 검사하는 Luhn 공식이다. 그 공식은 다음과 같다.
1. 신용카드의 16자리 숫자에서 맨 우측 수부터 세어 홀수 번째 수는 그대로 두고, 짝수 번째 수를 2배로 만든다.
2. 2배로 만든 짝수 번째 수가 10 이상인 경우, 각 자리의 숫자를 더하고 그 수로 대체한다.
3. 이와 같이 얻은 모든 자리의 수를 더한다.
4. 그 합이 10으로 나뉘면 "정당한 번호"(유효)이고 그렇지 않으면 "부당한 번호"(유효하지 않음)로 판정된다.
다음 공식을 이용해 주어진 신용카드의 번호가 유효한지, 유효하지 않은 지 판단해라.
입력
첫째 줄에 테스트 케이스의 수 T(1 ≤ T ≤ 1000)이 주어진다.
그 다음 줄부터 테스트 케이스에 해당하는 신용카드 번호가 주어진다.
출력
신용카드의 번호가 유효하면 "T", 유효하지 않으면 "F"를 한 줄 씩 출력한다.
예제 입력/출력
예제 입력 1
3
2720992711828767
3444063910462763
6011733895106094
예제 출력 1
T
F
T
출처
University > 중앙대학교 > 중앙대학교 프로그래밍 경진대회 (CPC) > 2017 중앙대학교 프로그래밍 경진대회 (CPC) A번
우선 내가 이 아이디어를 떠올리기 전의 방법으로 그냥 짠다면 이렇게 짰을 것이다.
n,*s=open(0,'rb').read().split()
for c in map(bytearray,s):
tot=0
count=1
while c:
x=c.pop()-48
tot+=sum(divmod(x*(2-(count&1)),10))
count+=1
print('F' if tot%10 else 'T')
2-(count&1)를 이용해서 현재 몇 번째 자리수인지 세면서 홀짝여부로 가중치를 조절한다.
좀 더 가독성 있는 코드를 제시하자면
# stdin에서 입력을 읽고 바이트 배열 리스트로 분할
n, *s = open(0, 'rb').read().split()
# 각 바이트 배열 처리
for c in map(bytearray, s):
tot = 0
count = 1
# 바이트 배열의 각 숫자를 오른쪽에서 왼쪽으로 처리
while c:
# 바이트를 정수로 변환 ('0'의 ASCII 값 빼기)
x = c.pop() - 48
# Luhn 알고리즘 가중치 적용 (위치가 홀수면 2를 곱함)
if count % 2 == 1: # 홀수 위치
weight = 2
else: # 짝수 위치
weight = 1
weighted_value = x * weight
# 가중치가 적용된 값의 자릿수 합계 (10 이상일 경우 divmod 사용)
digits_sum = sum(divmod(weighted_value, 10))
tot += digits_sum
count += 1
# 합계가 10으로 나누어 떨어지면 'T', 아니면 'F' 출력
print('F' if tot % 10 else 'T')
이 경우 별도의 카운트 변수를 사용해야 하고 홀 짝 판별을 하게 된다.
그런데 아래와 같은 수식을 쓰면 홀수번째와 짝수번째에 번갈아가면서 mul변수의 값을 1과 2로 만들 수 있다.
n,*s=open(0,'rb').read().split()
mul=2
for c in map(bytearray,s):
tot=0
while c:
mul=3-mul
x=c.pop()-48
tot+=sum(divmod(x*mul,10))
print('F' if tot%10 else 'T')
관찰



x의 값은 x초기값과 n의 차이 사이에서 토글된다. n이x보다 작아도 성립한다.
0,1 토글은 xor로도 할 수 있다.
활용
r = bytearray()
for i in range(10):
if i % 2 == 0:
r.append(ord('B')) # 짝수 번째는 'B'
else:
r.append(ord('W')) # 홀수 번째는 'W'
open(1,'wb').write(r)
위 코드를 아래와 같이 만들 수 있다.
r = bytearray()
c = 66
for i in range(10):
c = 153 - c
r.append(c) # 짝수 번째는 'B'
open(1,'wb').write(r)
결과는 똑같다.
BWBWBWBWBW
상태 반전도 가능하다.
import os
r = list(map(bytearray,(b'WBBBBBBBBW' for _ in range(10))))
os.write(1,b'before\n\n')
for c in r:
os.write(1,c+b'\n')
for i in range(10):
for j in range(10):
r[i][j] = 153 - r[i][j]
os.write(1,b'\nafter\n\n')
for c in r:
os.write(1,c+b'\n')
before
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
WBBBBBBBBW
after
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB
BWWWWWWWWB

https://www.acmicpc.net/problem/12813
def s():
res=[bytearray() for _ in range(5)]
for a,b in zip(*open(0,'rb').read().split()):
res[0].append(a&b)
res[1].append(a|b)
res[2].append((a^b)+48)
res[3].append(97-a)
res[4].append(97-b)
open(1,'wb').write(b'\n'.join(res))
s()'Tech > Coding' 카테고리의 다른 글
| 29768-펠린드롬 이름 (0) | 2025.05.03 |
|---|---|
| 출력 버퍼 (0) | 2025.04.29 |
| 위상 정렬 (Topological Sort) (0) | 2025.04.19 |
| 파이썬 heapq.heapreplace 동작 원리 (0) | 2025.04.12 |
| 파이썬 heapq : 힙큐 사용법 정리 (0) | 2025.04.11 |