2차 공부/알고리즘

공원 산책

공대탈출 2024. 7. 3. 16:15

프로그래머스 - 공원산책

 

 

 

처음 작성한 코드

function solution(park, routes) {
    var answer = [];
    let startX = 0;
    let startY = 0;
    let XObj = {};
    for (let i = 0; i<park.length; i++) {
        let sX = park[i].split('')
        if (!startX && !startY){
            let findXS = sX.indexOf('S')
            if (findXS !== -1) {
                startX = findXS
                startY = i
            }
        }
        let tempArr = []
        for (let j = 0; j<sX.length; j++) {
            if (sX[j] === 'X') {
                tempArr.push(j)
            }
        }
        XObj[i] = [...tempArr]
    }
    
    for (let k = 0; k<routes.length; k++) {
        switch (routes[k][0]) {
            case ('N') : {
                let beforeStartY = startY
                for (let l = 0; l<routes[k][2]; l++) {
                    startY--
                    let flag = XObj[startY].includes(startX)
                    if (startY<0 || flag)  {
                        startY = beforeStartY
                        break;
                    }
                }
                break;
            }
            case ('S') : {
                let beforeStartY = startY
                for (let l = 0; l<routes[k][2]; l++) {
                    startY++
                    let flag = XObj[startY].includes(startX)
                    if (startY>park.length-1 || flag) {
                        startY = beforeStartY
                        break;
                    }
                }
                break;
            }
            case ('W') : {
                let beforeStartX = startX
                for (let l = 0; l<routes[k][2]; l++) {
                    startX--
                    let flag = XObj[startY].includes(startX)
                    if (startX<0 || flag ) {
                        startX = beforeStartX
                        break;
                    }
                }
                break;
            }
            case ('E') : {
                let beforeStartX = startX
                for (let l = 0; l<routes[k][2]; l++) {
                    startX++
                    let flag = XObj[startY].includes(startX)
                    if (startX>park[0].length-1 || flag) {
                        startX = beforeStartX
                        break;
                    }
                }
                break;
            }
        }
    }
    return [startY, startX];
}

 

시작점부터 이동하는 X, Y값을 저장할 startX, startY변수를 생성해준다.

그리고 장애물을 세로 한칸마다 장애물의 위치를 저장할 객체 XObj를 생성해준다.

처음 i for문에서 park의 각 요소를 글자마다 분리하여 시작점이 입력되지 않았을 때만 S를 찾아 입력하게 하였다.

그리고 빈 배열을 만들어 X가 위치한 곳의 인덱스를 저장해 XObj에 세로줄: [X인덱스번호, X인덱스번호] 이런식으로 저장하게 하였다. 

let startX;
    let startY;
    let XObj = {};
    for (let i = 0; i<park.length; i++) {
        let sX = park[i].split('')
        if (startX === undefined && startY === undefined){
            let findXS = sX.indexOf('S')
            if (findXS !== -1) {
                startX = findXS
                startY = i
            }
        }
        let tempArr = []
        for (let j = 0; j<sX.length; j++) {
            if (sX[j] === 'X') {
                tempArr.push(j)
            }
        }
        XObj[i] = [...tempArr]
    }

 

routes의 요소들에 대해 반복문을 열어주고, 입력방향이 N, S, W, E인 경우를 나눠 작성하였다.

N, S인경우 이전 Y값을 beforeStartY값에 저장해주고 이동값인 routes[k][2]값까지의 반복문을 한번 더 열어준다.

N은 -방향이므로 Y에서 1을 빼주고, 장애물객체의 해당 Y값에서 해당 X값이 포함되어있는지 flag를 만들어준다.

조건문으로 0보다 작거나(공원을 벗어나거나) X가 포함된 경우 둘 중 하나라도 포함된다면 startY를 이전값으로 돌리고 해당 route의 반복을 break를 통해 부순다.

