본문 바로가기

컴퓨터/프로그래머스

프로그래머스 - 67256번: 키패드 누르기 [Java]

문제: https://school.programmers.co.kr/learn/courses/30/lessons/67256

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

1. 코드

class Point{
    int x;
    int y;
    
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public void setPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getDistance(int x, int y) {
         return Math.abs(this.x - x) + Math.abs(this.y - y);
    }
}

class Solution {
    public String solution(int[] numbers, String hand) {
        StringBuilder answer = new StringBuilder();
        int[][] phone = {
            {1, 4, 7},
            {2, 5, 8, 0},
            {3, 6, 9}
        };
        
        Point l = new Point(0, 3);
        Point r = new Point(2, 3);
        for(int num : numbers) {
        	boolean check = false;
            for(int i = 0; i < phone.length; i++) {
                for(int j = 0; j < phone[i].length; j++) {
                    if(phone[i][j] == num) {
                        switchPoint(answer, l, r, i, j, hand);
                        check = true;
                        break;
                    }
                }
                if(check) break;
            }
        }
        return answer.toString();
    }
    
    public void switchPoint(StringBuilder sb, Point l, Point r, int x, int y, String hand) {
        switch(x) {
            case 0 -> move(sb, l, x, y, true);
            case 2 -> move(sb, r, x, y, false);
            default -> {
                if(l.getDistance(x, y) > r.getDistance(x, y)) move(sb, r, x, y, false);
                else if(l.getDistance(x, y) == r.getDistance(x, y)) {
                    if(hand.equals("right")) move(sb, r, x, y, false);
                    else move(sb, l, x, y, true);
                }
                else move(sb, l, x, y, true);
            }
        }
    }
    
    public void move(StringBuilder sb, Point p, int x, int y, boolean leftHand) {
        p.setPoint(x, y);
        if(leftHand) sb.append("L");
        else sb.append("R");
    }
}

2. 설명

class Point{
    int x;
    int y;
    
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public void setPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    public int getDistance(int x, int y) {
         return Math.abs(this.x - x) + Math.abs(this.y - y);
    }
}

왼손과 오른손 가락의 위치를 다루기 위한 Point 클래스입니다. setPoint() 메서드를 이용하여 좌표를 수정하며 getDistance() 메서드를 통해서 손가락의 위치와 특정 번호에 대한 거리를 구합니다.

int[][] phone = {
    {1, 4, 7},
    {2, 5, 8, 0},
    {3, 6, 9}
};

기존 휴대폰의 번호 배열의 0열을 0행으로 1열을 1행으로 2열을 2행으로 즉, 전치행렬로 하여 진행하였습니다.

Point l = new Point(0, 3);
Point r = new Point(2, 3);
for(int num : numbers) {
    boolean check = false;
    for(int i = 0; i < phone.length; i++) {
        for(int j = 0; j < phone[i].length; j++) {
            if(phone[i][j] == num) {
                switchPoint(answer, l, r, i, j, hand);
                check = true;
                break;
            }
        }
        if(check) break;
    }
}

반복문을 통해서 numbers의 번호가 phone 배열을 통해서 좌표를 구합니다. 그리고 switchPoint() 메서드를 통해서 좌표 정보를 넘기고 check를 true로 반환하여 해당 번호를 찾고 관련 동작을 수행했음을 알려 다음 번호를 이어서 계속 수행합니다.

public void switchPoint(StringBuilder sb, Point l, Point r, int x, int y, String hand) {
    switch(x) {
        case 0 -> move(sb, l, x, y, true);
        case 2 -> move(sb, r, x, y, false);
        default -> {
            if(l.getDistance(x, y) > r.getDistance(x, y)) move(sb, r, x, y, false);
            else if(l.getDistance(x, y) == r.getDistance(x, y)) {
                if(hand.equals("right")) move(sb, r, x, y, false);
                else move(sb, l, x, y, true);
            }
            else move(sb, l, x, y, true);
        }
    }
}

switchPoint 메서드는 손가락이 번호에 맞게 동작하는 함수입니다. 0일 경우 {1, 4, 7}이라는 것을 의미하기에 왼손을 움직입니다. 2일 경우 {3, 6, 9}이기에 오른손을 움직입니다. 만약 1이라면 나머지 수이기에 거리를 측정한 뒤 더 적은 거리에 있는 손을 움직이며 만약 거리가 동일하다면 주로 사용하는 손을 사용해줍니다.

public void move(StringBuilder sb, Point p, int x, int y, boolean leftHand) {
    p.setPoint(x, y);
    if(leftHand) sb.append("L");
    else sb.append("R");
}

move() 메서드는 손가락의 위치 변경과 문자를 추가하는 메서드 입니다.

 

3. 정리

  1. 휴대폰 키 배열을 적절하게 배열로 옮긴다.
  2. 거리를 계산하는 식을 만든다.
  3. 문제의 길이가 길지만 천천히 읽어본다.
출처: 프로그래머스 코딩 테스트 연습, 
https://school.programmers.co.kr/learn/challenges