파이썬

CodeKata-2

content0474 2024. 11. 15. 16:02

27. 핸드폰 번호 가리

프로그래머스 모바일은 개인정보 보호를 위해 고지서를 보낼 때 고객들의 전화번호의 일부를 가립니다.
전화번호가 문자열 phone_number로 주어졌을 때, 전화번호의 뒷 4자리를 제외한 나머지 숫자를 전부 *으로 가린 문자열을 리턴하는 함수, solution을 완성해주세요.

def solution(number):
    masking=re.sub(r"\d","*",number,count=len(number)-4)
    return masking

re.sub(정규식표현, "대체할문자", 참조할 원본, count=앞에서부터 몇 번째까지 바꿀지)

\d는 0-9까지의 숫자를 의미하는 정규식 패턴

 

28. 없는 숫자 더하기

0부터 9까지의 숫자 중 일부가 들어있는 정수 배열 numbers가 매개변수로 주어집니다. numbers에서 찾을 수 없는 0부터 9까지의 숫자를 모두 찾아 더한 수를 return 하도록 solution 함수를 완성해주세요.

def solution(numbers):
    full_numbers=set(range(10))
    numbers=set(numbers)
    missing_numbers=full_numbers.difference(numbers)
    return sum(missing_numbers)

집합1.difference(집합2) ->집합1에서 집합2에 있는 요소를 제거하고 남은 요소만 반환

조건 중 모든 원소가 서로 다르다고 했으므로 set을 사용해 집합으로 만들면 비교적 쉽게 해결가능

또한 0부터 9까지의 숫자 집합을 만들 때 직접 입력하지 않고 set(range(10))으로 만들 수 있다.

 

29. 제일 작은 수 제거하기

정수를 저장한 배열, arr 에서 가장 작은 수를 제거한 배열을 리턴하는 함수, solution을 완성해주세요. 단, 리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴하세요. 예를들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴 하고, [10]면 [-1]을 리턴 합니다.

def solution(arr):
    arr.remove(min(arr))
    if not arr:
        return [-1]
    return arr

remove()만 알고 있으면 쉬운 문제 

remove는 특정값을 제거하는데, 여러 번 포함된 값이라도 제일 첫번째 값만 제거한다.

if not arr 은 arr이 빈 리스트일 때 True가 되어 [-1]을 반환

 

33. 약수의 개수와 덧셈

두 정수 left right가 매개변수로 주어집니다. left부터 right까지의 모든 수들 중에서, 약수의 개수가 짝수인 수는 더하고, 약수의 개수가 홀수인 수는 뺀 수를 return 하도록 solution 함수를 완성해주세요.

 

-> 약수가 짝수이다 = 정수의 제곱수가 아님 / 약수가 홀수이다 = 정수의 제곱수

 

33-1. int()

def solution(left, right):
    converted=[num if not num**0.5==int(num**0.5) else -num for num in range(left,right+1)]
    return sum(converted)

num**0.5 의 결과는 늘 float로 반환되므로 (ex 16**0.5=4.0)

isinstance(int, num**0.5)는 항상 False이다.

그래서 num**0.5==int( num**0.5 ) 로 정수의 제곱근인지를 판별한다.

 

33-2. math.isqrt()

def solution(left, right):
    converted=[num if not math.isqrt(num)**2==num else -num for num in range(left,right+1)]
    return sum(converted)

math.isqrt(n)은 n의 제곱근을 내림해서 정수로 반환한다. (ex. math.isqrt(21)=4)

따라서 math.isqrt(n)의 결과를 제곱한것과 n이 같으면 n은 정수의 제곱수이다.

 

36. 문자열 다루기 기본

문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, solution을 완성하세요. 예를 들어 s가 "a234"이면 False를 리턴하고 "1234"라면 True를 리턴하면 됩니다.

 

36-1. try-except

def solution(s):
    if len(s)==4 or len(s)==6:
        try:
            listed=list(s)
            list(map(int, listed))
            return True
        except ValueError:
            return False
    else:
        return False

if문으로 우선 길이를 검사하고, if문 통과 후 try-except 구문을 실행시킨다.

try-except는 오류, 예외처리를 할 때 유용하다

try에서 list내의 항목들을 int로 변환시키는데, 만약 list에 문자가 포함되어 에러가 나면 False 반환/에러 안나면 True 반환

 

36-2. isdigit()

def solution(s):
    return ((len(s)==4 or len(s)==6) and s.isdigit())

isdigit은 문자열이 숫자로만 구성되어 있는지를 확인한다.

'문자열' 이라도 그 안의 구성들이 '숫자'인지 알아내는 유용한 함수

 

39. 최대공약수와 최소공배수

두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3, 12의 최대공약수는 3, 최소공배수는 12이므로 solution(3, 12)는 [3, 12]를 반환해야 합니다.

 

39-1. 유클리드호제법

