박봉달의 개발생활
Today's Algoritm : 파이썬 알고리즘-12 (탐색)숫자만 추출 본문
파이썬 알고리즘에 대해서 정리해볼 예정이다. 기본부터 탄탄히 만들어가보려고 적어가는 과정.
알고리즘을 짜는데는 오래 걸리는데 막상 코드를 짜면 이렇게 짧은가 싶다.
문제 출처는 아래 벨로그에서!
1. 문제
문자와 숫자가 섞여있는 문자열이 주어지면 그 중 숫자만 추출하여 그 순서대로 자연수를 만
듭니다. 만들어진 자연수와 그 자연수의 약수 개수를 출력합니다.
만약 “t0e0a1c2h0er”에서 숫자만 추출하면 0, 0, 1, 2, 0이고 이것을 자연수를 만들면 120이
됩니다. 즉 첫 자리 0은 자연수화 할 때 무시합니다. 출력은 120를 출력하고, 다음 줄에 120
의 약수의 개수를 출력하면 됩니다.
추출하여 만들어지는 자연수는 100,000,000을 넘지 않습니다.
▣ 입력설명
첫 줄에 숫자가 섞인 문자열이 주어집니다. 문자열의 길이는 50을 넘지 않습니다.
▣ 출력설명
첫 줄에 자연수를 출력하고, 두 번째 줄에 약수의 개수를 출력합니다.
▣ 입력예제 1
g0en2Ts8eSoft
▣ 출력예제 1
28
6
2. 생각 과정
문자열을 받고 거기서 숫자만 출력하는 것이 관건인 문제가 되겠다. 그 이후에는 2부터 그 숫자까지의 약수의 개수를 출력하는 문제. 일단 간단히 문제를 파악해보자면 문자열을 받아 숫자인 것만 탐색하여 남기는 것이 1차적 목표이며, 그 숫자까지의 약수의 개수를 파악하여 출력하는 것이 2차적 목표가 되겠다.
그렇다면 문자열에서 숫자만 걸러내는 방법은 무엇이 있을까?
첫번째는 정규표현식을 사용하여 (re) 걸러내는 방법이다. re.findall() 을 사용하여 추출할 수 있고, 이는 리스트로 반환되어진다. 가장 정확하게 추출할 수 있는 방법이지만, 이는 리스트에서 다시 추출된 각 숫자를 다시 합쳐서 정수화시켜야하기에 과정이 길다고 생각되어 구글링을 더 해보았다.
두번째로 찾은 방법은 조금 더 간단하다.
https://hello-bryan.tistory.com/218
// 예시
str1 = "25 일 전"
days = int(''.join(list(filter(str.isdigit, str1))))
print(days)
# 25
이처럼 join과 filter를 사용하여 숫자인지 파악하고 숫자만을 반환하는 방법이다. 이는 리스트에서 바로 정수화를 시키는 과정을 포함하기 때문에 숫자가 바로 추출된다는 장점이 있지만, 마이너스 기호(-)가 표현될수 없다는 단점이 존재한다. 하지만 문제에서는 마이너스까지 요구하지 않기 때문에 더욱 빠른 방법을 가지고 문제를 해결해보려고 한다.
filter 함수에 대한 깊은 설명은 아래 링크에 설명되어 있다.https://wikidocs.net/22803
join 함수에 대한 깊은 설명은 아래 링크에 설명되어 있다. https://blockdmask.tistory.com/468
또 약수를 쉽게 구하는 방법은 무엇이 있을까? 약수는 목표의 수를 임의의 수로 나누었을 때 나머지가 생기지 않는, 한마디로 나눌 수 있는 수를 의미한다. 아래의 링크를 참고하여 문제를 해결해보면, 문자열에서 추출한 수를 for문을 가지고 반복문을 돌려서, 목표의 수를 임의의 수로 나누어 나머지가 0이 되면 count를 1 더해주는 코드를 짜주면 될 것 같다.
그렇다면 간단히 의사코드를 작성해보고 넘어가보도록 하자.
1. 문자열을 입력 받음
2. 문자열에서 숫자만을 걸러낸 문자열을 추출 -> 정수형으로 변환 (예를 들어 00120이라면 정수형으로 바꿀 시 120으로 무시됨)
3. 정수형으로 변환한 자연수를 출력하고
4. 그 자연수까지에 존재하는 약수를 구해 다음줄에 출력하기.
3. 내 코드
# filter를 사용하여 만든 코드
str1 = input()
nums = int(''.join(list(filter(str.isdigit, str1))))
count = 0
for i in range(1, nums + 1):
if nums % i == 0:
count += 1
print(nums, count, sep = '\n')
# 정규표현식을 사용하여 만든 코드
import re
str1 = input()
num_str = re.findall("\d+", str1)
nums = int(''.join(num_str))
count = 0
for i in range(1, nums + 1):
if nums % i == 0:
count += 1
print(nums, count, sep = '\n')
4. 풀이 코드
s=input()
res=0
for x in s:
if x.isdecimal():
res=res*10+int(x)
print(res)
cnt=0
for i in range(1, res+1):
if res%i==0:
cnt+=1
print(cnt)
5. 배운점
- 나는 문자열에서 숫자인 부분을 리스트로 추출해서 정수형으로 바꾸는 작업을 했는데, 아마 이게 메모리 소모가 더욱 커서 풀이 코드는 메모리 활용에 중점을 두고 짠 코드가 나온 것 같다. isdecimal() 메서드는 숫자 (0~9)까지 구할 수 있으며, 여기서 res = res*10+int(x)라고 나온 코드는 탐색을 할 때 그 숫자들이 차차 쌓이는(?) 개념으로 가야하기 때문에 2가 있는 상황에서 8이 나온다면 28이 되어야하기 때문에 10을 곱해주어 자릿수 자체를 올려준 것 같다.
- 10 이상의 수를 찾기 위해서는 isdigit()을 사용한다.
메모리 활용에 조금 더 중점을 두어 코드를 짜는 연습도 해봐야겠다!
'Projects > Algorithm' 카테고리의 다른 글
Today's Algoritm : 파이썬 알고리즘-11 (탐색)회문 문자열 검사 (1) | 2021.05.25 |
---|---|
Today's Algoritm : 파이썬 알고리즘-5 정다면체 (0) | 2021.04.19 |
Algoritm : Two Sum 두 정수의 합 구하기 / append(), 파이썬 화살표 -> 의미 (0) | 2021.03.20 |