프로그래머스

프로그래머스 Python Lv.1 가장 가까운 같은 글자 / 개인정보 수집 유효기간

s2h15 2023. 12. 17. 15:08
728x90

1. 가장 가까운 같은 글자

 

 

문제 설명  

문자열 s가 주어졌을 때, s의 각 위치마다 자신보다 앞에 나왔으면서, 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알고 싶습니다.예를 들어, s="banana"라고 할 때,  각 글자들을 왼쪽부터 오른쪽으로 읽어 나가면서 다음과 같이 진행할 수 있습니다.
b는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.a는 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.n은 처음 나왔기 때문에 자신의 앞에 같은 글자가 없습니다. 이는 -1로 표현합니다.a는 자신보다 두 칸 앞에 a가 있습니다. 이는 2로 표현합니다.n도 자신보다 두 칸 앞에 n이 있습니다. 이는 2로 표현합니다.a는 자신보다 두 칸, 네 칸 앞에 a가 있습니다. 이 중 가까운 것은 두 칸 앞이고, 이는 2로 표현합니다.
따라서 최종 결과물은 [-1, -1, -1, 2, 2, 2]가 됩니다.
문자열 s이 주어질 때, 위와 같이 정의된 연산을 수행하는 함수 solution을 완성해주세요.

나의 풀이

 

def solution(s):
    list = []
    result = []
    for i,v in enumerate(s):
        if v not in list:
            result.append(-1)
            list.append(v)
        else:
            index = s.find(v)
            result.append(i - index)
            list.append(v)
            s = s[:index] +" "+ s[index+1:]
    return result

 

문자열 s를 각각의 문자와 인덱스번호로 나누어 만약 가상의 리스트에 해당하는 문자가 없으면 -1을  result 리스트에 넣고,

리스트에 그 문자를 넣어 그 뒤에 오는 문자와 비교할 수 있도록 하였다.

만약 앞에서 있었던 문자가 있으면 이는 리스트에도 동일한 문자가 있으므로 result로는 해당 문자의 위치에서 문자열에서 동일한 문자 위치 index를 뺀 값을 넣고 , 문자열은 다시 해당 하는 문자를 공백으로 바꿔 지정하였다( find로 해당 문자의 인덱스 번호를 가지고 올때 제일 앞에 있는 문자를 기준으로 인덱스 번호가 나오기 때문에)

 

 

다른사람 풀이 + 개선점

 

def solution(s):
    answer = []
    dic = dict()
    for i in range(len(s)):
        if s[i] not in dic:
            answer.append(-1)
        else:
            answer.append(i - dic[s[i]])
        dic[s[i]] = i

    return answer

 

딕셔너리를 사용하여 나와 비슷한 방식으로 실행하였다.

 

 

 

 

2. 개인정보 수집 유효기간

 

 

 

 문제 설명  

 


고객의 약관 동의를 얻어서 수집된 1~n번으로 분류되는 개인정보 n개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인정보가 어떤 약관으로 수집됐는지 알고 있습니다. 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 합니다.
예를 들어, A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면 해당 개인정보는 2022년 1월 4일까지 보관 가능하며 2022년 1월 5일부터 파기해야 할 개인정보입니다.당신은 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 합니다.
모든 달은 28일까지 있다고 가정합니다.

나의 풀이

 

def solution(today, terms, privacies):
    result = []
    dic = {}
    today = int(today.replace(".",""))
    for t in terms:
        dic[t[0]] = t[2:]
    for i, p in enumerate(privacies):
        yyyy , mm ,dd =  p[:10].split(".")
        yyyy = int(yyyy) + int(dic[p[-1]]) // 12
        mm = int(mm) + int(dic[p[-1]]) % 12
        dd = int(dd) -1
        if mm > 12 :
            yyyy += mm //12
            mm = mm % 12
        if dd == 00:
            mm -= 1 
            dd = 28
        mm = str(mm)
        dd = str(dd)
        if len(mm) == 1:
            mm = "0" + mm
        if len(dd) == 1:
            dd = "0" + dd
        ymd = int(str(yyyy)+str(mm)+str(dd))
        if today > ymd:
            result.append(i+1)
    return result

 

