더하기 사이클, list와 숫자로 풀이
문제
0보다 크거나 같고, 99보다 작거나 같은 정수가 주어질 때 다음과 같은 연산을 할 수 있다. 먼저 주어진 수가 10보다 작다면 앞에 0을 붙여 두 자리 수로 만들고, 각 자리의 숫자를 더한다. 그 다음, 주어진 수의 가장 오른쪽 자리 수와 앞에서 구한 합의 가장 오른쪽 자리 수를 이어 붙이면 새로운 수를 만들 수 있다. 다음 예를 보자.
26부터 시작한다. 2+6 = 8이다. 새로운 수는 68이다. 6+8 = 14이다. 새로운 수는 84이다. 8+4 = 12이다. 새로운 수는 42이다. 4+2 = 6이다. 새로운 수는 26이다.
위의 예는 4번만에 원래 수로 돌아올 수 있다. 따라서 26의 사이클의 길이는 4이다.
N이 주어졌을 때, N의 사이클의 길이를 구하는 프로그램을 작성하시오.
예제 | |
입력 | 출력 |
26 | 4 |
55 | 3 |
1 | 60 |
이 문제를 보는 순간 재밌겠다는 생각이 들었습니다. 어떻게 풀어볼지 기대도 되고, 다양한 풀이가 나오니까요. 문제는 설명 그대로 긁어왔습니다.
생각대로 풀이는 다양했습니다. 먼저 제 코드입니다.
a = input()
n = list(a) # 처음 값
n.reverse() # 1.
m = list() # 다음 값
count = int()
while count < 100:
m = list(str(sum(list(map(int, n))))) # 2.
m.reverse() # 1.
n = list(n[0] + m[0]) # 3.
count += 1
if a == str(int("".join(n))): # 3.
print(count)
break
n.reverse()
- 저는 수가 10보다 작을 때, 문자열 타입으로 바꿔서 0을 더하거나 그렇지 않더라도 두 가지 경우(10보다 이하이거나 10보다 클 때)를 나눠서 코드를 짜야한다고 생각해서 .reverse() 함수를 사용했습니다. 그래서 n[0], m[0]을 쓰면 오른쪽 자리 수만 가져오게 되었습니다.
- 더하는 건 간단하게 한다고 sum()함수를 사용하려다보니 타입을 int로 바꾸고 슬라이스를 해야하니 str로 바꾸고 reverse()함수를 써야하니 list로 타입을 바꾸니 list(str(sum(list(map(int, n))))) 같은 괴상한 코드가 나왔습니다.
- 다음 값이랑 처음 값이랑 비교하는 내용은 str >> int >> str로 타입을 바꿔주었습니다. list를 합치기 위해 .join()함수를 썼고(str 타입이 됨), 처음 값의 오른쪽 자리 수(n[0])가 0일 경우가 있으므로 없애기 위해 int로 타입을 바꿔주었고, 입력받은 값은 기본이 str이므로 다시 바꿔주었습니다.
신나서 이것저것 넣다보니 코드 길이도 길고 시간도 오래 걸렸습니다. (264B, 72ms)
다른 분 코드도 가져와봤습니다.
N = int(input()) # 처음 값
n = -1 # 더한 값
t = 0
while n != N:
if n == -1: n = N
n = (n//10 + n%10)%10 + (n%10)*10 # 1.
t += 1
print(t)
- (n//10 + n%10)%10 + (n%10)*10 을 나눠서 보면..
- (n//10 + n%10) % 10 연산자 //는 나눗셈에서 몫만, 연산자 %는 나눗셈에서 나머지만 추출합니다. n//10 + n%10를 해주어 십의 자리와 일의 자리를 더합니다. 더한 값에서 필요한 건 일의 자리이므로 다시 %10을 해줍니다.
- (n%10) * 10 다음 값의 십의 자리는 처음 값에 일의 자리였습니다. 그래서 일의 자리를 추출한 다음(n%10) 십의 자리가 되게 *10을 해줍니다.
길이는 114B, 시간은 52ms가 나왔습니다.
저는 list를 이용했고, 다른 분은 계산식을 이용했습니다. 수학을 열심히 하지 않은 티가 여기서 나네요..
컴퓨터는 수학문제가 풀기 쉬운가 봅니다. 다음에 숫자가 나오는 문제는 이런 방식으로 풀어봐야겠습니다.
# 참고
백준 알고리즘 문제 1110 : https://www.acmicpc.net/problem/1110