본문 바로가기
프로그래머스 코딩테스트 문제/Level 1

[프로그래머스] - 대충 만든 자판(C#)

by jyppro 2023. 9. 16.

대충 만든 자판

오늘은 "대충 만든 자판" 문제를 풀어보도록 하겠습니다. 이번 문제의 정답률은 53%입니다.

 

문제 설명

휴대폰의 자판은 컴퓨터 키보드 자판과는 다르게 하나의 키에 여러 개의 문자가 할당될 수 있습니다. 키 하나에 여러 문자가 할당된 경우, 동일한 키를 연속해서 빠르게 누르면 할당된 순서대로 문자가 바뀝니다.

예를 들어, 1번 키에 "A", "B", "C" 순서대로 문자가 할당되어 있다면 1번 키를 한 번 누르면 "A", 두 번 누르면 "B", 세 번 누르면 "C"가 되는 식입니다.

같은 규칙을 적용해 아무렇게나 만든 휴대폰 자판이 있습니다. 이 휴대폰 자판은 키의 개수가 1개부터 최대 100개까지 있을 수 있으며, 특정 키를 눌렀을 때 입력되는 문자들도 무작위로 배열되어 있습니다. 또, 같은 문자가 자판 전체에 여러 번 할당된 경우도 있고, 키 하나에 같은 문자가 여러 번 할당된 경우도 있습니다. 심지어 아예 할당되지 않은 경우도 있습니다. 따라서 몇몇 문자열은 작성할 수 없을 수도 있습니다.

이 휴대폰 자판을 이용해 특정 문자열을 작성할 때, 키를 최소 몇 번 눌러야 그 문자열을 작성할 수 있는지 알아보고자 합니다.

1번 키부터 차례대로 할당된 문자들이 순서대로 담긴 문자열배열 keymap과 입력하려는 문자열들이 담긴 문자열 배열 targets가 주어질 때, 각 문자열을 작성하기 위해 키를 최소 몇 번씩 눌러야 하는지 순서대로 배열에 담아 return 하는 solution 함수를 완성해 주세요.

단, 목표 문자열을 작성할 수 없을 때는 -1을 저장합니다.

 

제한사항

  • 1 ≤ keymap의 길이 ≤ 100
  • 1 ≤ keymap의 원소의 길이 ≤ 100
  • keymap[i]는 i + 1번 키를 눌렀을 때 순서대로 바뀌는 문자를 의미합니다.
  • 예를 들어 keymap[0] = "ABACD" 인 경우 1번 키를 한 번 누르면 A, 두 번 누르면 B, 세 번 누르면 A 가 됩니다.
  • keymap의 원소의 길이는 서로 다를 수 있습니다.
  • keymap의 원소는 알파벳 대문자로만 이루어져 있습니다.
  • 1 ≤ targets의 길이 ≤ 100
  • 1 ≤ targets의 원소의 길이 ≤ 100
  • targets의 원소는 알파벳 대문자로만 이루어져 있습니다.

 

입출력 예

keymap targets result
["ABACD", "BCEFD"] ["ABCD", "AABB"] [9, 4]
["AA"] ["B"] [-1]
["AGZ", "BSSS"] ["ASA", "BGZ"] [4, 6]

 

입출력 예 설명

입출력 예 #1
"ABCD"의 경우,
1번 키 한 번 → A
2번 키 한 번 → B
2번 키 두 번 → C
1번 키 다섯 번 → D
따라서 총합인 9를 첫 번째 인덱스에 저장합니다.
"AABB"의 경우,
1번 키 한 번 → A
1번 키 한 번 → A
2번 키 한 번 → B
2번 키 한 번 → B
따라서 총합인 4를 두 번째 인덱스에 저장합니다.
결과적으로 [9,4]를 return 합니다.


입출력 예 #2
"B"의 경우, 'B'가 어디에도 존재하지 않기 때문에 -1을 첫 번째 인덱스에 저장합니다.
결과적으로 [-1]을 return 합니다.


입출력 예 #3
"ASA"의 경우,
1번 키 한 번 → A
2번 키 두 번 → S
1번 키 한 번 → A
따라서 총합인 4를 첫 번째 인덱스에 저장합니다.
"BGZ"의 경우,
2번 키 한 번 → B
1번 키 두 번 → G
1번 키 세 번 → Z
따라서 총합인 6을 두 번째 인덱스에 저장합니다.
결과적으로 [4, 6]을 return 합니다.

 

시작 코드

using System;

public class Solution {
    public int[] solution(string[] keymap, string[] targets) {
        int[] answer = new int[] {};
        return answer;
    }
}

 

나의 풀이

public class Solution {
    public int[] solution(string[] keymap, string[] targets) {
        int[] answer = new int[targets.Length];
        int sum = 0;
        int count = 0;
        
        for(int i = 0; i < targets.Length; i++)
        {
            for(int j = 0; j < targets[i].Length; j++)
            {
                count = press(keymap, targets[i][j]);
                if(count == -1)
                {
                    sum = -1;
                    break;
                }
                sum += count;
            }
            answer[i] = sum;
            sum = 0;
        }
        return answer;
    }
    
    public int press(string[] keymap, char ch)
    {
        int min = -1;
        
        for(int i = 0; i < keymap.Length; i++)
        {
            for(int j = 0; j < keymap[i].Length; j++)
            {
                if(keymap[i][j] == ch)
                {
                    if(min == -1) min = j + 1;
                    else if(min > j) min = j + 1;
                    break;
                }
            }
        }
        return min;
    }
}

 

코드 분석

string타입의 배열 keymap과 targets가 주어지며 코드가 시작됩니다. answer의 길이를 target의 길이로 지정해주고, int형 변수 sum과 count를 선언해 줍니다. 이후 이중 for문을 작성하게 되는데, for문을 살펴보기 전에 밑에 있는 함수 press를 살펴보겠습니다.

 

string타입의 배열 keymap과 char타입의 ch를 매개변수로 받고 int형으로 반환하는 함수입니다. int형으로 min을 -1로 초기화하여 선언하고 이중 for문 안에 if문과 if else문을 실행합니다. i = 0부터 keymap의 길이까지 실행하는 for문 안에 j = 0부터 keymap[i]의 길이까지 실행하는 for문 안에 keymap[i][j]과 ch를 비교하는 if문 안에 min이 -1이면 min에 j + 1을 넣고 그게 아니라 min이 j보다 크다면 똑같이 min에 j + 1을 넣어줍니다. 그리고 break문을 실행합니다. 모든 반복문을 빠져나오면 min을 리턴하면서 함수가 종료됩니다.

 

이제 위에 있는 코드를 살펴보면, 아래와 똑같이 이중for문을 작성하고, 그 안에 count에다가 press(keymap, targets[i][j])를 실행한 값을 넣어줍니다. 그리고 count가 -1이면 sum에 -1을 넣고 break를 해줍니다. 이후 sum에 count를 더해주고, for문을 빠져나오면 answer[i]에 sum을 넣고, sum을 0으로 만들어줍니다. 마지막 for문을 빠져나오면 answer값을 리턴하면서 코드가 끝이 납니다.

 

풀이 설명

문제에서 원하는 것은 keymap에 주어진 자판을 통해서 targets에 있는 문자를 만들기 위해 keymap을 몇번 눌러야 하는지를 리턴하는 것입니다. press함수부터 살펴보면, 매개변수로 keymap과 targets 원소의 문자를 넘겨주며 계산을 시작합니다. 넘겨준 단어와 일치하는 단어를 keymap에서 for문을 통해 찾고 누르는 횟수를 세는 동작을 press를 통해서 진행합니다. 그렇게 press에서 계산된 min을 count에 넘겨주고, 만약count가 -1 즉, 어떤 키로도 완성시킬 수 없는 단어라면 sum에 -1을 넣고, 이후 sum에 count를 누적시켜 줍니다. targets의 갯수에 따라 넘겨줘야 하는 answer의 갯수도 여러개가 될 수 있으므로, answer배열에 순서대로 완성된 sum을 넣어주고 sum을 0으로 초기화 시키는 작업을 여러 번 거쳐 완성된 answer값을 리턴해주면 됩니다.

 

<NEXT>

오늘은 "대충 만든 자판" 문제를 풀어보았습니다. 다음에는 "둘만의 암호" 문제를 다뤄보도록 하겠습니다. 감사합니다.