본문 바로가기

개발일지/TIL

TIL 23-05-01 팀원과의 코드리뷰 - 한 번만 등장한 문자

1. 팀원과의 코드리뷰 - 한 번만 등장한 문자 

 문제점

https://school.programmers.co.kr/learn/courses/30/lessons/120896

# 문자열 s
# in으로 확인하기

 시도해 본 것들

dict 사용해서 문자열 숫자 확인하기

def solution(s):
    answer = ''
    s_list = {}
    for i in s:
    	# s_dict에 없다면
        if i not in s_list:
            s_list[i] = 1
        # s_dict에 있다면
        elif i in s_list:
            s_list[i] += 1
    # for문의 순서 = key를 기준으로 sort된 s_list로 사용
    for i in sorted(s_list.keys()):
        # value 값이 1이면
        if s_list[i] == 1:
            answer += i
    return answer

첫 번째 for문으로 s_list [i]로 등장 횟수 확인하기

두 번째 for문으로 key를 i에 담고 if문으로 값이 1인 key만 추가하기

 

완성된 코드 리팩토링하기 

def solution(s):
    s_dict = {}
    for i in s:
        if i not in s_dict:
            s_dict[i] = 1
        elif i in s_dict:
            s_dict[i] += 1
        # if 값이 1인 key를 정렬해서 리스트화
        # ''.join()으로 리스트 언패킹
    return ''.join([i for i in sorted(s_dict.keys()) if s_dict[i] == 1])

List Comprehension과 ''. join으로 변수와 for문, if문 줄이기  

 

dict 대신 list로 풀어보기

def solution(s):
    answer = []
    pop_list = []
    for i in s:
        # answer에 i가 없다면
        if i not in answer:
            answer.append(i)
        # answer에 i가 있다면
        else:
            pop_list.append(i)
    for p in pop_list:
        try:
            # 전체 리스트에서 index찾기
            pop_index = answer.index(p)
            # 전체 리스트에서 빼기
            answer.pop(pop_index)
            # del로 같은 결과 가능
            # del answer[pop_index]
            # 없는 값 pop 에러 핸들링
        except ValueError:
            pass
    return ''.join(sorted(answer))

처음 등장한 숫자 answer에 추가 

중복된 숫자가 생기면 pop_list에 추가 

pop_index로 answer에서의 index 찾기 

answer.pop()으로 중복 값 제거 

try, except를 통해서 pop으로 빈값 제거 시도 에러 처리 

 

set을 통한 try, except 제거

    for p in set(pop_list):
        pop_index = answer.index(p)
        answer.pop(pop_index)
    return ''.join(sorted(answer))

for문에서 set을 사용하면서 처음부터 중복값을 제거하고 시작 

 

팀원과의 코드리뷰 

로직이 기억에 남는 코드 

def solution(s):
    answer = ''
    words = sorted(s)
    for i in range(len(words)):
        alpha = words[::] # words.copy()
        alpha.remove(words[i])
        if words[i] not in alpha:
            answer += ''.join([words[i]])
    return answer

alpha로 깊은 복사를 실행하고 remove를 통해서 원소를 하나 지우기

if문에서 지워진 원소가 alpha에 없는지 확인 <= 1개라면 if문 진입 , 2개 이상이라면 진입 X

 

리뷰 중 set과 list로 풀이하기

def solution(s):
    answer = ''
    s_list = list(s)
    s_set_list = list(set(list(s)))
    for i in sorted(s_set_list):
        s_list.remove(i)
        if i not in s_list:
            answer+=i
    return answer

한 팀원이 리뷰 중 set과 list로는 풀 수 없을지 고민하면서 만든 코드다.

지금 살펴보니 로직 자체는 위의 코드와 동일하다. 

for문에서 원소를 한개씩 지우고 if문에서 s_list에 존재하는지 확인한다. 

 

코드 리팩토링

def solution(s):
    answer = ''
    words = sorted(s)
    for i in words:
        alpha = words[::] # words.copy()
        alpha.remove(i)
        if i not in alpha:
            answer += i
    return answer

이 코드를 작성했던 팀원이 remove는 str 값으로 삭제가 가능하다고 한 이야기를 듣고 수정할 수 있었다. 

 

def solution(s):
    answer = ''
    s_list = list(s)
    for i in sorted(set(s)):
        s_list.remove(i)
        if i not in s_list:
            answer+=i
    return answer