def solution(a,b):
    x=max(a,b)
    y=min(a,b)
    r=x%y
    while r!=0:
        x=y
        y=r
        r=x%y
    lcm=y
    gcd=(a*b)/lcm
    return [lcm,int(gcd)]

1. x>y일 때, x를 y로 나눈 나머지가 r이면 x와 y의 최소공배수는 y와 r의 최소공배수와 같다.

2. a와 b의 최대공배수를 gcd, 최소공배수를 lcm이라고 할 때 a*b= gcd*lcm

위 두 가지 사실을 이용하면 구할 수 있다.

r이 0이 되기 전까지 x와 y를 새로운 값인 y와 r로 업데이트해주고 있으며

gcd를 구할 때 업데이트되어 값이 변한 x,y대신 a와 b를 사용해야 한다.

 

 

39-2. math.gcd

import math
def solution(a,b):
    gcd=math.gcd(a,b)
    lcm=a*b//gcd
    return [gcd, lcm]

최소공배수를 간편하게 구할 수 있는 math.gcd() 라는게 있다.

또한 lcm=a*b//gcd 를 사용하면 int변환할 필요 없이 바로 정수로 최대공약수를 구할 수 있다.

ex)

6/3=2.0 

6//3 -> 몫은 2 , 6%3->나머지는 0 

 

42. 삼총사

한국중학교에 다니는 학생들은 각자 정수 번호를 갖고 있습니다. 이 학교 학생 3명의 정수 번호를 더했을 때 0이 되면 3명의 학생은 삼총사라고 합니다. 예를 들어, 5명의 학생이 있고, 각각의 정수 번호가 순서대로 -2, 3, 0, 2, -5일 때, 첫 번째, 세 번째, 네 번째 학생의 정수 번호를 더하면 0이므로 세 학생은 삼총사입니다. 또한, 두 번째, 네 번째, 다섯 번째 학생의 정수 번호를 더해도 0이므로 세 학생도 삼총사입니다. 따라서 이 경우 한국중학교에서는 두 가지 방법으로 삼총사를 만들 수 있습니다.

한국중학교 학생들의 번호를 나타내는 정수 배열 number가 매개변수로 주어질 때, 학생들 중 삼총사를 만들 수 있는 방법의 수를 return 하도록 solution 함수를 완성하세요.

def solution(number):
    combs=list(combinations(number,3))
    count=0
    for comb in combs:
        if sum(comb)==0: count+=1
    return count

combinations(리스트, 개수) ->리스트에서 개수만큼의 요소를 선택하는 모든 경우의 수를 반환

여기서 for in 문으로 합이 0일때만 count를 올리게 하면 된다.

combinations만 알고 있으면 간단한 문제

 

45. 시저암호

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

def solution(s,n):
    result=""
    for letter in s:
        if letter.isalpha(): 
            if letter.islower():
                result+=(chr((ord(letter)-ord('a')+n)%26+ord('a')))
            else:
                result+=(chr((ord(letter)-ord('A')+n)%26+ord('A')))
        else: result+=letter
    return result
더보기

ord('문자') : 문자를 유니코드 값(숫자)로 반환

ex) ord('a')=97 ord('A')=65 ord(' ')=32 (공백의 유니코드값은 32)

 

chr(숫자): 유니코드 값에서 그 숫자에 해당하는 문자를 반환

ex) chr(97)=a

 

isalpha(): 해당문자열이 모두 알파벳으로 되어있는지

islower(): 해당문자열이 모두 소문자인지

isupper(): 해당문자열이 모두 대문자인지

 

ord('a')=97, ord('z')=122 이다.

97 98 99 ... 121 122
a b c   y z

 

다음과 같이 지정되어 있을 때 ord('a')값만큼 빼면

0 1 2 ... 24 25
a b c   y z

 

이렇게 알파벳이 0부터 25의 범위로 들어온다.

여기서 n만큼 뒤로 밀릴때 26부터는 다시 0으로 돌아오게 해야한다.

0 1 2 ... 24 25
26 27 28   50 51
52 53 54   76 77

조금만 살펴보면 같은 열의 숫자들은 26으로 나누었을때 나머지가 각각 0, 1, 2,..,24,25인것을 알 수 있다.

 

if letter.islower():
     result+=(chr((ord(letter)-ord('a')+n)%26+ord('a')))

위의 논리가 들어있는 부분이 바로 여기

ord(letter)에서 ord(a)만큼 빼서 0~25사이의 값으로 만들고,

n만큼 뒤로 미뤄서 시저암호로 만든 다음

26으로 나눈 나머지를 구해 숫자가 아무리 커져도 다시 0~25사이로 들어오게 하고

뺐던 ord('a')를 더해서 원래의 유니코드 값으로 되돌려주고

그 값을 chr() 안에 넣으면 시저암호로 변환된 문자가 나온다.

 

else: 이후는 대문자일때 처리방법으로 ord('A')를 사용한것 외에는 같은 논리

 