① terms의 약관 종류와 유효기간을 각각 key , value 로 나누어 딕셔너리에 넣어주기.

for t in terms:
    dic[t[0]] = t[2:]

 

 

② privacies를 인덱스 i , 값 p로 나누어(enumerate) for문을 통해 하나의 값씩 유효기간을 계산하도록 함.

이때 값을 yyyy , mm, dd 즉 년도 , 월 , 일 로 나누어줌.

for i, p in enumerate(privacies):
    yyyy , mm ,dd =  p[:10].split(".")

 

 

③ 년도는 yyyy 에 해당하는 약관종류에 맞는 유효기간 개월수를 딕셔너리에서 찾아 더한값을 12로 나눈 몫을 더해줌.

 

2022년 8월 일때 유효기간이 10개월이면 2023년 6월이다.

따라서 18개월에서 12를 나눈 1을 년도에 더해준다. 

yyyy = int(yyyy) + int(dic[p[-1]]) // 12

 

④ 월 mm 은 mm에 유효기간 개월수를 더한 뒤 12로 나눈 나머지를 더해준다

 

8월 일때 유효기간 10개월이면 18에서 12를 나눈 나머지 6을 더해줌 , 일자dd에서는 1을 빼

mm = int(mm) + int(dic[p[-1]]) % 12
dd = int(dd) -1

 

⑤ 만약 mm의 값이 12보다 크면 (  10월인데 유효기간이 13이라 년에는 1년 월에는 11이 더해져 월이 21이 된경우)

mm 을 12로 나누어 몫을 yyyy에 더해주고 mm에는 그 나머지 값을 지정해준다(더하는것 아님)

if mm > 12 :
    yyyy += mm //12
    mm = mm % 12

 

⑥ 만약 dd가 00 이면( 01 이라서 1을 뺐을때 00 이됨) 

mm 에서 1을 뺀 뒤 dd 에는 마지막 날 값인 28을 지정해준다.

if dd == 00:
    mm -= 1 
    dd = 28

 

⑦ 각각 계산이 끝난 후 mm과 dd는 한자리 수가 될 수 있음 이를 03 / 05 와 같은 형태로 바꾸어주어야함.

문자열로 변경한 뒤에 0을 앞에 붙여주는 형식을 선택했다.

mm = str(mm)
dd = str(dd)
if len(mm) == 1:
    mm = "0" + mm
if len(dd) == 1:
    dd = "0" + dd

 

⑧ today 를 20220101의 형식으로 바꾸어준뒤 yyyymmdd 형식으로 된 int를 만들어 그 크기를 비교하여

유효기간이 지났는지 아닌지를 판단한 뒤 유효기간이 지났으면 result라는 리스트에 그 인덱스값 + 1을 append한다.

 

today = int(today.replace(".",""))
ymd = int(str(yyyy)+str(mm)+str(dd))
if today > ymd:
    result.append(i+1)

 

 

다른사람 풀이 + 개선점

 

def to_days(date):
    year, month, day = map(int, date.split("."))
    return year * 28 * 12 + month * 28 + day

def solution(today, terms, privacies):
    months = {v[0]: int(v[2:]) * 28 for v in terms}
    today = to_days(today)
    expire = [
        i + 1 for i, privacy in enumerate(privacies)
        if to_days(privacy[:-2]) + months[privacy[-1]] <= today
    ]
    return expire

 

년도와 월 일을 각각으로 생각하지 않고 일수로 환산하여 계산하는 방법이다.

각각으로 생각하다보니 00과 같이 없는 일자는 월에서 1을 빼고 28을 넣어주는 등 이런 저런 조건 문이 길어져서 실패하는 경우가 많았는데 이러한 방법을 사용하면 그냥 년월일을 일수로 계산하니 그런 조건 문을 넣어줄 필요가 없이 비교가 가능해진다.

728x90