본문 바로가기
파이썬/파이썬 알고리즘

파이썬 프로그래머스 level 1. 체육복

by Go! Jake 2021. 5. 2.

 

 

이전 글: 파이썬 프로그래머스 level 1. 모의고사

이전 글: 파이썬 프로그래머스 level 1. K번째수

  문제

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.

전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.

 

 

 

 

  풀이

별도의 내 풀이가 있으나 모범 답안 풀이가 효율적이고 배울 점이 있어 이에 코멘트하는 것으로 대체한다.

def solution(n, lost, reserve):
    reserve_a=[r for r in reserve if r not in lost]
    lost_a=[a for a in lost if a not in reserve]

    for i in reserve_a:
        left=i-1
        right=i+1
        if left in lost_a:
            lost_a.remove(left)
        elif right in lost_a:
            lost_a.remove(right)
    print("lost_a",lost_a)
    return n-len(lost_a)

 

 

<1>

    reserve_a=[r for r in reserve if r not in lost]
    lost_a=[a for a in lost if a not in reserve]

도난당한 학생과 여분의 옷이 있는 학생이 겹치는 경우 다른 사람에게 체육복을 줄 수도 없고, 옷이 없는 것도 아니므로 서로 영역에서 겹치는 부분은 제외 해 줄 필요가 있다.

 

reserve_a=[r for r in reserve if r not in lost] - 예시로 들면, 이 코드는 reserve에 있는 값이지만 lost에는 없는 값을 넣겠다는 의도의 코드이다.

 

 

<2>

    for i in reserve_a:
        left=i-1
        right=i+1
        if left in lost_a:
            lost_a.remove(left)
        elif right in lost_a:
            lost_a.remove(right)

for i in reserve_a:
    left=i-1
    right=i+1

해당 코드에 대한 접근은, '여벌이 있는 학생이 나눠줄 수 있는 도난당한 학생이 좌우에 있는 지'이다. 내 풀이는 반대로 '도난 당한 학생 근처에 여벌이 있는 학생이었는 지'가 되었다. 따라서 완전 탐색하게 되었는 데, 불필요한 코드를 여러 개 생성하였다. 따라서 문제마다 양 방향으로 생각 해 보고 어느 방향이 빠른 지 판단할 수 있는 능력이 필요하다.

left와 right 변수를 정의한다.

 

    if left in lost_a:
        lost_a.remove(left)
    elif right in lost_a:
        lost_a.remove(right)
    return n-len(lost_a)

이 때 왼쪽 학생이 도난당한 학생이면 체육복을 주고 이 도난당한 학생 명단에서 이 학생을 제외한다.

리스트.remove(값), remove는 리스트에서 "값"을 기준으로 제거하는 것이기 때문에, remove() 함수는 이 때 적절한 함수가 된다.

 

왼쪽 학생이 도난 당한 학생이 아니면 우측 학생이 도난 당한 학생인지 보고 마찬가지 작업을 한다.

다만 이 때 elif를 사용하는 게 반드시 중요하다. 단순히 if를 사용하면 왼쪽 학생에게도 체육복을 주고, 오른쪽 학생에게도 체육복을 줄 수 있기 때문이다. 따라서 elif 조건으로, if 조건에서 이미 체육복을 주었다면 그 이후 코드에서는 체육복을 줄 수 없도록 elif를 사용한다. 간단한 문제였지만 매우 중요한 내용으로 파악된다.

 

마지막으로 n-len(lost_a)로 전체 학생 수에서 최종으로 남은 도난당하여 체육복이 없는 학생을 빼면 체육복을 입을 수 있는 학생 수가 된다.

 

- 다음 글: 파이썬 프로그래머스 level 1. 2016년

- 다음 글: 파이썬 프로그래머스 level 1. 가운데 글자 가져오기

 

 

댓글