본문 바로가기

IT 공부/코딩테스트

[프로그래머스 level1] 대충 만든 자판 python3

문제

입출력 예1)

keymap = ["ABACD", "BCEFD"] 총 자판이 2개가 있고 이 자판으로 targets의 문자열을 만들면 되는 문제이다.

(예전 2D폰의 자판 생각하자)

 

그런데, keymap의 자판중"ABACD"같은 경우는 A가 총 2번 나오니까 targets의 "ABCD"를 만들려면 둘 중 하나를 써야 한다.

문제에서는 최솟값을 출력하라고 했으니 처음 A, 즉 1번 누른 것이 3번 누른 것보다 더 적게 누르게 되니, 첫번째 A를 사용하면 되고,

 

자판이 다른 경우 즉 "ABACD"와 "BCEFD"에서 B는 두 자판에 둘 다 있기 때문에 둘 중에 하나를 써야 한다.

첫번째 자판은 B를 쓰려면 자판을 2번 눌러야하고, 두번째 자판은 B를 쓰려면 자판을 1번 눌러야하기 때문에

2번째 자판을 사용하는 것이 이득이다.

 

그래서 다 더한 값을 출력하면 된다.


풀이

1. 먼저 keymap의 자판 중 어떤 문자를 사용할 것인지를 판별한다.

- 1.1) 자판을 새로 만든다. (new_key)

 

- 1.2) 먼저 "ABACD"의 각 문자에 접근한다.

for key in keymap:

    for i, k in enumerate(key):

- 1.3) 각 문자(k)가 new_key안에 없으면

if k not in new_key:

문자를 new_key에 넣어준다. 이때, 리스트로 할지 딕셔너리로 할지 고민이 되었는데, 결국 문자에 해당하는 인덱스값이 필요하기 때문에 딕셔너리를 이용하여

new_key = {} 맨 앞에 선언

문자key값으로 인덱스 + 1value값(0번째 인덱스는 1번 클릭한걸로 간주)으로 new_key를 딕셔너리로 초기화해주었다. (ex) {'A': 1}이런 식으로 저장되도록)

new_key[k] = i+1

 

- 1.4) 만약에 각 문자가 new_key 딕셔너리 안에 있으면

else: 1.3번의

각 문자(k)가 가지고 있는 value값과 각 문자(k)의 인덱스 + 1값과 비교하여 기존의 new_key[k]가 더 작으면 그걸 쓰고, 아니면 그 값을 인덱스 + 1로 초기화해준다.

if new_key[k] > i+1 :
    new_key[k] = i+1

else:

    pass

 

최종 new_key => {'A':1, 'B':1, 'C':2, 'D':5, 'E':3, 'F':4}

2. 판별된 문자가 targets에 쓰인다면 result에 1을 더해주고, 쓰이지 않는다면 result값을 -1로 초기화해주고 for문을 빠져나온다.

- 2.1) targets 각 문자 하나하나에 일단 접근한다.("ABCD" -> 'A', 'B', 'C', 'D')

for target in targets:

    for t in target:

- 2.2) 접근한 문자가 new_key의 key값으로 있다면 result에 1을 더하고 반복문을 계속 실행한다.

result = 0 맨 처음 정의부분에 선언

...(생략)

if k in new_key:

    result += 1

- 2.3) 접근한 문자가 new_key의 key값으로 있지 않다면 result를 -1로 초기화하고 for문을 멈춘다.(다음 target으로 넘어가든지 끝이든지)

else: (2.2의 if문)

    result = -1

    break

-2.4) target이 바뀌기 전에 최종값인 result_list에 result값을 넣어준다.

result_list.append(result)

-2.5) result_list 값을 return 한다. 

return result_list

def solution(keymap, targets):
    new_key = {}
    result = 0
    result_list = []
    for key in keymap:
        for i, k in enumerate(key):
            if k not in new_key:
                new_key[k] = i+1
            else:
                if new_key[k] > i+1:
                    new_key[k] = i+1
                else:
                    pass
            
    #자판 찍을 때 사용하는 코드
    for target in targets:
        for t in target:
            if t in new_key:
                result += new_key[t]
            else:
                result = -1
                break
        result_list.append(result)
        result = 0
    return result_list

나의 삽질

예를 들어 자판에 없는 값이 있는 경우와 있는 경우가 섞여있는 경우에는
keymap = ["QEHGMS", "WRQRJH", "AAABE", "RJGHHE"]

targets = ["QEQ", "GJR", "AAHH", "KHA"]

result = [4, 6, 8, -1]

result = -1인 상황에서 break를 해줘야 -1에서 더 더해지지 않고 return값에 -1이 들어가는데

break를 안해서 몇개는 통과하고 몇개는 통과하지 않았음.

해결 방법

1. 문제를 일단 다시 보면서 내가 빼먹은 예외사항은 없는지 파악했다.

2. 내가 쓴 코드가(위의 풀이로 보면 1번 2번) 다른 케이스를 줄 때 문제가 발생하지 않는지 각 변수들을 다 출력해보았다.

1번 즉, 어떤 자판을 쓸지에 대한 코드는 이상이 없어보였다. 그래서 2번의 코드에서 문제가 발생한다고 가정하고 하나하나 1번 반복할 때는 어떻게 되고, 2번 반복할 때는 어떻게 되고를 유심히 print를 찍으면서 관찰하였다.

3. 테스트케이스에 자판에 없는 값이 있는 경우와 있는 경우가 섞여있는 경우를 넣어서 내 출력값을 확인했는데 2번 코드에 에러가 났다.

4. 알고보니 반복문을 멈추질 않아서 result = -1이 되었음에도 반복문을 계속 실행하게 되어서 -1 + 5 이런식으로 되어서 문제가 발생했던 것.

5. 그래서 반복문을 멈추는 break를 사용해서 반복문을 멈춰주었다.