알고리즘 문제 풀이/Python

python 백준 2469 사다리 타기

맛대 2024. 7. 10. 17:03

https://www.acmicpc.net/problem/2469

로직

  • 구현문제
  • 모르는 줄(?????)을 기준으로 그 위에선 어떻게 진행되는지, 그 아레에선 어떻게 진행되는지 계산(check함수)
    • 사다리의 정보를 기준으로 이동을 기록
    • 예를들어 [A,B,C,D] 로 출발하여 [B,A,C,D] 로 완성될 경우 [1,0,2,3] 으로 기록됨
    • [1,0,2,3]의 경우 0번 인덱스가 1번으로, 1번 인덱스 0번으로, 2,3번은 그대로를 의미
  • 이렇게 위 아래를 계산 후 col이 0번부터 현재 사다리에 가로막대가 없을 경우 값을 계산
    • 계산된 값이 결과와 다르면 사다리가 있어야함을 의미
    • 이 때 사다리가 있을 경우 +1번과 자리가 변경됨
    • 전에 이동이 필요해서 -를 두었는데, 또 이동이 필요한 경우 해당 문제에선 불가능한 경우의 수
def check(arr:list[str])->list[int]:
  R,C = len(arr)+1,len(arr[0])+1
  process = [-1]*C
  for i in range(C):
    process[i] = i

  for r in range(R-1):
    for c in range(C-1):
      if arr[r][c] == '*':
        continue
      process[c],process[c+1] = process[c+1],process[c]
  return process

def solution(k:int,n:int,result:str,arr:list[str])->str:
  result = list(map(lambda x: ord(x)-65,result))
  value = ''
  for i in range(n):
    if arr[i][0] == '?':
      if i == 0: process1 = list(range(k))
      else:process1 = check(arr[:i])
      if i != n-1: process2 = check(arr[i+1:])
      else: process2 = list(range(k))
      break
  dictProcess2 = dict()
  for i in range(k):
    dictProcess2[process2[i]] = i

  for i in range(k-1):
    if process1[i] != result[dictProcess2[i]]:
      if value and value[-1] == '-':
        return 'x'*(k-1)
      process1[i],process1[i+1] = process1[i+1],process1[i]
      value += '-'
    else:
      value += '*'
  return value

k = int(input())
n = int(input())
result = input()
arr = [input() for _ in range(n)]
ans = solution(k,n,result,arr)
print(ans)

chatGPT-4o 분석

질문 내용

  • 내가 알고리즘 문제를 풀었는데 이에 대한 코드리뷰가 필요해
  • 문제 주소는 다음과 같아 https://www.acmicpc.net/problem/2469
  • 그리고 이에 대한 나의 답변 코드는 아래와 같아

답변

코드 리뷰를 진행하기 전에, 문제를 간단히 요약하겠습니다. 문제는 알파벳이 주어지고, *와 -로 이루어진 사다리 타기를 통해 그 결과를 도출하는 것입니다. 주어진 사다리의 중간에 ?가 있는 상태에서 최종 결과를 얻기 위한 ?의 구성을 찾아야 합니다.

코드 리뷰

1.    입출력 부분:
•    k, n을 입력 받고, result와 arr 리스트를 입력받는 부분은 문제 없이 잘 구현되어 있습니다.
2.    함수 check:
•    사다리 타기를 시뮬레이션하여 최종 위치를 계산하는 역할을 잘 수행하고 있습니다.
•    코드의 가독성을 위해 변수명을 더 명확히 할 수 있습니다. 예를 들어, process 대신 positions와 같은 이름을 사용하는 것이 좋습니다.
3.    함수 solution:
•    문제의 요구사항을 잘 반영하여 해결하고 있습니다.
•    process1과 process2를 계산하는 부분에서 사다리를 분할하여 처리하는 로직이 잘 작성되어 있습니다.
•    최종 결과를 계산하는 부분에서도 논리적으로 잘 처리되고 있습니다.

제안된 수정 및 최적화

•    변수명 개선: 가독성을 높이기 위해 의미 있는 이름을 사용합니다.
•    불필요한 연산 줄이기: dictProcess2를 굳이 딕셔너리로 만들 필요 없이 리스트로 처리해도 좋습니다.
•    주석 추가: 주요 부분에 주석을 달아 코드의 의도를 명확히 합니다.
def check(ladder: list[str]) -> list[int]:
    R, C = len(ladder) + 1, len(ladder[0]) + 1
    positions = list(range(C))

    for r in range(R - 1):
        for c in range(C - 1):
            if ladder[r][c] == '*':
                continue
            positions[c], positions[c + 1] = positions[c + 1], positions[c]
    return positions

def solution(k: int, n: int, result: str, ladder: list[str]) -> str:
    result_positions = list(map(lambda x: ord(x) - 65, result))
    solution_str = ''

    for i in range(n):
        if ladder[i][0] == '?':
            if i == 0:
                process_before = list(range(k))
            else:
                process_before = check(ladder[:i])
            if i != n - 1:
                process_after = check(ladder[i + 1:])
            else:
                process_after = list(range(k))
            break

    final_positions = {pos: idx for idx, pos in enumerate(process_after)}

    for i in range(k - 1):
        if process_before[i] != result_positions[final_positions[i]]:
            if solution_str and solution_str[-1] == '-':
                return 'x' * (k - 1)
            process_before[i], process_before[i + 1] = process_before[i + 1], process_before[i]
            solution_str += '-'
        else:
            solution_str += '*'

    return solution_str

# 입력 부분
k = int(input())
n = int(input())
result = input()
ladder = [input() for _ in range(n)]
ans = solution(k, n, result, ladder)
print(ans)

주요 변경 사항

1.    변수명을 직관적으로 변경 (arr -> ladder, process -> positions, dictProcess2 -> final_positions).
2.    process_before와 process_after에서 중복되는 부분을 처리하여 가독성을 높임.
3.    최종 위치를 리스트 대신 딕셔너리로 간단하게 매핑하여 처리.
4.    주요 로직에 주석을 추가하여 가독성을 높임.