본문 바로가기
Study/Algorithm & Data structure

[프로그래머스][greedy] 조이스틱 (201020)

by 후이 (hui) 2020. 10. 20.
728x90
반응형

1. 문제설명 

programmers.co.kr/learn/courses/30/lessons/42860

 

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

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

programmers.co.kr

 

 

조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 A로만 이루어져 있습니다.
ex) 완성해야 하는 이름이 세 글자면 AAA, 네 글자면 AAAA

 

조이스틱을 각 방향으로 움직이면 아래와 같습니다.

▲ - 다음 알파벳 ▼ - 이전 알파벳 (A에서 아래쪽으로 이동하면 Z로) ◀ - 커서를 왼쪽으로 이동 (첫 번째 위치에서 왼쪽으로 이동하면 마지막 문자에 커서) ▶ - 커서를 오른쪽으로 이동

 

예를 들어 아래의 방법으로 JAZ를 만들 수 있습니다.

- 첫 번째 위치에서 조이스틱을 위로 9번 조작하여 J를 완성합니다.

- 조이스틱을 왼쪽으로 1번 조작하여 커서를 마지막 문자 위치로 이동시킵니다.

- 마지막 위치에서 조이스틱을 아래로 1번 조작하여 Z를 완성합니다. 따라서 11번 이동시켜 "JAZ"를 만들 수 있고, 이때가 최소 이동입니다.

 

만들고자 하는 이름 name이 매개변수로 주어질 때, 이름에 대해 조이스틱 조작 횟수의 최솟값을 return 하도록 solution 함수를 만드세요.

 

제한 사항

  • name은 알파벳 대문자로만 이루어져 있습니다.
  • name의 길이는 1 이상 20 이하입니다.

입출력 예

name        return

JEROEN 56
JAN 23

 

 

 

2. 풀이 

 

1) 나의 화려한 오답 

alpha_list = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")

def get_alpha_gap(x1, x2):
    index_gap = abs(alpha_list.index(x1) - alpha_list.index(x2))
    if index_gap > 13:
        index_gap = abs(index_gap - 26)
    return index_gap

def solution(name):
    total_cnt = 0
    len_str = len(name)
    name = list(name)
    last_point = 0
    total_cnt_list = []

    for idx, chk_tok in enumerate(name):
        if chk_tok == 'A':
            continue
        else:
            if idx == 0 :
                button_cnt = (get_alpha_gap('A', chk_tok))
            else:
                idx_gap = abs(idx - last_point)
                if idx_gap > (len_str // 2):
                    idx_gap = abs(idx_gap - len_str)
                button_cnt = (get_alpha_gap('A', chk_tok) + idx_gap)
            if button_cnt > 0:
                total_cnt_list.append(button_cnt)
                last_point = idx
            
                
    return sum(total_cnt_list)

 

우선 좌에서 우만 탐색을 하는 접근 자체가 잘못된거 같다. 

가령 변경 순서가 엉키는 경우 (5번째 글자를 먼저 고쳐주고 3번째를 고치는게 더 빠른경우가 있을수 있는데 이 경우를 간과했음) 

따라서 좌 우를 동시에 살피는 방법이 필요하다. 

 

 

2) 다른 사람 풀이 참고 

 

gurumee92.tistory.com/182

 

프로그래머스 문제 풀이 조이스틱

문제 URL 조이스틱 Contents 문제 지문 파악하기 구르미의 알고리즘 풀이 문제 지문 파악하기 이번에도 문제의 입력을 통해서, 문제를 파악해보도록 하겠습니다. 다음은, 문제의 입력입니다. 입력:

gurumee92.tistory.com

def solution(name):
    # 1. 알파벳을 맞추는 최소 횟수를 저장하는 배열 m을 만듭니다.
    m = [ min(ord(c) - ord("A"), ord("Z") - ord(c) + 1)  for c in name  ]
    answer = 0
    where = 0

    # 2. 위치 where를 0부터 시작해서, 다음을 반복합니다.
    while True:
        # 1. m[where]를 answer에 더합니다
        answer += m[where]
        # 2. m[where]를 0으로 만듭니다.
        m[where] = 0
        
        # 3. 만약, 현재 m이 모두 0이라면, 반복을 멈춥니다.
        if sum(m) == 0:
            break
        
        # 4. 3이 만족하지 않을 때, left, right를 1로 만듭니다.
        left, right = (1, 1)
        
        # 5. m[where-left] <= 0일 때까지, left를 1씩 증가시킵니다.
        while m[where - left] <= 0:
            left += 1
            
        # 6. m[where+right] <= 0일 때까지 right를 1씩 증가시킵니다.            
        while m[where + right] <= 0:
            right += 1
        
        # 7. left, right를 비교합니다.
        # 7-1. left < right 라면, answer에 left를 더하고, where에 -left를 더합니다.
        # 7-2. 반대라면, answer에 right를 더하고 where에 right를 더합니다.
        answer += left if left < right else right
        where += -left if left < right else right
            
    return answer

 

728x90
반응형

댓글