[Algorithm] 2309. 일곱 난쟁이

유지민·2023년 1월 25일
0

Algorithm

목록 보기
6/75
post-thumbnail

2309. 일곱 난쟁이 (Bronze I)

✔️ 문제

2309번 문제 보기

✔️ 문제 분석 및 해결 과정 설계

  • 문제 이해 :

    • 일곱 난쟁이의 키의 합 : 100
    • 9 난쟁이 중 7 난쟁이 찾아내기
  • 입력 :

    • 9개의 줄에 걸쳐 난쟁이의 키가 주어짐
    • 1 <= 난쟁이 키 < 100
    • 아홉 난쟁이의 키는 모두 다름
  • 출력 :

    • 일곱 난쟁이의 키 오름차순 출력
    • 일곱 난쟁이를 찾을 수 없는 경우 X
    • 가능한 정답이 여러 가지인 경우 아무거나 출력
  • 문제 분석

    • 순서는 상관 없이 9개 중 7개의 값을 뽑아 합이 100이 되는 조합을 찾으면 되는 문제
    • combinations()를 사용해 7개의 조합을 뽑은 뒤 100이 되는 값을 새로운 리스트에 넣음
      • 입력 조건에서 "난쟁이의 키는 모두 다름"이라고 하였으므로 중복은 없음
    • 마지막 출력 시 새로운 리스트의 값을 sort()해서 출력

✔️ 문제 해결 과정

  1. 9개의 입력값 list에 저장
  2. combinations()를 사용해 7개의 조합 생성
  3. 합이 100이 되는 값을 sorted()해 요소 출력
from itertools import combinations

heights = [int(input()) for _ in range(9)]

for combi in combinations(heights, 7):
    print(combi) # tuple 형태로 출력
    if sum(combi) == 100:
        for height in sorted(combi):
            print(height)

"가능한 정답이 여러개인 경우 아무거나 출력하라" 조건을 고려하지 않음
→ 위 코드의 경우 7개의 합이 100인 경우가 여러개일 때, 7개, 14개, 21개, ...를 출력하는 문제 발생

from itertools import combinations

heights = [int(input()) for _ in range(9)]

for combi in combinations(heights, 7):
    if sum(combi) == 100:
        for height in sorted(combi):
            print(height)
        break

합이 100인 경우를 찾으면 break를 사용해 반복 탈출

Combination 없이 해당 문제를 해결하는 방법

  • 플래그를 사용해 문제 해결
heights = [int(input()) for _ in range(9)]
heights.sort()
tot = sum(heights)
flag = False

# 9개 중 7개를 뽑는 것 == 9개 중 2개를 뽑는 것
for i in range(8):
    for j in range(i + 1, 9):
        if tot - heights[i] - heights[j] == 100:
            for k in range(9):
                if i != k and j != k:
                    print(heights[k])

            flag = True
            break

        if flag:
            break
  • break문을 사용하는 것이 아닌, exit()로 답 중복 출력 경우 제거
heights = [int(input()) for _ in range(9)]
heights.sort()
tot = sum(heights)
flag = False

# 9개 중 7개를 뽑는 것 == 9개 중 2개를 뽑는 것
for i in range(8):
    for j in range(i + 1, 9):
        if tot - heights[i] - heights[j] == 100:
            for k in range(9):
                if i != k and j != k:
                    print(heights[k])

            exit()
  • 함수로 처리해 값이 도출될 경우 return 사용
heights = [int(input()) for _ in range(9)]
heights.sort()
tot = sum(heights)
flag = False

# 9개 중 7개를 뽑는 것 == 9개 중 2개를 뽑는 것
def f():
    for i in range(8):
        for j in range(i + 1, 9):
            if tot - heights[i] - heights[j] == 100:
                for k in range(9):
                    if i != k and j != k:
                        print(heights[k])

                return

f()

💡 회고

  • 본인의 풀이 소스코드
from itertools import combinations
nine_array = []

for _ in range(9):
    nine_array.append(int(input()))

for i in combinations(nine_array, 7):
    if sum(i) == 100:
        seven_array = list(i)

seven_array.sort()

for i in seven_array:
    print(i)
  • 강의에서의 풀이 소스코드
from itertools import combinations

heights = [int(input()) for _ in range(9)]

for combi in combinations(heights, 7):
    if sum(combi) == 100:
        for height in sorted(combi):
            print(height)
        break

본 문제는 비교적 쉽게 풀이할 수 있었다.
1. 합이 100이되는 7개의 리스트 요소 추출
2. 정렬하여 7개의 요소 출력
- 이 때 답이 여러가지 도출된다면 아무거나 출력
위 조건들만을 고려해주면 되는 문제였다.

강의에서의 풀이와 내 코드를 비교해보니 "가능한 정답이 여러개인 경우 아무거나 출력하라" 조건을 고려하지 않고 풀이했다는 점을 발견했다.
근데 왜 코드 제출했을 때는 맞다고 나왔을까 ...?

for i in combinations(nine_array, 7):
    if sum(i) == 100:
        seven_array = list(i)

분석해보니 combinations()를 사용해 합이 100이 되는 조합을 찾았을 때
if 분기문 내에서 해당 조합을 seven_array에 넣어줬기 때문에,
만약 답이 되는 조합1과 조합2가 있을 경우 최종적으로 "아무 조합이나" seven_array에 저장되었을 것이며,
이로써 조건을 충족해줬다고 할 수 있겠다.

강의에서의 로직대로 내 코드에 적용시켜본다면
조건을 만족하는 조합이 발생하였을 때 조합을 반복적으로 찾는 과정을 중단하기 위해 break를 걸어주면 되겠다.

for i in combinations(nine_array, 7):
    if sum(i) == 100:
        seven_array = list(i)
    break

강의에서의 풀이 코드와 본인의 코드를 분석하며 보다 간결하게 코드를 작성할 수 있겠다는 생각을 했으며,
간결한 코드가 지나칠 경우 코드의 직관성과 가독성이 떨어지는 부작용이 발생할 수 있겠다 판단하여
적절한 단계에서 코드를 작성해야겠다고 느꼈다.

📝 Check point

  • combinations() : 리턴 값은 tuple의 형태
  • sorted(ARRAY_NAME) : 정렬된 새로운 리스트 리턴
  • sort(ARRAY_NAME) : 아무것도 리턴하지 않음 (None)
some_list = [5, 7, 2, 3, 1]

print(sorted(some_list)) # [1, 2, 3, 5, 7]
print(some_list.sort()) # None
  • list(DATA_STRUCTURE) : 리스트로 변환하는 메소드
profile
끊임없이 도전하며 사고하는 주니어 Web 개발자 유지민입니다.

0개의 댓글