S는 더해지는 방향이므로 startY에 1을 더하고 조건문에서 공원의 최대Y길이를 벗어나는지를 포함시켰다.

 

    for (let k = 0; k<routes.length; k++) {
        switch (routes[k][0]) {
            case ('N') : {
                let beforeStartY = startY
                for (let l = 0; l<routes[k][2]; l++) {
                    startY--
                    let flag = XObj[startY].includes(startX)
                    if (startY<0 || flag)  {
                        startY = beforeStartY
                        break;
                    }
                }
                break;
            }
            case ('S') : {
                let beforeStartY = startY
                for (let l = 0; l<routes[k][2]; l++) {
                    startY++
                    let flag = XObj[startY].includes(startX)
                    if (startY>park.length-1 || flag) {
                        startY = beforeStartY
                        break;
                    }
                }
                break;
            }
            case ('W') : {
                let beforeStartX = startX
                for (let l = 0; l<routes[k][2]; l++) {
                    startX--
                    let flag = XObj[startY].includes(startX)
                    if (startX<0 || flag ) {
                        startX = beforeStartX
                        break;
                    }
                }
                break;
            }
            case ('E') : {
                let beforeStartX = startX
                for (let l = 0; l<routes[k][2]; l++) {
                    startX++
                    let flag = XObj[startY].includes(startX)
                    if (startX>park[0].length-1 || flag) {
                        startX = beforeStartX
                        break;
                    }
                }
                break;
            }
        }
    }
    return [startY, startX];

결과는?

런타임에러가 돌아왔다.

 

 

두번째로 작성한 코드

function solution(park, routes) {
    
    //방향을 객체에 담아줌
    const directions = {'E': [0, 1], 'W': [0, -1], 'S': [1, 0], 'N': [-1, 0]};
    //높이와 너비를 미리 담아줌
    const height= park.length;
    const width = park[0].length;
    
    let start = []
    for (let i = 0; i < height; i++) {
        //매 반복마다 includes를 쓰지 않도록 변경
        for (let j = 0; j < width; j++) {
            if (park[i][j] === 'S') {
                start = [i, j]
                break;
            };
        }
        //시작 지점을 찾을 시 반복을 끝내도록 설정
        if (start.length !== 0) {
            break
        }
    }
    
  //각각의 이동값을 검사하는 반복문
    for (const route of routes) {
        //방향과 이동거리를 구조분해할당하여 저장
        const [direction, distance] = route.split(" ");
        //start배열에서 x와 y값 구조분해할당
        let [movingX, movingY] = start;
        //이동거리를 미리 정해둔 방향배열에 맞춰 한번씩 이동한다.
        let step = 0;
        //step이 이동거리가 될 때까지 아래 반복문 실행
        while (step < Number(distance)) {
            //directions의 배열에서 알맞은(N,S...)방향의 x값과 y값을 1씩 더함
            movingX += directions[direction][0];
            movingY += directions[direction][1];
            //공원 밖을 나가거나 장애물을 만나면 반복문 종료
            if (movingX < 0 || height <= movingX || movingY < 0 || width <= movingY || park[movingX][movingY] === "X") break;
            //공원밖을 나가지않고, 장애물을 만나지 않았다면, step에 1을 더하고 다음 반복으로 넘어간다.
            step++;
        }
        //걸음수가 이동거리에 해당하면 start값을 다시 nx, ny로 조정해준다.
        if (step === Number(distance)) {
            start = [movingX, movingY]
        };
    }

    return start;
}

항상 느끼는 거지만, includes는 편리하지만 효율이 좋지 않다.

코드를 작성할 때 무작정 글자만 쓰지말고 효율에 대해 조금 더 생각해봐야 할 것 같다.

 

'2차 공부 > 알고리즘' 카테고리의 다른 글

최댓값과 최소값  (0) 2024.07.05
신고 결과 받기  (0) 2024.07.04
달리기 경주  (0) 2024.07.02
개인정보 수집 유효기간  (0) 2024.07.01
성격 유형 검사하기  (0) 2024.06.27