Better Code, Better Life

조이스틱 - 프로그래머스 - 파이썬 풀이 본문

Coding Test/Programmers

조이스틱 - 프로그래머스 - 파이썬 풀이

심재훈 2020. 8. 5. 09:10

문제 풀이

  1. 먼저 up, down으로 움직일 조이스틱 횟수를 구합니다.
    1. initial_codes 를 이름의 길이만큼 모두 65로 초기화합니다. ("A"의 유니코드값: 65)
    2. name_in_codes 에 이름의 유니코드값을 저장합니다.
    3. "A" 기준으로 이름을 완성하기 위해 필요한 up, down 횟수만을 구합니다. (get_up_down_shortest_moves)
  2. left, right으로 움직일 조이스틱 횟수를 구합니다.
    1. index_diffs: 이름에서 "A"가 아닌 index는 모두 방문해야 합니다.
    2. index_diffs: [0, 2, 5, 9], name_length: 10일때
      • 총 7번으로 모두 방문 할 수 있습니다. (좌-우우우-우우우)
      • 단순히 오른쪽으로만 가면 총 8번을 움직여야 합니다. (우우-우우우-우우우우)
      • 그 순간마다 제일 가까운 index를 찾아가는 그리디 알고리즘을 통해 해결합니다.
  3. 1, 2번에서 움직인 횟수를 합치면 답이 나옵니다.

클린 코드 작성법

  1. 문제해결을 위해 로직을 나눠주면 이해하기 편합니다. (up_down, left_right)

  2. zip을 이용해 동일한 길이의 리스트를 index 없이 순회할 수 있습니다.
    for name_code, initial_code in zip(name_in_codes, initial_codes):

  3. 변수의 의미를 명시화합니다.
    alphabetic_order_moves, reverse_alphabetic_order_moves, current, destination

해답 코드

from collections import deque

def solution(name):
    name_length = len(name)
    initial_codes = [ord("A")]*name_length
    name_in_codes = []
    for chr_ in name:
        name_in_codes.append(ord(chr_))
    moves = 0
    moves += get_up_down_shortest_moves(initial_codes, name_in_codes)
    index_diffs = get_index_diffs(initial_codes, name_in_codes)
    moves += get_left_right_shortest_moves(index_diffs, name_length)
    return moves

def get_up_down_shortest_moves(initial_codes, name_in_codes):
    up_down_moves = 0
    for name_code, initial_code in zip(name_in_codes, initial_codes):
        alphabetic_order_moves = abs(name_code - initial_code)
        reverse_alphabetic_order_moves = abs(name_code - initial_code - 26)
        up_down_moves += min(alphabetic_order_moves, reverse_alphabetic_order_moves)
    return up_down_moves

def get_index_diffs(initial_codes, name_in_codes):
    index_diffs = []
    for index, code in enumerate(name_in_codes):
        if name_in_codes[index] != initial_codes[index]:
            index_diffs.append(index)
    return deque(index_diffs)

def get_left_right_shortest_moves(index_diffs, name_length):
    current = 0
    left_right_moves = 0
    while index_diffs:
        forward_index = index_diffs[0]
        backward_index = index_diffs[-1]
        forward_length = get_short_path(current, forward_index, name_length)
        backward_length = get_short_path(current, backward_index, name_length)
        if forward_length <= backward_length:
            current = forward_index
            left_right_moves += forward_length
            index_diffs.popleft()
        else:
            current = backward_index
            left_right_moves += backward_length
            index_diffs.pop()
    return left_right_moves

def get_short_path(current, destination, name_length):
    if destination < current:
        current, destination = destination, current
    right_path = destination - current
    left_path = current + name_length - destination
    return min(right_path, left_path)

 

도움이 됐다면 공감버튼을 눌러주세요! 질문이 있다면 댓글 달아주세요!

 

문제 링크

 

코딩테스트 연습 - 조이스틱

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다. ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA 조이스틱을 각 방향으로 움직이면 아래와 같습니다. ▲ - 다

programmers.co.kr

 

Comments