[코테] 키패드 누르기

이동창·2022년 4월 14일
0

코딩테스트

목록 보기
4/5
function calculateLR(number, numPos, leftPos, rightPos, hand) {
    if(number === 0 || number % 3 === 2){
        const leftDistance = Math.abs(leftPos[0]-numPos[0]) + Math.abs(leftPos[1]-numPos[1])
        const rightDistance = Math.abs(rightPos[0]-numPos[0]) + Math.abs(rightPos[1]-numPos[1])
        
        if(leftDistance > rightDistance)
            return 'R'
        else if (leftDistance < rightDistance)
            return 'L'
        else if(hand === 'right')
            return 'R'
        else
            return 'L'
    } else if(number % 3 === 1)
        return 'L'   
    else
        return 'R'
}

function solution(numbers, hand) {
    let result = ''
    let leftPos = [3,0]
    let rightPos = [3,2]
    
    for(let i in numbers){
        const numPos = numbers[i] === 0 ? [3,1] : [Math.floor((numbers[i] - 1) / 3), (numbers[i] - 1) % 3]
        const leftOrRight = calculateLR(numbers[i], numPos, leftPos, rightPos, hand)
        
        if(leftOrRight === 'L') 
            leftPos = numPos
        else 
            rightPos = numPos
        
        result += leftOrRight   
    }
    
    return result
}

처음엔 solution 안에 다 넣었었는데, result += str, leftPos = numPos 같은 애들이
너무 많이 중복되는 것 같아서, 따로 함수를 만들어 로직을 구분했다.

근데 calculateLR 함수의 인자가 좀 많은 것 같아서 줄이고 싶은데..
다른 문제에 비해, 더 깔끔한 solution이 나와 있는 것 같지는 않아 혼자 더 생각을 해봐야겠다.

그리고 저 let 들도 뭔가 보기 싫은데 재귀함수로 이렇게 없애는 건 어떨까?

function calculateLR(number, numPos, leftPos, rightPos, hand) {
    if(number === 0 || number % 3 === 2){
        const leftDistance = Math.abs(leftPos[0]-numPos[0]) + Math.abs(leftPos[1]-numPos[1])
        const rightDistance = Math.abs(rightPos[0]-numPos[0]) + Math.abs(rightPos[1]-numPos[1])
        
        if(leftDistance > rightDistance)
            return 'R'
        else if (leftDistance < rightDistance)
            return 'L'
        else if(hand === 'right')
            return 'R'
        else
            return 'L'
    } else if(number % 3 === 1)
        return 'L'   
    else
        return 'R'
}

function calculateNumPos(number) {
    if(number === 0)
        return [3,1]
    else
        return [Math.floor((number - 1) / 3), (number - 1) % 3]
}

function getResult({numbers, hand, leftPos, rightPos, result, i}) {
    if(i >= numbers.length)
        return result
    
    const numPos = calculateNumPos(numbers[i])
    const leftOrRight = calculateLR(numbers[i], numPos, leftPos, rightPos, hand)

    return getResult({
        numbers, 
        hand, 
        leftPos: leftOrRight === 'L' ? numPos : leftPos, 
        rightPos: leftOrRight === 'R' ? numPos : rightPos, 
        result: result + leftOrRight, 
        i: i + 1
    })
}

function solution(numbers, hand) {
    const initLeftPos = [3,0]
    const initRightPos = [3,2]
    
    const result = getResult({
        numbers, 
        hand, 
        leftPos: initLeftPos, 
        rightPos: initRightPos, 
        result: '', 
        i: 0
    })
    
    return result
}

흠... 너무 길다

게다가 브라우저의 자바스크립트 엔진은 tail call optimization을 지원하지 않아서 성능상 좋지 않은 영향을 미치는 것 같다.
바로 퍼포먼스의 하락이 눈에 보이던데, 이럼 자바스크립트로 함수형 프로그래밍을 어떻게 하라는거지?

일단 첫번째 solution이 더 괜찮아보이는걸로

0개의 댓글