또 주목할점은 result=[] 이렇게 빈 리스트를 만드는 것처럼

result="" 이렇게 빈 문자열을 만들수도 있다.

문자열도 기본적으로 반복가능한 객체라서 리스트와 비슷하게 활용되는 부분이 있다.

46. 숫자열과 문자열과 영단어

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

  • 1478 → "one4seveneight"
  • 234567 → "23four5six7"
  • 10203 → "1zerotwozero3"

이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

 

46-1. dictionary and replace

def solution(s):
    num_dic={"0":"zero", "1":"one", "2":"two", "3":"three", "4":"four", "5":"five", "6":"six", "7":"seven", "8":"eight", "9":"nine"}
    for key, value in num_dic.items():
       while value in s:
           s=s.replace(value, key, 1)
    return int(s)

 

in 

더보기

해당 문자열 안에 특정 문자(열)이 포함되어 있는지 확인하여 True/False로 반환

ex

s="1zerotwozero3"
print("zero" in s) 

를 실행시키면 True가 나온다.

replace(old,new,count)

더보기

replace의 장점은 문자열을 순ㅊ ㅏ적으로 스캔해서 일치하는 패턴을 자동으로 찾는다는 점이다.

굳이 문자를 나누거나 슬라이싱하거나 리스트로 만들고 인덱스를 넣고 정규표현식을 쓰는 등 귀찮은 작업을 하지 않아도 된다.

 

old:대체될 문자

new:대체할 문자

count: 대체할 횟수

 

ex

list=['cat', 'dog', 'cat', 'bird', 'cat', 'turtle']

list.replace('cat', 'tiger', 2)

-> ['tiger', 'dog', 'tiger', 'bird', 'cat', 'turtle' ]

 

while value in s: zero부터 ten까지가 s에 포함된 경우

s=s.replace(value,key,1)

s의 value를 key로 대체하고 한번만 대체

 

s="2three46sixseven" ->"2346sixseven"->"23466seven"->"23457"

더이상 s에 value(zero부터 ten)가 없으므로 while문이 끝남

 

46-2. list and replace

def solution(s):
    num_words = ["zero", "one", "two", "three", "four","five", "six", "seven", "eight", "nine"]
    for i, word in enumerate(num_words):
        s=s.replace(word, str(i))
    return int(s)

enumerate(list)를 쓰면 인덱스가 알아서 부여는 점을 사용해서, 리스트를 사용해도 된다.

 

46-3. re.sub

import re
def solution(s):
    num_dic={"0":"zero", "1":"one", "2":"two", "3":"three", "4":"four", "5":"five", "6":"six", "7":"seven", "8":"eight", "9":"nine"}
    for number, word in num_dic.items():
        s=re.sub(word, number, s)
    return int(s)

 

re.sub(pattern, replace, strings)

pattern: 대체하고싶은 대상의 정규표현식이나 패턴

replace: 대체할 내용

strings: 원본문자열

 

47. 문자열 내 마음대로

문자열로 구성된 리스트 strings와, 정수 n이 주어졌을 때, 각 문자열의 인덱스 n번째 글자를 기준으로 오름차순 정렬하려 합니다. 예를 들어 strings가 ["sun", "bed", "car"]이고 n이 1이면 각 단어의 인덱스 1의 문자 "u", "e", "a"로 strings를 정렬합니다.

def solution(strings,n):
    answer=sorted(strings, key=lambda x: (x[n], x))
    return answer

 

sorted() 에는 key라는 옵션을 줄 수 있다.

key 다음에는 함수가 들어가며

sort는 key 다음에 나오는 함수에 iterable의 각 요소를 넣어서, 반환된 값을 기준으로 정렬한다.

ex

animals=[ 'tiger', 'Felis catus', 'Sternotherus carinatus', 'dog']

sorted(animals, key=len)  ->animals 요소에 len함수를 적용하여 반환된 값을 기준으로 오름차순 정렬

['dog', 'tiger',  'Felis catus', 'Sternotherus carinatus']

 

lambda

익명의 함수를 사용할 수 있어서 간단한 함수를 사용할때 유용함 

lambda input : output  (ex: lambda x: x^2 -> x제곱을 반환하는 함수)

 

x[n]

여기서 x에는 strings의 각 요소가 들어간다.

위의 예시에서는 sun, bed, car가 전달되며 n=1이라면

sun[1]=u , bed[1]=e, car[1]=a 가 된다. 

sort는 이 반환값을 기준으로 strings를 정렬한다.

 

x[n], x

만약 x[n]이 같으면 그 다음에는 x 순서대로 정렬하도록 하는 옵션

'파이썬' 카테고리의 다른 글

heapq, deque  (0) 2024.12.02
CodeKata-3  (2) 2024.11.21
CodeKata-1  (2) 2024.11.14
WIL(2주차)  (1) 2024.10.11
random, dataframe (인사이드아웃, 흑백요리사)  (2) 2024.10.11