
내가 생각했을때 문제에서 원하는부분
첫째 줄엔 9개의 정수가 주어진다.
첫 번째 정수는 1번 키를 누르면 원래 자판에서 어떤 키를 누른 것처럼 동작하는지, 두 번째 정수는 2번 키를 누르면 원래 자판에서 어떤 키를 누른 것처럼 동작하는지...이런 식이다.
재석이는 *이랑 0은 쓸 수가 없다. #키는 망가지지 않았다.
두 번째 줄엔 소문자로 된 문자열이 주어진다. 길이는 100 문자를 넘지 않는다.
재석이의 메세지를 쓰기 위해 눌러야 하는 키를 출력한다.
내가 이 문제를 보고 생각해본 부분
입력 및 출력 준비 (Setup):
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedReader는 대량의 텍스트 데이터를 효율적으로 읽기 위해 사용된다.
여기서는 표준 입력(키보드 입력)에서 데이터를 읽어온다.
StringBuilder sb = new StringBuilder();
StringBuilder는 문자열을 효율적으로 조작(추가, 삭제 등)하기 위한 클래스이다.
많은 문자열을 이어 붙일 때 + 연산자 대신 사용하면 성능상 이점을 얻을 수 있다.
최종 출력할 결과 문자열을 여기에 저장한다.
물리적 키 -> 오리지널 키 매핑 정보 파싱:
int[] physicalToOriginalKey = new int[9];
physicalToOriginalKey 배열은 물리적인 키(1번부터 9번)를 눌렀을 때, 원래 어떤 키(1번부터 9번)처럼 작동하는지에 대한 정보를 저장한다.
배열의 인덱스는 물리적 키 번호 - 1 에 해당한다.
예를 들어, physicalToOriginalKey[0]의 값이 2라면, 물리적 1번 키를 누르면 원래 자판의 2번 키처럼 동작한다는 의미이다.
StringTokenizer st = new StringTokenizer(br.readLine());
첫 번째 줄에 공백으로 구분된 9개의 정수를 읽어와 StringTokenizer를 사용하여 각 정수를 분리한다.
for (int i = 0; i < 9; i++) { physicalToOriginalKey[i] = Integer.parseInt(st.nextToken()); }
분리된 각 문자열 토큰을 Integer.parseInt()를 통해 정수로 변환하여 physicalToOriginalKey 배열에 순서대로 저장한다.
문자 -> 오리지널 키 정보 매핑 (charMapping):
Map<Character, int[]> charMapping = new HashMap<>();
charMapping은 입력 메시지의 각 소문자가 원래 어떤 키 번호에 할당되어 있고, 그 키를 몇 번 눌러야 하는지에 대한 정보를 저장하는 HashMap이다.
key는 입력 메시지의 문자(예: 'a'), value는 int 배열로, [오리지널 키 번호, 눌러야 하는 횟수]를 가진다.
charMapping.put('a', new int[]{2, 1}); charMapping.put('b', new int[]{2, 2}); ...
알파벳 a부터 z까지를 오리지널 키 번호와 누르는 횟수에 따라 미리 매핑하여 저장해둔다.
이렇게 해두면 문자열을 처리할 때 각 문자에 해당하는 키 정보를 빠르게 조회할 수 있다.
입력 메시지 처리:
String message = br.readLine();
두 번째 줄에서 입력될 메시지 문자열을 읽어온다.
int previousPhysicalKey = -1;
이전에 눌렀던 물리적 키 번호를 저장하는 변수이다.
첫 문자 처리 시에는 비교할 이전 키가 없으므로 -1로 초기화한다.
for (char c : message.toCharArray()) { ... }
메시지 문자열을 char 배열로 변환하여 각 문자에 대해 반복 작업을 수행한다.
int[] originalKeyInfo = charMapping.get(c);
현재 처리 중인 문자 c에 대한 오리지널 키 정보를 charMapping에서 가져온다.
이 정보는 [targetOriginalKey, pressCount] 형태이다.
int targetOriginalKey = originalKeyInfo[0];
해당 문자를 입력하기 위해 눌러야 하는 오리지널 키 번호이다.
int pressCount = originalKeyInfo[1];
해당 오리지널 키를 눌러야 하는 횟수이다.
오리지널 키 -> 물리적 키 변환:
int currentPhysicalKey = -1;
현재 문자를 입력하기 위해 눌러야 할 물리적 키 번호를 저장할 변수이다.
for (int i = 0; i < 9; i++) { if (physicalToOriginalKey[i] == targetOriginalKey) { currentPhysicalKey = i + 1; break; } }
physicalToOriginalKey 배열을 순회하면서, targetOriginalKey (현재 문자에 해당하는 오리지널 키)와 일치하는 값이 있는 인덱스 i를 찾는다.
이때 i + 1이 실제 눌러야 할 물리적 키 번호가 된다 (배열 인덱스는 0부터 시작하기 때문).
해당 키를 찾으면 더 이상 찾을 필요가 없으므로 break로 루프를 빠져나온다.
# 삽입 로직:
if (previousPhysicalKey != -1 && previousPhysicalKey == currentPhysicalKey) { sb.append('#'); }
이전 문자가 있었고 (previousPhysicalKey != -1), 이전 문자를 입력할 때 사용했던 물리적 키와 현재 문자를 입력할 때 사용해야 할 물리적 키가 동일하다면, #을 StringBuilder에 추가한다.
이 #은 같은 키를 연속으로 누르는 경우 문자를 구분해주는 역할을 한다.
결과 문자열에 물리적 키 추가:
for (int i = 0; i < pressCount; i++) { sb.append(currentPhysicalKey); }
currentPhysicalKey (현재 문자에 해당하는 물리적 키)를 pressCount 횟수만큼 StringBuilder에 추가한다.
이전 물리적 키 저장:
previousPhysicalKey = currentPhysicalKey;
현재 물리적 키를 다음 반복을 위한 previousPhysicalKey로 저장한다.
최종 출력 및 마무리:
System.out.println(sb.toString());
모든 문자에 대한 처리가 끝나면, StringBuilder에 저장된 최종 키 시퀀스를 문자열로 변환하여 출력한다.
br.close();
BufferedReader를 닫아 자원을 해제한다.
코드로 구현
package baekjoon.baekjoon_32;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
// 백준 10545번 문제
public class Main1267 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
// 1. 물리적 키 -> 오리지널 키 매핑 정보 파싱
// index i는 물리적 키 번호 (0-8) -> value는 오리지널 키 번호
// 예를 들어 physicalKeyMap[0] = 2는 물리적 1번 키를 누르면 오리지널 2번 키처럼 작동
int[] physicalToOriginalKey = new int[9];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < 9; i++) {
physicalToOriginalKey[i] = Integer.parseInt(st.nextToken());
}
// 2. 문자 -> 오리지널 키 정보 매핑
// key: 문자, value: {오리지널 키 번호, 눌러야 하는 횟수}
Map<Character, int[]> charMapping = new HashMap<>();
charMapping.put('a', new int[]{2, 1}); charMapping.put('b', new int[]{2, 2}); charMapping.put('c', new int[]{2, 3});
charMapping.put('d', new int[]{3, 1}); charMapping.put('e', new int[]{3, 2}); charMapping.put('f', new int[]{3, 3});
charMapping.put('g', new int[]{4, 1}); charMapping.put('h', new int[]{4, 2}); charMapping.put('i', new int[]{4, 3});
charMapping.put('j', new int[]{5, 1}); charMapping.put('k', new int[]{5, 2}); charMapping.put('l', new int[]{5, 3});
charMapping.put('m', new int[]{6, 1}); charMapping.put('n', new int[]{6, 2}); charMapping.put('o', new int[]{6, 3});
charMapping.put('p', new int[]{7, 1}); charMapping.put('q', new int[]{7, 2}); charMapping.put('r', new int[]{7, 3}); charMapping.put('s', new int[]{7, 4});
charMapping.put('t', new int[]{8, 1}); charMapping.put('u', new int[]{8, 2}); charMapping.put('v', new int[]{8, 3});
charMapping.put('w', new int[]{9, 1}); charMapping.put('x', new int[]{9, 2}); charMapping.put('y', new int[]{9, 3}); charMapping.put('z', new int[]{9, 4});
// 3. 입력 메시지 처리
String message = br.readLine();
int previousPhysicalKey = -1; // 이전 물리적 키를 저장, 초기값은 없는 키로 설정
for (char c : message.toCharArray()) {
// 현재 문자의 오리지널 키 정보 가져오기
int[] originalKeyInfo = charMapping.get(c);
int targetOriginalKey = originalKeyInfo[0]; // 문자가 매핑된 오리지널 키 번호
int pressCount = originalKeyInfo[1]; // 오리지널 키를 눌러야 하는 횟수
// 오리지널 키 번호에 해당하는 물리적 키 번호를 찾기
int currentPhysicalKey = -1;
for (int i = 0; i < 9; i++) {
if (physicalToOriginalKey[i] == targetOriginalKey) {
currentPhysicalKey = i + 1; // 인덱스 + 1이 물리적 키 번호
break;
}
}
// 이전 물리적 키와 현재 물리적 키가 같으면 '#' 추가
if (previousPhysicalKey != -1 && previousPhysicalKey == currentPhysicalKey) {
sb.append('#');
}
// 현재 물리적 키를 필요한 횟수만큼 추가
for (int i = 0; i < pressCount; i++) {
sb.append(currentPhysicalKey);
}
// 이전 물리적 키 저장
previousPhysicalKey = currentPhysicalKey;
}
System.out.println(sb.toString());
br.close();
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.