코딩 테스트/백준

[Python] 백준 2231 분해합

위시리 2024. 12. 29. 16:23

 

문제 분석

  • 분해합이 주어졌을 때 가장 작은 생성자를 구하라
  • 생성자가 없다면 0 출력

 

코드 설계

  • 입력 받은 분해합을 최대한 분해
  • 분해합이 3자리라고 할 때 가장 큰 분해합 - 생성자 = 27 (9+9+9)

 

정답 코드

실패.. 아이디어가 안떠오른다..

 

다른 사람 코드 1

n = int(input())

for i in range(1, n + 1):
    num = sum((map(int, str(i))))  # i의 각 자릿수를 더함
    num_sum = i + num  # 분해합 = 생성자 + 각 자릿수의 합

	# i가 작은 수부터 차례로 들어가므로 처음으로 분해합과 입력값이 같을 때 가장 작은 생성자를 가짐
    if num_sum == n:
        print(i)
        break
    if i == n:  # 생성자 i와 입력값이 같다는 것은 생성자가 없다는 의미
        print(0)

 

다른 사람 코드 2

n = int(input())
result = 0
for i in range(1, n+1):
    nums = list(map(int, str(i)))
    result = sum(nums) + i
    if result == n:
        print(i)
        break
    if i == n:
        print(0)
  • bruteforce
  • 입력과 빈 변수를 만들고
  • 분해합에 해당하는 숫자를 찾기 위해 1부터 입력값 까지의 모든 수를 더해서 찾는다.
  • 브루트 포스를 위한 for문을 작성한 뒤 i 값을 각 자릿수로 슬라이싱하여 리스트로 만드는 함수 검색
  • result에 sum(nums)와 i를 선언하여 i라는 수와 i의 각 자릿수의 합을 더한다.
  • i가 분해합을 찾지 못하고 n까지 가게 된다면 분해합이 없는 경우 → 0 출력

 

다른 사람 코드 3 - 2에서 좀 더 간단하게

https://afterdawncoding.tistory.com/60

N = int(input())
x = 0
for i in range(N):
    a = list(map(int, str(i)))
    if N == sum(a) + i:
        x = i
        break;
print(x)

** 해설

1. 1부터 입력한 값 N까지를 증가시키는 반복문을 돌리면서 각 숫자에 대한 분해합을 구한다.

정수의 각 자릿수를 리스트로 받기 위해서는 map()함수를 활용해야 한다.
문자열은 iterable에 해당하므로 1~입력받은 값(정수로 변환한) N까지의 값에 해당하는 i를 str으로 형변환하여 받고, 다시 map()함수로 각 자릿수 값을 int로 형변환한다.
이렇게하면 N에 245를 입력받았을 때 리스트 a에 [2, 4, 5]를 담을 수 있다.

N = int(input())
x = 0
for i in range(N):
    a = list(map(int, str(i)))
    if N == sum(a) + i:
        x = i
        break;
print(x)

2. 구한 분해합이 입력한 숫자와 같다면 해당 분해합 값은 입력한 숫자의 생성자이므로 반복문을 빠져나와 그 값을 출력한다.

sum함수는 리스트의 모든 원소를 더한 값을 반환한다. 여기에 i를 더하면 i의 분해합이 된다.
이 값이 입력한 값 N과 같다면 N의 생성자와 같은 값이므로 반복문을 탈출하여 그 값을 출력하도록 한다.

 

GPT 설명

for i in range(N):
    a = list(map(int, str(i)))

1. for i in range(N)

  • range(N):
    • 숫자 0부터 N-1까지의 정수 시퀀스를 생성합니다.
    • 예: N = 5일 경우 range(5)는 [0, 1, 2, 3, 4]와 같은 시퀀스를 만듭니다.
  • for i in range(N):
    • range(N)에서 생성된 숫자 하나하나를 i에 할당하면서 반복합니다.
    • 예: N = 5일 경우, i의 값은 순서대로 0, 1, 2, 3, 4가 됩니다.

2. str(i)

  • 숫자 i를 문자열로 변환합니다.
    • str() 함수는 숫자나 다른 자료형을 문자열로 바꾸는 역할을 합니다.
i = 123
str(i)  # 출력: "123" (문자열)
  • 변환 이유:
    • 숫자의 각 자릿수를 개별적으로 처리하려면, 문자열로 변환해야 합니다.

3. map(int, str(i))

  • str(i):
    • 숫자 i를 문자열로 변환한 값입니다.
    • 예: i = 123일 경우, str(i)는 "123"입니다.
  • map(int, str(i)):
    • str(i)는 문자열 "123"처럼 문자로 이루어진 시퀀스입니다.
    • map()은 각 문자에 대해 int 함수를 적용하여, 문자열을 다시 정수로 변환합니다.
i = 123
list(map(int, str(i)))  # 출력: [1, 2, 3]

동작 과정:

  1. str(i)가 반환한 문자열 "123"은 "1", "2", "3"이라는 개별 문자로 분리됩니다.
  2. map(int, ...)는 각 문자에 대해 int를 적용하여 정수로 변환합니다.
    • "1" → 1
    • "2" → 2
    • "3" → 3
  3. 결과는 [1, 2, 3]처럼 정수 리스트로 변환됩니다.

4. list(map(int, str(i)))

  • map(int, str(i))는 이터레이터 형태로 반환되므로, 이를 리스트로 변환하여 사용할 수 있게 합니다.
  • 결과:
    • i = 123일 경우:
      python
      코드 복사
      list(map(int, str(i))) # 출력: [1, 2, 3]

동작 흐름 전체

for i in range(N):  # 0부터 N-1까지 반복
    a = list(map(int, str(i)))  # i를 자릿수 별로 쪼개고 정수 리스트로 변환

예제: N = 5

  1. i = 0 → str(0) = "0" → list(map(int, str(0))) = [0]
  2. i = 1 → str(1) = "1" → list(map(int, str(1))) = [1]
  3. i = 2 → str(2) = "2" → list(map(int, str(2))) = [2]
  4. i = 3 → str(3) = "3" → list(map(int, str(3))) = [3]
  5. i = 4 → str(4) = "4" → list(map(int, str(4))) = [4]

요약

  • str(i): 숫자 i를 문자열로 변환.
  • map(int, str(i)): 문자열을 구성하는 각 문자를 정수로 변환.
  • list(map(int, str(i))): 변환된 결과를 리스트로 반환.

이 부분은 숫자를 자릿수 단위로 분해하여 정수 리스트로 변환하는 작업입니다

 

 

2회차 - 25.02.18

문제 분석

  • 어떤 자연수 N
  • 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미
  • M ( 생성자 ) - N ( 분해합 )

 

코드 설계

  • 입력(n)을 받고, 1~n 반복하면서(i) 만약 현재 i와 i의 각 자리수의 합이 n과 같으면 break
  • 끝까지 탐색했는데 없다면 0 출력

 

정답 코드

import sys
input = sys.stdin.readline

n = int(input())

for i in range(1, n+1) :
    num = list(str(i)) # 각 자리수 추출 -> 문자열 -> list
    # 각 자리가 str인 list의 값을 int로 바꿔서 합을 구하려고 한다.
    num_sum = sum(map(int, num))

    if n == (i+num_sum) :
        print(i)
        exit(0)

print(0)