오늘은 파이썬 심화프로그래밍 마지막날이었습니다.
주요한 진도는 다 진행이 되었기 때문에 여러 코딩테스트용 문제풀이를 진행했습니다.
문제풀이를 하면서 어떻게 해결할까 떠올려 보니 자연스럽게 복습이 됐습니다.
프로그래머스나 파이알고에 올라와 있는 코딩테스트 문제들이 생각보다 어려웠습니다.
좀 더 다양한 문제들을 접하고 많이 풀어보는 것이 복습에도 더 도움이 된다고 느꼈습니다.
문제들과 주요 코드들을 정리해보겠습니다.
이메일 주소 변경
# 문제: 주어진 문자열에서 모든 이메일 주소를 user@weniv.co.kr으로 변경하시오.
# 예시 입력: "저의 이메일 주소는 kim123@gmail.com입니다. 친구의 이메일 주소는 lee456@gmail.com입니다."
# 예시 출력: "저의 이메일 주소는 kim123@weniv.co.kr입니다. 친구의 이메일 주소는 lee456@weniv.co.kr입니다."
my_string = "저의 이메일 주소는 kim123@gmail.com입니다. 친구의 이메일 주소는 lee456@gmail.com입니다."
re.sub(r"@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}", "@weniv.co.kr", my_string)
이 문제의 핵심은 정규표현식입니다.
문제 자체에서 정규표현식을 알려줬지만 한번 분석을 해봤습니다.
예시 입력 문장에서 이메일 주소만 확인해서 @weniv.co.kr 으로 변경해야 합니다.@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}
여기서 []
는 택일 하라는 것입니다.
대문자A-Z, 소문자a-z, 숫자0-9, ., - 까지 허용합니다.[]
뒤에 +는 앞에 있는 문자가 1~n개 까지 올 수 있다는 의미입니다.\.
에서 \
는 .
을 표현하기 위해 이스케이프 문자표현입니다.
그리고 .
아래 있는 []
는 택일 이고, A-Z|a-z
는 대문자A-Z 또는 소문자a-z 가 올 수 있다는 의미입니다.
그 뒤에 {2,}
는 앞에 있는 문자가 2개 이상 이라는 의미입니다.
복잡하시만 가능한 이메일이 어떤 형태인지 정리한 정규표현식입니다.
모음을 제거한 문자열
# 입력 받은 숫자 리스트에서 짝수의 개수와 홀수의 개수를 반환하는 리스트를 출력
# 입력: [1, 2, 3, 4, 5], 출력: [2, 3]
# 입력: [1, 3, 5, 7] 출력: [0, 4]
data = [1, 2, 3, 4, 5]
def solution(data):
홀수 = [i % 2 != 0 for i in data]
짝수 = [i % 2 == 0 for i in data]
return [sum(짝수), sum(홀수)]
solution(data)
리스트를 for문 돌려서 2로 나눴을때 0이 아닌건 홀수 리스트에 넣고, 2로 나눴을때 0인건 짝수 리스트에 넣습니다.
그 값들을 sum해서 return하면 같은 결과를 얻을 수 있습니다.
# 입력 받은 숫자 리스트에서 짝수의 개수와 홀수의 개수를 반환하는 리스트를 출력
# 입력: [1, 2, 3, 4, 5], 출력: [2, 3]
# 입력: [1, 3, 5, 7] 출력: [0, 4]
data = [1, 2, 3, 4, 5]
def solution(num_list):
answer = [0, 0]
for i in num_list:
answer[i % 2] += 1
return answer
solution(data)
미리 return할 리스트 answer를 만들어 놓습니다.
매개변수로 받은 num_list를 for문으로 돌려서 answer[i % 2] += 1
구문을 실행합니다.
리스트를 i % 2
하면 결과가 0 아니면 1이 나와서 answer[0]
, answer[1]
만 됩니다.
거기에 값을 1씩 추가해주면 리스트에서 짝수의 개수와 홀수의 개수가 자연스럽게 정리되는 겁니다.
멋진 코드에요. 이렇게 깔끔하게 코딩을 할 수 있을까요?
키 큰 사람 출력
# 리스트와 기준 숫자를 입력을 받고, 리스트에서 기준 숫자보다 큰 값의 갯수를 출력
# 입 력 출력
# [149, 180, 192, 170] 167 3
# [180, 120, 140] 190 0
data = [149, 180, 192, 170]
n = 167
def solution(array, height):
answer = 0
for i in array:
if i > height:
answer += 1
return answer
solution(data, n)
기본적으로 생각할 수 있는 코드입니다.
for문을 입력받은 리스트만큼 반복하고, 각 값 하나하나가 기준키 보다 큰지 체크해서 큰 경우만 answer에 1씩
추가하는 코드입니다.
# 리스트와 기준 숫자를 입력을 받고, 리스트에서 기준 숫자보다 큰 값의 갯수를 출력
# 입 력 출력
# [149, 180, 192, 170] 167 3
# [180, 120, 140] 190 0
data = [149, 180, 192, 170]
n = 167
def solution(array, height):
return len(list(filter(lambda x: x > height, array)))
solution(data, n)
filter함수를 이용한 출력입니다. filter는 리스트에서 조건에 맞는 값들만 골라내는 함수입니다.
filter함수에는 len이 없습니다. 그 이유는 filter는 순회 돌기 전까지 실행이 되지 않는 함수입니다.
for와 같이 순회를 돌아야 그때서야 각 원소 별로 접근합니다.
그래서 list로 만들어주고, len을 통해 원소의 갯수를 return할 수 있습니다.
숨어있는 숫자의 출력
# 문자열에서 소문자, 대문자 제외한 한자리 자연수만 뽑아서 숫자 더해서 출력
data = "aAb1B2cC34oOp"
# data = "1a2b3c4d123"
def solution(my_string):
answer = 0
for i in my_string:
if i.isdigit():
answer += int(i)
return answer
solution(data)
문자열을 입력 받고, for문으로 순회해서 문자열 앞에서 하나씩 숫자인지 isdigit()
으로 판단하고, 숫자인 경우
int로 형변환해서 더해줍니다. 문자열 3
은 더한 값을 구할 수 없습니다.
r'hello\nworld' # \n은 이스케이프 문자입니다.
print('hello\nworld')
import re
def solution(my_string):
return sum(map(int, re.findall(r'[0-9]', my_string)))
solution("aAb1B2cC34oOp")
간단한 샘플입니다. "aAb1B2cC34oOp"
문자열을 매개변수로 보내고, 문자열에서 0~9까지 숫자를 찾고,
int형으로 형변환 하고, sum을 해주고 return하는 코드입니다.
그외 간단하게 여러 용어들을 설명해주셨습니다.
r은 raw 날것의 라는 뜻이 있습니다. 실무에서 자주 쓰는 용어이고, raw != low 는 다릅니다.
raw data를 전달해줘 라는 말은 가공하지 않은 순수데이터를 달라는 얘기입니다.print(r'hello\nworld')
여기서 \n
은 줄바꿈 이스케이프 문자입니다.
암호해독
# "dfjardstddetckdaccccdegk" 을 입력받고, 4를 입력받아 문자열에서 4칸 단위로 문자를 뽑아서 출력
# "pfqallllabwaoclk"을 입력 받고, 4를 입력 받아 문자열에서 2칸 단위로 문자를 뽑아서 출력
data = "dfjardstddetckdaccccdegk"
n = 4
# data = "pfqallllabwaoclk"
# n = 2
def solution(cipher, code):
count = 1
answer = ''
for i in cipher:
if count == code:
count = 0
answer += i
count += 1
return answer
solution(data, n)
입력 받은 문자열을 for문으로 순회를 돌고, if문에서 자리값이 code와 같은지 확인하고, 같은 경우 count를
0으로 초기화 하고, answer에 그 문자를 추가합니다. 0으로 초기화된 카운트는 if count == code
에서
4가 될때 까지 skip 합니다. 결국 count가 4일때 더해진 문자들을 더해서 출력하면 원하는 결과값을 얻습니다.
data = "dfjardstddetckdaccccdegk"
n = 4
# data = "pfqallllabwaoclk"
# n = 2
def solution(cipher, code):
return cipher[code-1::code]
solution(data, n)
문자열 슬라이싱을 이용하는 코드입니다. 슬라이싱의 자리 숫자들의 의미는 [start index: end index: step]
입니다.[::code]
했으면 문자열의 첫번째 자리부터 4자리 단위로 잘라서 return 했을 것입니다.code-1
해서 index 자리를 하나 앞으로 세팅해서 조정했습니다. 정말 멋진 코드입니다.
이렇게 간단하게 처리할 수 있습니다.
369게임
# 숫자를 입력 받고, 그 숫자에서 3, 6, 9의 갯수 출력
# 3을 입력 받으면 1
# 29423 을 입력 받으면 2
# data = 3
data = 29423
import re
def solution(order):
answer = 0
order = str(order)
answer = len((list(re.findall(r'[369]', order))))
return answer
solution(data)
입력받은 숫자에서 369가 들어간 문자를 뽑아서 리스트로 만들고, 그 리스트의 len을 출력하는 코드입니다.
핵심은 정규표현식입니다. findall()
은 원하는 걸 다 찾아내는 함수입니다.
정규표현식에서 []
는 택일입니다. [369]
는 숫자 369 가 들어간 것을 찾아냅니다.
# data = 3
data = 29423
import re
def solution(order):
order = str(order)
return order.count('3') + order.count('6') + order.count('9')
solution(data)
이렇게도 만들 수 있습니다. 입력받은 값을 문자열로 바꾸고, 문자열에서 order.count('3')
는 3이 있는 갯수를
리턴합니다. 그렇게 3, 6, 9 가 있는 갯수를 더해서 값을 출력합니다.
중복문자 제거
# 입력 받은 문자열에서 중복된 문자를 제거하고, 중복된 문자는 하나의 문자만 남긴 문자열을 출력
# data = "people"
# data = "We are the world"
data = "We are the world"
def solution(my_string):
answer = ''
for i in my_string:
if i not in answer:
answer += i
return answer
solution(data)
문자열을 입력 받고, 문자열 만큼 for문으로 순회를 도는데 문자열의 문자가 answer
에 있는지 없는지 확인하고,
없을 경우에 answer
에 그 문자를 추가합니다. answer
에 그 문자가 있다면 추가하지 않기 때문에
중복된 문자를 추가하는 것을 피할 수 있습니다.
data = "We are the world"
def solution(my_string):
return ''.join(dict.fromkeys(my_string)) # 딕셔너리는 키의 중복이 안된다는 점을 이용! dict는 이제 순서를 보장합니다!
solution(data)
딕셔너리는 키가 중복이 안된다는 점을 이용했습니다. 그리고 파이썬은 3.7 버전 이상부터는 딕셔너리가 순서를 보장합니다.dict.fromkeys(my_string)
는 my_string
의 각 요소를 키로 하는 새로운 딕셔너리를 생성합니다. 딕셔너리의 특성상 각 키는
고유해야 해서 중복된 요소는 하나만 유지됩니다.
"We are the world" 문자열은 {'W': None, 'e': None, ' ': None, 'a': None, 'r': None, ...}
형태의 딕셔너리를 생성합니다.
그리고, ''.join()
은 주어진 문자열을 사용해서 시퀀스의 요소들을 연결합니다. 여기서는 빈 문자열''
을 사용해서
딕셔너리의 키들을 연결합니다.
A로 B 만들기
# before 와 after 문자열이 주어질 때 before의 순서를 바꾸어 after를 만들 수 있으면 1을 출력, 아니면 0을 출력
# before 는 "olleh" after는 "hello" 일때 결과는 1
# before 는 "allpe" after는 "apple" 일때 결과는 0
def solution(before, after):
answer = 0
if len(before) != len(after):
return 0
if sorted(before) == sorted(after):
answer = 1
return answer
solution("olleh", "hello")
before 와 after의 문자열 길이가 다르면 0을 출력하고, before 와 after를 정렬했을때 결과가 같으면 1을 출력 하는 코드입니다.
import collections
def solution(before, after):
answer = 0
if collections.Counter(before) == collections.Counter(after):
answer = 1
return answer
solution("olleh", "hello")
collection을 이용한 코드입니다. 코드에서 collections.Counter(before)
와 collections.Counter(after)
부분은
각각 before 문자열과 after 문자열의 각 문자가 몇 번 나타나는지를 세어, 이를 Counter
객체로 return합니다.collections.Counter("olleh")
는 Counter({'o': 1, 'l': 2, 'e': 1, 'h': 1})
을 return합니다.collections.Counter("hello")
는 Counter({'h': 1, 'e': 1, 'l': 2, 'o': 1})
을 return합니다.Counter
객체는 문자의 등장 순서는 고려하지 않고, 단순히 문자의 개수만을 카운트 하게 됩니다.
그래서 결과적으로 두 문자열이 문자들의 종류와 개수는 같지만 배열 순서는 다를 수 있는지 확인합니다.
강의 내내 여러문제를 풀었습니다. 다양한 문제를 풀었지만 오늘은 일단 여기까지 정리합니다.
추후에 나머지 문제들은 추가적으로 더 정리해 보도록 하겠습니다. 4문제 정도 빠졌네요.^^
'오름캠프(23.12.28 ~ 24.4.18)' 카테고리의 다른 글
오름캠프 학습일지(2024/01/23) - 5주차 2일 (1) | 2024.01.23 |
---|---|
오름캠프 학습일지(2024/01/22) - 5주차 1일 (0) | 2024.01.22 |
오름캠프 학습일지(2024/01/18) - 4주차 4일 (0) | 2024.01.18 |
오름캠프 학습일지(2024/01/17) - 4주차 3일 (0) | 2024.01.17 |
오름캠프 학습일지(2024/01/16) - 4주차 2일 (0) | 2024.01.16 |