반응형
문제 링크
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제
지나다니는 길을 'O', 장애물을 'X'로 나타낸 직사각형 격자 모양의 공원에서 로봇 강아지가 산책을 하려합니다. 산책은 로봇 강아지에 미리 입력된 명령에 따라 진행하며, 명령은 다음과 같은 형식으로 주어집니다.
["방향 거리", "방향 거리" … ]
예를 들어 "E 5"는 로봇 강아지가 현재 위치에서 동쪽으로 5칸 이동했다는 의미입니다. 로봇 강아지는 명령을 수행하기 전에 다음 두 가지를 먼저 확인합니다.
주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.
위 두 가지중 어느 하나라도 해당된다면, 로봇 강아지는 해당 명령을 무시하고 다음 명령을 수행합니다.
공원의 가로 길이가 W, 세로 길이가 H라고 할 때, 공원의 좌측 상단의 좌표는 (0, 0), 우측 하단의 좌표는 (H - 1, W - 1) 입니다.
입출력 예
설명
park라는 맵이 주어지면 routes라는 배열을 순차적으로 진행합니다.
한 방향으로 연속적으로 이동하는데 이동 중 'X' 장애물을 만나거나 공원 밖으로 벗어나면 그 명령은 취소됩니다.
설계
function solution()
main함수인 solution() 함수에서는 현재 위치('S' 좌표)를 구하고, 명령 횟수만큼 반복하면서 validateAndMove() 함수로 이동 가능한지 검증 후, 조건에 맞는 경우에만 최종 위치를 지속적으로 업데이트하도록 설계했습니다.
function solution(park, routes) {
let currentLocation = findStartLocation(park);
routes.forEach(action => {
currentLocation = validateAndMove(park, currentLocation, action);
});
return currentLocation;
}
function findStartLocation()
공원 배열에서 시작 지점('S')을 찾아 그 좌표를 반환합니다.
function findStartLocation(park) {
for (let y = 0; y < park.length; y++) {
for (let x = 0; x < park[y].length; x++) {
if (park[y][x] === 'S') {
return [y, x];
}
}
}
return null;
}
function validateAndMove() [핵심]
- 주어진 거리만큼 이동할 수 있는지 검증
- 조건에 맞다면 최종 위치를 반환
- direction에 따란 newX, newY를 한 칸씩 증가시켜 이동합니다.
- 모든 이동이 유효하면 최종 위치 [newY, newX]를 반환
- 조건에 만족하지 않으면 currentLocation을 반환하여 이동을 무시
function validateAndMove(park, currentLocation, action) {
const [direction, steps] = action.split(" ");
const moveCount = parseInt(steps, 10);
const [y, x] = currentLocation;
let newY = y, newX = x;
for (let i = 0; i < moveCount; i++) {
switch (direction) {
case 'E': newX++; break;
case 'S': newY++; break;
case 'N': newY--; break;
case 'W': newX--; break;
}
if (newY < 0 || newY >= park.length || newX < 0 || newX >= park[0].length || park[newY][newX] === 'X') {
return currentLocation;
}
}
return [newY, newX];
}
개선 전체 코드
function solution(park, routes) {
let currentLocation = findStartLocation(park);
routes.forEach(action => {
currentLocation = validateAndMove(park, currentLocation, action);
});
return currentLocation;
}
function findStartLocation(park) {
for (let y = 0; y < park.length; y++) {
for (let x = 0; x < park[y].length; x++) {
if (park[y][x] === 'S') {
return [y, x];
}
}
}
return null;
}
function validateAndMove(park, currentLocation, action) {
const [direction, steps] = action.split(" ");
const moveCount = parseInt(steps, 10);
const [y, x] = currentLocation;
let newY = y, newX = x;
for (let i = 0; i < moveCount; i++) {
switch (direction) {
case 'E': newX++; break;
case 'S': newY++; break;
case 'N': newY--; break;
case 'W': newX--; break;
}
if (newY < 0 || newY >= park.length || newX < 0 || newX >= park[0].length || park[newY][newX] === 'X') {
return currentLocation;
}
}
return [newY, newX];
}
처음 풀었을 때 런타임 에러 코드 ('더보기' 클릭)
더보기
/**
* [이동 전 확인 사항] -> 하나라도 해당 시 다음 명령 시행
* 주어진 방향으로 이동할 때 공원을 벗어나는지 확인합니다.
* 주어진 방향으로 이동 중 장애물을 만나는지 확인합니다.
*
* 0. 2차웜으로 만들기
* 1. 현재 위치 찾기
* 3. 이동
*
* @Param park 공원 ex) ["SOO","OOO","OOO"]
* @Param routes 강아지 수행 명령 ex) ["E 2","S 2","W 1"]
* @Return answer 강아지 위치 [세로, 가로]
*/
function solution(park, routes) {
var answer = [];
let currentLocation = [0,0];
// map 2차원으로 만들기
const towDimensionPark = twoDimension(park);
// 현재 위치 찾기
currentLocation = findStartLocation(towDimensionPark);
//이동
routes.map(action => {
currentLocation = moveValidationAndMove(towDimensionPark, currentLocation, action);
})
answer = currentLocation
return answer;
}
/**
* 1차원 배열 park를 2차원 배열로 반환해줍니다.
* @param {*} park
* @returns towDimensionPark 2차원 배열
*/
function twoDimension(park) {
let towDimensionPark = []
park.map(row => {
towDimensionPark.push(row.split(''))
})
return towDimensionPark
}
/**
* 이동 전 이동 가능 검증 후 이동
* - 이동 가능 시 검증한 위치로 이동
* - 이동 불가능 시 기존 위치 return
* * 한번씩 이동하게 해야한다.
* @Return moveValidation boolean
*/
function moveValidationAndMove(park, currentLocation, nextAction) {
let actionData = nextAction.split(" ");
let arrow = actionData[0];
let moveCount = Number(actionData[1]);
let checkLocation = [];
let testLocation = currentLocation; // 걸어가는 시뮬레이션
for(let repeat = 0; repeat< moveCount; repeat++) {
switch (arrow) {
case 'E':
checkLocation = [testLocation[0], testLocation[1] + 1]
break;
case 'S':
checkLocation = [testLocation[0] + 1, testLocation[1]]
break;
case 'N':
checkLocation = [testLocation[0] - 1, testLocation[1]]
break;
case 'W':
checkLocation = [testLocation[0], testLocation[1] - 1]
break;
}
if (park[checkLocation[0]][checkLocation[1]] === 'O' ||
park[checkLocation[0]][checkLocation[1]] === 'S') {
testLocation = checkLocation;
} else {
return currentLocation;
}
}
return testLocation
}
/**
* 현재 위치 찾기
* @Return CurrentLocationArray [y,x]
*/
function findStartLocation(field) {
for(let y = 0; y<field.length; y++) {
for(let x = 0; x<field[y].length; x++) {
if(field[y][x] === 'S') {
return [y, x];
}
}
}
}
728x90
반응형
'코딩 > 알고리즘, cordingTest' 카테고리의 다른 글
코딩테스트 java 프로그래머스 추억점수 (긴 코드 주의) (1) | 2024.01.31 |
---|---|
코딩테스트 java 프로그래머스 pccp 기출문제 1번 붕대감기 (코테 초보의 풀이법) (1) | 2024.01.30 |
Java로 별찍기 알고리즘 풀어보기: 반복문과 조건문의 활용 삼각형, 마름모 (0) | 2024.01.18 |