Stay Hungry Stay Foolish

SWEA

[SWEA] 1209. [S/W 문제해결 기본] 2일차 - Sum (Python/D3)

dev스카이 2024. 10. 25. 15:31

[문제 링크] 👇

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com


풀이

💡 슬라이싱, 행 열 변환, sum(), max() 이용

 

 

📌 각 행, 열의 합 구하는 방법

for i in range(100):
    sum_num = sum(board[i][:])
  • [ : ]
    • 모든 인덱스를 슬라이싱 한다.
    • [5 : ] = 5부터 끝까지 슬라이싱, [5 : 7] = 5부터 6까지 슬라이싱, [ : 8] = 처음부터 7까지 슬라이싱
  • sum(board[i][:])
    • i가 0부터 99까지 움직이므로 각 행의 전체를 가져와서 합계를 구한다.

 

📌 행 열을 서로 변경하는 방법

new_board = list(map(list, zip(*board)))

 

  • zip(*board)
    • zip은 여러 개의 이터러블(iterable, 반복 가능한 객체)을 병렬로 묶어서 각 위치에 있는 요소들을 튜플(tuple)로 반환한다.
    • 여기서 *board는 리스트 board의 각 행을 개별적으로 zip에 전달하는 역할을 한다. 즉, *board는 board의 모든 행을 각각의 인자로 전달한다.
    • zip(*board)의 결과는 각 열을 튜플로 묶은 이터레이터가 된다.
  • map(list, zip(*board))
    • zip(*board)의 결과는 튜플이므로, 이를 리스트로 변환해야 한다.
    • map(list, zip(*board))는 zip(*board)의 각 튜플을 list로 변환하여 이터레이터로 반환한다.
  • list(map(list, zip(*board))):
    • map의 결과는 이터레이터이기 때문에, list()로 감싸 최종적으로 list 객체로 변환한다.
    • 최종 결과는 행과 열이 전환된 2차원 리스트가 된다.

 

📌 최댓값 구하는 방법

result = max(row_max, col_max, dia_max)
  • row_max, col_max, dia_max
    • 행의 합 중에서 최댓값, 열의 합 중에서 최댓값, 대각선의 합 중에서 최댓값이다.
  • max()
    • 최댓값을 반환하는 파이썬의 내장 함수다. 
    • 인자로 정수를 전달하면 최댓값을 반환한다.

 

 

Solution

def calc(board):
    max_sum = 0
    for i in range(100):
        sum_num = sum(board[i][:])  # 0~99 인덱스의 전체 합 구하기
        max_sum = max(sum_num, max_sum)  # 합계의 최댓값 구하기
    return max_sum

def diagonal(board):
    right_sum, left_sum = 0, 0
    for i in range(100):
        right_sum += board[i][i]  # 오른 대각
        left_sum += board[i][99 - i]  #왼 대각
    return max(right_sum, left_sum)

for _ in range(10):
    test_case = int(input())
    board = [list(map(int, input().split())) for _ in range(100)]
    row_max = calc(board)  # 행의 합
    # 행 열 변환 후 열의 합
    new_board = list(map(list, zip(*board)))
    col_max = calc(new_board)
    # 대각선 최댓값
    dia_max = diagonal(board)
    result = max(row_max, col_max, dia_max)
    print(f"#{test_case} {result}")

 

코드의 효율성과 가독성 문제 때문에 다음과 같이 수정한다.

 

수정 포인트

  • calc 함수에서 전체 합 계산 방식 단순화
    • sum(board[i][:]) 대신 sum(board[i])로도 같은 효과를 얻을 수 있다. 리스트의 전체를 대상으로 슬라이싱 [:]을 사용하는 대신, 리스트 자체를 sum에 전달해도 무방하다.
  • diagonal 함수의 중복된 max 구문 제거
    • 현재 대각선의 합 중 큰 값을 반환하는 부분에서 max 함수를 사용하고 있다. 하지만 호출부에서 이미 최대값을 비교하고 있으므로 diagonal 함수는 두 대각선의 합을 구하기만 하고, result = max(row_max, col_max, right_sum, left_sum)로 최대값을 결정할 수 있.
  • 주석을 추가하여 코드 가독성 향상
    • 각 섹션에 대해 명확한 주석을 달면 가독성을 높일 수 있다.
  • 최종적으로 최대값을 반환할 때 대각선 합의 두 가지 값을 명시적으로 전달
    • diagonal 함수가 두 값을 반환하게 변경하고, 호출부에서 최종 max 비교를 할 수 있도록 한다.

 

 

최적화된 코드

def calc(board):
    max_sum = 0
    # 각 행의 합을 계산하여 최대값 찾기
    for i in range(100):
        sum_num = sum(board[i])  # 각 행의 합 구하기
        max_sum = max(sum_num, max_sum)  # 현재 행 합계와 최대값 비교
    return max_sum

def diagonal(board):
    right_sum, left_sum = 0, 0
    # 오른쪽 대각선과 왼쪽 대각선의 합을 구하기
    for i in range(100):
        right_sum += board[i][i]          # 오른쪽 대각선
        left_sum += board[i][99 - i]      # 왼쪽 대각선
    return right_sum, left_sum

# 테스트 케이스 실행
for _ in range(10):
    test_case = int(input())
    board = [list(map(int, input().split())) for _ in range(100)]

    # 행의 최대 합
    row_max = calc(board)
    # 행과 열을 변환한 새로운 배열을 이용하여 열의 최대 합
    col_max = calc(list(map(list, zip(*board))))
    # 대각선의 두 합
    right_sum, left_sum = diagonal(board)

    # 모든 최대값 중 가장 큰 값
    result = max(row_max, col_max, right_sum, left_sum)
    print(f"#{test_case} {result}")

 

 

👩‍💻 회고

데이터가 너무 많은 거 빼고는 쉽게 풀 수 있었다. 각자 함수를 따로 나눠서 계산해서 보기에도 편한 것 같다.

가독성과 불필요한 코드가 조금 들어가 있었지만 꽤 잘 푼 것 같다.