programmers.co.kr/learn/courses/30/lessons/42860
문제 설명
조이스틱으로 알파벳 이름을 완성하세요. 맨 처음엔 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 |
※ 공지 - 2019년 2월 28일 테스트케이스가 추가되었습니다.
♠ 나의 풀이
# 실패
import string
uppercase=list(string.ascii_uppercase)
def calculation(name, answer) :
idx=uppercase.index(name)
if 13 < idx : # 아래로 움직이기
answer+=(26-idx)
elif idx != 0 : # 위로 움직이기
answer+=idx
return answer
def solution(name):
answer = 0
size=len(name)
make_name="A" * size
for i in range(1, size-1) :
answer=calculation(name[i], answer)
answer += 1 # 방향키
if answer == size-2 : # 가운데에 A만 있음
answer-=1
answer=calculation(name[0], answer)
answer=calculation(name[-1], answer)
return answer+1 # 조작 횟수의 최솟값
가운데랑 처음, 끝은 따로 계산
# 3, 4, 5, 7, 11 실패 = 총점 54.5
def solution(name):
answer = 0
length=len(name)
alpha=['A']*length
direction=[1, -1, -1, 1]
position=[i for i, j in enumerate(name) if j != 'A']
for i in range(length):
if name[i] == 'A':
continue
desc=abs(ord('Z')-ord(name[i]))+1
asc=abs(ord('A')-ord(name[i]))
#print(desc, asc)
if asc < desc :
answer+=asc
else:
answer+=desc
#desc=abs(ord('Z')-ord(n))
return answer+len(position)-1
문제 자체를 이해못했음.
테스트케이스의 "JEROEN"이 56이 나오는게 이해안됨ㅋ
"JEROEN"= 51, 기댓값은 56
J=9
E=4
R=9
O=12
E=4
N=13
그 다음 알파벳으로 이동하니까 51+5=56
# 모르겠는 것
커서를 왼쪽으로 이동하는 경우를 구해야함.
목표 위치까지의 거리를 계산한다(앞뒤로).
🗝 다른사람 풀이
def solution(name):
if set(name) == {'A'} :
return 0
answer=float('inf')
for i in range(len(name) // 2) : # 반 이상 움직일 필요 없음
left_moved=name[-i:] + name[:-i]
right_moved=name[i:] + name[:i]
for n in [left_moved, right_moved[0] + right_moved[:0:-1]] :
while n and n[-1] == 'A' :
n=n[:-1]
row_move=i+len(n)-1
col_move=0
for c in map(ord, n) :
col_move += min(c-65, 91-c)
answer=min(answer, row_move + col_move)
return answer
모두 A로 이루어진 경우 0을 바로 리턴해준다는 점을 주의하자.
1) left_moved='JEROEN'
right_moved='JEROEN'
right_moved[:0:-1]='NEORE'은 0번째 인덱스를 제외하고 거꾸로 뒤집은 것
n='JEROEN'
row_move는 방향키 이동 횟수
col_move에 a에서 시작했을 때와 z에서 시작했을 때 둘중에 차이가 더 작은 값을 더한다.
1-1) n='JNEORE'
2) left_moved='NJEROE'
right_moved='EROENJ'
n='NJEROE'
row_move=6
2-1) n='EJNEOR'
row_move=6
left_moved는 인덱스 0에서 왼쪽으로 가는 것
right_moved는 인덱스 0에서 오른쪽으로 가는 것
출발점의 방향이다.
while n and n[-1] == 'A'는 'A'를 제외시키는 부분이다.
'A'가 있는 곳은 바꿀 필요가 없으니까
row_move에 i를 더하는 이유는 인덱스 0이 아닌 다른 위치에서 시작하는 방향키 이동 횟수
'JEROEN'같은 경우는
left_moved | right_moved | right_moved[0] + right_moved[:0:-1] |
JEROEN | JEROEN | JNEORE |
NJEROE | EROENJ | EJNEOR |
ENJERO | ROENJE | REJNEO |
right_moved[0] + right_moved[:0:-1]은 <- 방향
문제 출처 👉 프로그래머스
'coding test' 카테고리의 다른 글
[파이썬] 4831. 전기버스 (0) | 2021.01.04 |
---|---|
[파이썬] 풍선 터트리기 (0) | 2021.01.04 |
[파이썬, Java] 다리를 지나는 트럭 (0) | 2020.12.28 |
[파이썬] 약수의 합 (0) | 2020.12.24 |
[파이썬] 이진 변환 반복하기 (0) | 2020.12.24 |