[Baekjoon] 12034/김인천씨의 식료품가게 (Large)/Python/파이썬

·2025년 3월 10일
0

문제풀이

목록 보기
47/56
post-thumbnail

💡문제

전설적인 인천 식료품가게의 주인인 김인천 씨는 대대적인 할인행사를 계획하고 있습니다. 계산을 단순하게하기 위해 그는 25% 할인된 가격으로 상점의 모든 품목을 판매하기로 결정했습니다. 즉, 각 품목의 판매 가격은 정상 가격의 정확히 75 %입니다. 우연하게도 인천 식료품가게에서 판매하는 모든 물건의 정상가는 4의 배수인 정수이고, 할인된 가격 역시 편리하게도 모두 정수입니다.

김인천씨는 이 할인행사를 준비하기위해서 먼저 모든 판매물품의 할인된 판매가격을 프린터로 출력을 실행했고, 또한 할인행사 종료후 다시 쓸 모든 품목에 정상가격표 역시 출력을 실행하였습니다.

손님이 찾아와 잠깐 자리를 비웠던 김인천씨가 다시 가격표의 출력을 확인하기 위해서 프린터로 돌아와보니, 공교롭게 프린터는 모든 물품의 할인가격과 정상가격을 따로 구분하지 않고 오름차순으로 정렬한 뒤 순서대로 출력하여 하나의 출력물 더미를 만들었습니다. 각 품목의 할인가격표와 정상가격표 모두가 출력물 더미의 어딘가에 있습니다. 그러나 두 유형(할인가격, 정상가격)의 가격표는 비슷하게 보이고, 모든 품목의 가격을 기억하지 못하기 때문에 김인천씨는 어느 가격표가 할인가격표인지 확신할 수 없습니다. 이 상황에서 김인천씨는 무엇이 할인가격표인지 구분해낼 수 있을까요?

예를 들어, 정상가격이 20, 80, 100 인 경우 할인가격은 15, 60, 75이며 프린터의 인쇄출력더미는 오름차순으로 정렬된 15, 20, 60, 75, 80, 100 가격표들로 구성됩니다.

입력

입력의 첫 번째 라인(줄)은 테스트 사례의 케이스의 수 T를 나타냅니다. 이후의 라인은 T개의 테스트 케이스가 이어집니다. 각 테스트 케이스는 두 줄로 구성됩니다. 첫 번째 줄에는 INU 식료품가게에 존재하는 상품수인 단일 정수 N이 포함됩니다. 두 번째 줄에는 프린터에서 가격의 오름차순으로 인쇄한 2N개의 정수 P1, P2, ..., P2N이 주어집니다.

입력값의 제한은 아래와 같습니다

  • 1 ≤ T ≤ 100.
  • 모든 i에 대해서 1 ≤ Pi ≤ 109.
  • 모든 i에 대해서 Pi ≤ Pi+1. (가격은 오름차순으로 존재)
  • 정답은 단 하나만 존재하는것이 보장되어 있음.
  • 1 ≤ N ≤ 100

출력

개별 테스트 케이스에 대해서 출력라인은 “Case #x: y” 형식(큰 따옴표는 제외)으로 출력하며, x는 1부터 시작하는 테스트 케이스의 번호 (인덱스)이며, y는 할인가격에 해당하는 오름차순으로 정렬된 N개의 정수들이다.

예제입력

2
3
15 20 60 75 80 100
4
9 9 12 12 12 15 16 20

예제출력

Case #1: 15 60 75
Case #2: 9 9 12 15

📖내가 작성한 Code

import sys
import collections


def find_discount_price(n, array):
    counter = collections.Counter(array)
    result = []
    for price in array:
        if len(result) == n:
            return " ".join(map(str, result))

        if counter[price]:
            counter[price] -= 1
            prev_price = price // 3 * 4
            if counter[prev_price]:
                counter[prev_price] -= 1
                result.append(price)
            
    return " ".join(map(str, result))


def main():
    inputs = map(int, sys.stdin.read().split())
    for test_case in range(1, next(inputs)+1):
        sys.stdout.write(f'Case #{test_case}: '
                         f'{find_discount_price(n := next(inputs), [next(inputs) for _ in range(n*2)])}\n')


if __name__ == '__main__':
    main()

✍️풀이과정

이따금, 실버 5인데 안풀리면 자괴감이 들 때가 있다. 멘탈이 무너져서 이거 쓸까말까하다가 그냥 적음. 결과론적으로 출력문을 잘못 적은거였다.

처음에는 원본 가격에서 세일 가격을 찾기를 했는데 원본 가격 %4 한게 4의 배수가 될 수 있기 때문에, 세일 가격을 원본가격으로 돌리게 했다.
그리고 remove는 시간이 많이 걸려서 counter 사용했는데, 시간 빠른거 보니까 대부분 remove썻드라...
그리고 마지막으로

sys.stdout.write(f'Case #{test_case}: '
                         f'{find_discount_price(n := next(inputs), [next(inputs) for _ in range(n*2)])}\n')                       

여기서 띄어쓰기를 한번 잘못해서 오류가 나고 있었던 것이였다. 다시 한 번 조심해야겠다.


🧠 코드 리뷰

  1. 코드 분리: 주요 로직(할인 가격 쌍 찾기)과 입출력 처리 부분을 분리하여 모듈화하면, 테스트 및 디버깅이 용이해집니다.

🛠️AI 개선 코드

import sys
import collections

def find_discount_price(n, prices):
    """
    할인 가격과 정상 가격 쌍을 찾아 할인 가격만 반환하는 함수.
    
    할인 가격에 대한 정상 가격은 (할인 가격 // 3 * 4)로 계산되며,
    주어진 prices 리스트에서 할인 가격과 정상 가격이 각각 존재하는 쌍을 찾습니다.
    
    Parameters:
        n (int): 할인 가격 쌍의 개수.
        prices (List[int]): 길이가 2*n인 가격 리스트 (할인 가격과 정상 가격이 섞여 있음).
    
    Returns:
        str: 찾은 할인 가격들을 공백으로 구분한 문자열.
    """
    price_counter = collections.Counter(prices)
    valid_discounts = []

    for discount in prices:
        if len(valid_discounts) == n:
            break

        # 현재 할인 가격이 사용 가능한 경우 처리
        if price_counter[discount] > 0:
            price_counter[discount] -= 1

            # 할인 가격에 대응하는 정상 가격 계산
            original_price = discount // 3 * 4
            if price_counter[original_price] > 0:
                price_counter[original_price] -= 1
                valid_discounts.append(discount)

    return " ".join(map(str, valid_discounts))

def main():
    """
    전체 입력을 처리하고, 각 테스트 케이스마다 결과를 출력하는 메인 함수.
    """
    input_values = list(map(int, sys.stdin.read().split()))
    num_cases = input_values[0]
    index = 1
    output_lines = []

    for case in range(1, num_cases + 1):
        n = input_values[index]
        index += 1
        prices = input_values[index:index + 2 * n]
        index += 2 * n

        result = find_discount_price(n, prices)
        output_lines.append(f"Case #{case}: {result}")

    sys.stdout.write("\n".join(output_lines))

if __name__ == '__main__':
    main()

💻결과

백준문제 보러가기


🖱️참고 링크

나무위키 그리디 알고리즘 참고

profile
우물 안에서 무언가 만드는 사람

0개의 댓글