set()이 사용되는 곳이 for문 하나이므로 변수로 선언하는 대신 for문에 직접적으로 넣어줬다.  

 

 해결 방법

dict를 사용한 풀이 

def solution(s):
    s_dict = {}
    for i in s:
        # s_dict에 없다면
        if i not in s_dict:
            s_dict[i] = 1
        # s_dict에 있다면
        elif i in s_dict:
            s_dict[i] += 1
        # if 값이 1인 key를 정렬해서 리스트화
        # ''.join()으로 리스트 언패킹
    return ''.join([i for i in sorted(s_dict.keys()) if s_dict[i] == 1])

 

list를 활용한 풀이 

def solution(s):
    answer = []
    pop_list = []
    for i in s:
        # answer에 i가 없다면
        if i not in answer:
            answer.append(i)
        # answer에 i가 있다면
        else:
            pop_list.append(i)
    for p in set(pop_list):
        # 전체 리스트에서 index찾기
        pop_index = answer.index(p)
        # 전체 리스트에서 빼기
        answer.pop(pop_index)
    return ''.join(sorted(answer))

 

count를 사용한 풀이 

def solution(s):
    # for문 = set()으로 중복을 제거하고 sorted()로 정렬된 s
    # i = count로 확인된 숫자가 1개인 변수
    return ''.join([i for i in sorted(set(s)) if s.count(i) == 1])
count는 바로 생각 못했다. count를 활용한 예를 보고서야 만들 수 있었다.
 

index를 활용한 풀이 

def solution(s):
    answer = ''
    for n in set(s):
        # 첫번째 index 찾기
        first_index = s.index(n)
        # 두번째 index 찾기 시도
        try:
            _ = s.index(n, first_index+1)
        # 두번째 index가 없을 경우 except ValueError:
        except ValueError:
            answer += n
    return ''.join(sorted(answer))

두 번째 index를 찾으려고 할 때 ValueError가 발생하는 것을 이용한 풀이 

 알게 된 점

여러가지 풀이방법이 가능한 알고리즘을 풀면서 각각의 사용방법이 연결되고 미흡한 사용법은 잘 아는 사용법을 통해서 이해할 수 있는 시간이었다.

알고리즘은 함수를 이용해서 깔끔하게 푸는 것도 좋지만, 함수를 모르거나 사용하지 않고 다르게 풀 때 사고력 향상에 매우 도움이 되는 것 같다. 

 

1. 백준 알고리즘 - 분산처리

 문제점

# 1번부터 10번까지 컴퓨터를 가지고 차례대로 연산함
# return은 마지막 자료를 처리하는 컴퓨터의 번호 

 시도해 본 것들

기본적인 구현 후 결과 체크 

T = int(sys.stdin.readline())
for _ in range(T):
    a, b = map(int, sys.stdin.readline().split())
    total_num = str(a**b)
    print(int(total_num[-1]))

시간 초과 발생 ** 연산이 시간을 많이 사용하는 것 같다.

 

** 연산 시간 개선하기 

연산량을 최소화하기 위해 마지막 자릿수만 취해서 계산하기 

a1, b1 = int(str(a)[-1]), int(str(b)[-1])
    total_num = str(a1 ** b1)

마지막 자리가 0인 경우 0을 출력하는데 10을 출력해야 함

 

10번 컴퓨터 출력을 위한 if문 추가

if int(total_num[-1]) == 0:
        print(10)
    else:
        print(int(total_num[-1]))

아직 결과가 제대로 나오지 않음

 

반례 찾기 

print(pow(2, 10)) # 1024
print(pow(2, 0)) # 1
print(pow(2, 1)) # 2

b를 한자리만 가지고 오면 제대로 된 끝자리가 나오지 않음 

 

제곱 값 변경 

a1, b1 = int(str(a)[-1]), int(str(b)[-2:])

b1을 끝에서 두 자리를 취함

 해결 방법

T = int(sys.stdin.readline())
for _ in range(T):
    a, b = map(int, sys.stdin.readline().split())
    a1, b1 = int(str(a)[-1]), int(str(b)[-2:])
    total_num = str(a1 ** b1)
    if int(total_num[-1]) == 0:
        print(10)
    else:
        print(int(total_num[-1]))

 알게 된 점

제곱값을 두 자리 수로 취하면서 통과했지만, 1500과 0을 비교하면 다른 숫자가 나오는데 올바른 로직으로 푼 게 맞을까?

올바른 로직이라고 해도 이해가 안 되는 걸 보면 제대로 푼 건 아닌 것 같다.