본문 바로가기
Programmers/Lv.1

[프로그래머스] Lv.1 공원 산책 JAVA 풀이

by Poorm 푸름 2024. 6. 28.

문제 Lv.1 공원 산책 (방향 탐색 시뮬레이션)

 

 :  지나다니는 길 O 장애물 X

    ["방향거리", "방향거리"..]

 

    "E 5" = 현재 위치에서 동쪽으로 5칸 이동했다는 의미

 

    공원의 가로 길이가 W, 세로 길이가 H

 

    공원을 나타내는 문자열 배열 park

    명령이 담긴 문자열 배열 routes

 

  • 3 ≤ park[i]의 길이 ≤ 50
    • S : 시작 지점 (1개) 
    • O : 이동 가능한 통로
    • X : 장애물
  • 1 ≤ routes의 길이 ≤ 50
    • 수행할 명령어
    • routes의 원소는 "op n"과 같은 구조 (op는 이동할 방향, n은 이동할 칸의 수)
      • N : 북 이동 / S : 남 이동 / W : 서 이동 / E : 동 이동
    • 1 ≤ n ≤ 9

 

 

[과정]

 

- 2차원 배열 헷갈리지 말자!! -

 

arr[행][열] 발음하는 순서대로 생각하면 된다 (행의 인덱스 / 열의 인덱스)

  • 다만 인덱스는 세로줄을 보고 판단 의 인덱스는 가로줄을 보고 판단

  • 행의 개수 = 세로로 나열된 원소의 개수
    열의 개수 = 가로로 나열된 원소의 개수

    단순히 행은 가로줄을 의미하니까 가로줄의 원소의 개수와 같다고 생각해선 안된다!

 

x이동과 y이동은 좌표가 아닌 배열의 형식으로 생각한다

 

char[][] arr = {
    {'O', 'S', 'O'},
    {'O', 'X', 'O'},
    {'O', 'O', 'O'}
};

 

여기서 S의 위치는 좌표형식으로 본다면 높이가 바뀐 것이 아니기 때문에 (1,0) 이다 

하지만 배열의 형식으로 본다면 0번째 행의 1번째 열이므로 arr[1][0]이 맞다

고로 x를 가로의 이동이 아닌 행의 이동 (세로이동)으로 생각하고

y를 세로의 이동이 아닌 열의 이동 (가로이동)으로 생각한다

 

 

1. 좌표이동

  • E = 우로 이동 = 열 변경 (y++)
  • W = 좌로 이동 = 열 변경 (y--)
  • N = 상으로 이동 = 행 변경 (x--)
  • S = 하로 이동 = 행 변경 (x++)

 

2. 보통의 if문 조건과는 다르다

  • 보통은 모두 될 조건문부터 먼저 쓴다 (&&연산자 사용)
  • 하지만 해당코드는 참이 되지 않는 경우부터 먼저 쓴다 (||연산자 사용)
    • nx < 0 || ny < 0 범위를 벗어날 경우 
    • ny >= park[0].length() || nx >= park.length 범위를 벗어날 경우
    • || arr[nx][ny] == 'X' 장애물일 경우
    • 위와 같을 경우 이동불가하므로 현재지점을 시작지점으로 다시 초기화 한다
      nx,ny = 현지점 sx,sy = 시작지점
    • break 하고 바로 종료 애초에 시작불가

 

3. 마지막 연산에서만 시작지점 갱신

  • 명령문 [E 2]라고 해도 한번에 두칸을 가는게 아니라 한칸씩 가보면서 장애물이 있는지 확인 필요
  • 가는길에 장애물이 없다면 마지막 순간에만 갱신하면 된다
  • 예로  [E 2] 이면 1칸 이동했을 때는 시작지점을 갱신하지 않고 2칸 모두 다 이동했을 때만 시작지점을 현지점으로 갱신

 

 

[코드]

import java.io.*;
import java.util.*;

class Solution {
    public int[] solution(String[] park, String[] routes) {
        char arr[][] = new char[park.length][park[0].length()];
        int result[] =new int[2];
        int sx = 0;
        int sy = 0;
        
        for(int i=0;i<park.length; i++){
            arr[i]=park[i].toCharArray();
            for(int j=0; j<park[0].length();j++){
                if(arr[i][j]=='S'){
                     sx=i;
                     sy=j;
                }
            }
        }
        
        
        for(String route : routes){
            String dir = route.split(" ")[0];
            int move = Integer.parseInt(route.split(" ")[1]);
            int nx = sx;
            int ny = sy;
            
            for(int j=0; j<move; j++){
                switch(dir){
                    case "E": ny++; break;
                    case "W": ny--; break;
                    case "N": nx--; break;
                    case "S": nx++; break;
                }
                 if (nx < 0 || ny >= park[0].length() || ny < 0 || nx >= park.length || arr[nx][ny] == 'X') {
                    nx = sx; 
                    ny = sy;
                    break;
                }
                
                if (j == move - 1) {
                    sx = nx;
                    sy = ny;
                }
            }
            
        }
        result[0] = sx; 
        result[1] = sy; 
        return result;
    }
}

 

 : public int[] solution(String[] park, String[] routes) {  park랑 routes 입력받기
        char arr[][] = new char[park.length][park[0].length()];  [행개수][열개수]
        int result[] =new int[2];  출력 배열
        int sx = 0;  시작행 초기화
        int sy = 0;  시작열 초기화
        
        for(int i=0;i<park.length; i++){
            arr[i]=park[i].toCharArray();  i행마다 park 한묶음씩 집어넣고 j열에 묶음 쪼개기
            for(int j=0; j<park[0].length();j++){  한묶음 안의 원소개수 만큼 열 만들기
                if(arr[i][j]=='S'){  S라고 하면 시작지점
                     sx=i;  행
                     sy=j;  열
                }
            }
        }
       
        for(String route : routes){  입력받은 routes 배열 한묶음씩 보기
            String dir = route.split(" ")[0];  0번째가 방향
            int move = Integer.parseInt(route.split(" ")[1]);  1번째가 움직일 칸 개수
            int nx = sx;  시작지점으로 nx 초기화
            int ny = sy;   시작지점으로 ny 초기화
            
            for(int j=0; j<move; j++){  routes의 한묶음 안의 원소 다 살펴보기
                switch(dir){  방향이 무엇인지 보고 그에 맞는 명령어 대입
                    case "E": ny++; break;  열 이동 (보이는건 가로 변화)
                    case "W": ny--; break;   열 이동 (보이는건 가로 변화)
                    case "N": nx--; break;  행 이동 (보이는건 세로 변화)
                    case "S": nx++; break;   이동 (보이는건 세로 변화)
                }
                 if (nx < 0 || ny >= park[0].length() || ny < 0 || nx >= park.length || arr[nx][ny] == 'X') {
                    nx = sx;  이동이 불가할 경우 현지점을 다시 시작지점으로 되돌린다
                    ny = sy;  switch 연산 이전으로 되돌리기
                    break;  더 갈 것도 없이 바로 중단
                }
                
                if (j == move - 1) {  for문 마지막 순간에 뽑아내기
                    sx = nx;  시작지점을 지금의 지점으로 갱신
                    sy = ny;  시작지점을 지금의 지점으로 갱신
                }
            }
            
        }
        result[0] = sx;  도착 행 저장
        result[1] = sy;  도착 열 저장
        return result;  결과 출력
    }
}

 

 


  

https://school.programmers.co.kr/learn/courses/30/lessons/172928?language=java

 

프로그래머스

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

programmers.co.kr