▼ What ?
이번에도 해결한 문제도 구현 - 시뮬레이션 유형의 문제이다.
▼ 좌석 번호
문제 정보
현수는 자신의 홍채 지문을 읽으면 비밀번호가 자동으로 입력되는 소프트웨어를 만들고 있습 니다. 이 소프트웨어는 1부터 9까지의 숫자가 3 * 3 격자모양으로 되어 있는 키패드에서 비밀번호의 순서대로 이동하면서 입력되는 방식입니다.
키패드의 숫자배치는 항상 변합니다.
소프트웨어는 비빌번호의 첫 숫자에서 시작하여 이웃한(상하좌우, 대각선) 8개의 방향으로 이동하면서 입력됩니다. 이웃한 번호로의 이동시간은 1초가 걸립니다. 그리고 이웃하지 않은 숫자로의 이동은 이웃한 숫자를 통해서 이동하는 형태를 취하며, 이웃한 숫자로 이동때마다 1초씩 걸립니다.
즉 키패드에 숫자가 아래와 같이 배치되고,
시작위치가 2라면 1, 3, 4, 5, 6 으로 이동은 1초가 걸리고, 시작위치 2에서 7, 8, 9로는 2초가 걸립니다. 물론 번호가 입력되는 시간은 무시합니다.
매개변수 keypad에 키패드의 숫자배열이이 주어지고, password에 입력해야 할 비밀번호가 주어지면 비밀번호가 모두 입력되는데 걸리는 총 시간을 반환하는 프로그램을 작성하세요.
제한 사항
- password의 길이는 200,000을 넘지 않습니다.
입출력 예
어떻게 해결해야 할까 ?
- 전에 "키패드" 문제에서 번호간의 거리를 미리 계산하고 이를 활용하여 해결했던 방식을 참고하면 될 것 같다
- 일단 키패드의 구조대로 1차원 배열 'keypad'에 저장된 값을 2차원 배열 'pad'를 하나 생성해서 저장해주자
- 그다음 번호 간의 이동시간을 저장할 2차원 배열 'timeCnt'를 생성해주고, 이웃한 번호를 체크하기 위해서 방향 배열도 생성한다
- 'timeCnt'를 'Arrays.fill()' 메서드를 활용해 배열의 값을 일단 모두 2로 채워준다
- 같은 번호를 연속으로 입력할 경우엔 이동 시간이 0이기 때문에 값을 0으로 채워준다
- 이제 이웃한 번호들을 탐색해서 이웃한 번호들 사이의 이동 시간을 1이기 때문에, 이 경우에 해당하는 'timeCnt'의 값은 1로 변경해준다
- 이제 'password'을 'charAt()' 메서드로 번호를 하나씩 꺼내고, 이 번호에 해당하는 'timeCnt'의 값을 비밀번호가 입력되는데 걸리는 총 시간에 더해주면 된다
해결 코드
public class Solution {
public int solution(int[] keypad, String password){
int[][] pad = new int[3][3];
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
pad[i][j] = keypad[i * 3 + j];
}
}
int[][] timeCnt = new int[10][10];
int[] dx = {-1, -1, 0, 1, 1, 1, 0, -1};
int[] dy = {0, 1, 1, 1, 0, -1, -1, -1};
for(int[] cnt : timeCnt) {
Arrays.fill(cnt, 2);
}
for(int i = 0; i < 10; i++) { // 같은 번호를 연속으로 입력할 경우
timeCnt[i][i] = 0;
}
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
int from = pad[i][j];
// 주위에 이웃한 번호 탐색
for(int k = 0; k < 8; k++) {
// 키패드 밖을 벗어나지 않는 경우
if(i + dx[k] >= 0 && i + dx[k] < 3 && j + dy[k] >= 0 && j + dy[k] < 3) {
int to = pad[i + dx[k]][j + dy[k]];
timeCnt[from][to] = 1;
}
}
}
}
int answer = 0;
// 패스워드 첫 번호는 비밀번호 입력하는데 걸리는 시간으로 치지 않는다
for(int i = 1; i < password.length(); i++) {
int from = password.charAt(i - 1) - '0';
int to = password.charAt(i) - '0';
answer += timeCnt[from][to];
}
return answer;
}
}
▼ 정리
- 2차원 배열을 같은 값으로 채워줄 때엔 'Arrays.fill()' 메서드를 활용하되 행(row)별로 접근해서 사용해야 오류가 발생하지 않는다
( 배열을 특정 값으로 채우고자 할 때엔 일일히 접근하지 않아도 메서드를 활용하면 된다는 사실을 기억해두면 좋을 것 같다 ) - char형을 int형으로 형 변환하고자 할 때엔 강제 형 변환을 하게 되면 아스키 코드를 반환하기 때문에, 강제 형변환이 아닌 아스키 코드를 이용해서 변환해주도록 하자