본문 바로가기
Xcode/Swift - Algorithm

Swift) 프로그래머스(Lv1) - 키패드 누르기 (DFS)

by 후르륵짭짭 2020. 8. 12.
728x90
반응형

programmers.co.kr/learn/courses/30/lessons/67256

 

코딩테스트 연습 - 키패드 누르기

[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] "right" "LRLLLRLLRRL" [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] "left" "LRLLRRLLLRR" [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] "right" "LLRLLRLLRL"

programmers.co.kr

안녕하세요 후르륵짭짭 입니다.

이번에는 카카오 2020 인턴쉽 Lv1 문제인 키패드 누르기 문제를 풀었습니다.

개인적으로 저의 코드는 마음에 안 들기 때문에 ㅎㅎㅎㅎ 그냥 넘어가도 좋을 것 같습니다.

저는 일단 DFS로 키패드 사이의 간격을 찾았는데,,

다른 분들은 더 좋은 코드로 해결 했더군요 (배웠습니다.)

 

** 개인적으로 좋았던 코드 ** 

KyungminLeeDev 님의 코드 입니다.

func countKeypad(_ start: Int , _ dest: Int) -> Int {
    // [ 1, 2,  3]
    // [ 4, 5,  6]
    // [ 7, 8,  9]
    // [-1, 0, -2]
    let keypad = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [-1, 0, -2]]
    var startPos = [0, 0]
    var destPos = [0, 0]

    for i in 0..<4 {
        for j in 0..<3 {
            if keypad[i][j] == start {
                startPos[0] = i
                startPos[1] = j
            }
            if keypad[i][j] == dest {
                destPos[0] = i
                destPos[1] = j
            }
        }
    }

    var count = 0
    for i in 0...1 {
        count += startPos[i] > destPos[i] ? startPos[i] - destPos[i] : destPos[i] - startPos[i]
    }

    return count
}

func solution(_ numbers:[Int], _ hand:String) -> String {
    var LH = -1
    var RH = -2
    var result = ""

    for n in numbers {
        switch n {
        case 1, 4, 7:
            LH = n
            result += "L"
            break

        case 3, 6, 9:
            RH = n
            result += "R"
            break

        default:
            let countLH = countKeypad(LH, n)
            let countRH = countKeypad(RH, n)

            // 같은거리면 왼손잡이 오른손잡이로 누름
            if countLH == countRH {
                if hand == "left" {
                    LH = n
                    result += "L"
                } else {
                    RH = n
                    result += "R"
                }
                break
            }

            // 가까운 손으로 누름
            if countLH < countRH {
                LH = n
                result += "L"
            } else {
                RH = n
                result += "R"
            }
            break
        }
    }

    return result
}

 

** 저의 코드 **

import Foundation

var KeyPad : [[String]] = Array(repeating: Array(repeating: "*", count: 3), count: 4)
var tempPad : [[String]] = Array(repeating: Array(repeating: "*", count: 3), count: 4)

var cnt : Int = Int.max

let RL = [1,-1,0,0]
let UD = [0,0,1,-1]

var answer : String = ""

func solution(_ numbers:[Int], _ hand:String) -> String {

    KeyPad[3][0] = "L"
    KeyPad[3][2] = "R"

    for element in numbers{

        switch element {
        case 1 , 4 , 7:
            answer += "L"
            move(element, finger: "L")
        case 3 , 6 , 9 :
            answer += "R"
            move(element, finger: "R")
        default:
            moreClose(element, hand)
        }

    }

    return answer
}

func moreClose(_ element : Int ,_ hand : String){

    var left : Int
    var right: Int

    switch element {
    case 2:
        DFS(0, findFinger("L")!.x, findFinger("L")!.y, 1, 0)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        left = cnt; cnt = Int.max
        DFS(0, findFinger("R")!.x, findFinger("R")!.y, 1, 0)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        right = cnt; cnt = Int.max

        if left < right {
            answer += "L"
            move(element,finger:  "L")
        }
        else if left == right {

            if hand == "left"{
                answer += "L"
                move(element,finger:  "L")
            }
            else{
                answer += "R"
                move(element,finger:  "R")
            }

        }
        else {
            answer += "R"
            move(element,finger:  "R")
        }

    case 5:
        DFS(0, findFinger("L")!.x, findFinger("L")!.y, 1, 1)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        left = cnt; cnt = Int.max
        DFS(0, findFinger("R")!.x, findFinger("R")!.y, 1, 1)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        right = cnt; cnt = Int.max

        if left < right {
            answer += "L"
            move(element,finger:  "L")
        }
        else if left == right {

            if hand == "left"{
                answer += "L"
                move(element,finger:  "L")
            }
            else{
                answer += "R"
                move(element,finger:  "R")
            }

        }
        else {
            answer += "R"
            move(element,finger:  "R")
        }


    case 8:
        DFS(0, findFinger("L")!.x, findFinger("L")!.y, 1, 2)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        left = cnt; cnt = Int.max
        DFS(0, findFinger("R")!.x, findFinger("R")!.y, 1, 2)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        right = cnt; cnt = Int.max

        if left < right {
            answer += "L"
            move(element,finger:  "L")
        }
        else if left == right {

            if hand == "left"{
                answer += "L"
                move(element,finger:  "L")
            }
            else{
                answer += "R"
                move(element,finger:  "R")
            }

        }
        else {
            answer += "R"
            move(element,finger:  "R")
        }

    case 0:
        DFS(0, findFinger("L")!.x, findFinger("L")!.y, 1, 3)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        left = cnt; cnt = Int.max
        DFS(0, findFinger("R")!.x, findFinger("R")!.y, 1, 3)
        tempPad = Array(repeating: Array(repeating: "*", count: 3), count: 4)
        right = cnt; cnt = Int.max
        print(left, right)
        if left < right {
            answer += "L"
            move(element,finger:  "L")
        }
        else if left == right {

            if hand == "left"{
                answer += "L"
                move(element,finger:  "L")
            }
            else{
                answer += "R"
                move(element,finger:  "R")
            }

        }
        else {
            answer += "R"
            move(element,finger:  "R")
        }
    default:
        break
    }


}

func DFS(_ temp : Int ,_ currentX : Int ,_ currentY : Int ,_ endX : Int ,_ endY : Int){

    tempPad[currentY][currentX] = "#"

    if currentX == endX && currentY == endY{

        if cnt > temp {
            cnt = temp
        }

    }
    else{

        for move in 0...3{

            let nextX = currentX + RL[move]
            let nextY = currentY + UD[move]

            if nextX >= 0 && nextX < 3 && nextY >= 0 && nextY < 4 {

                if tempPad[nextY][nextX] != "#" {
                    DFS(temp + 1, nextX, nextY, endX, endY)
                    tempPad[nextY][nextX] = "*"
                }

            }

        }

    }

}

func move(_ element : Int , finger : String){

    let location = findFinger(finger)
    KeyPad[location!.y][location!.x] = "*"
    switch element {
    case 1:
        KeyPad[0][0] = "L"
    case 4:
        KeyPad[1][0] = "L"
    case 7:
        KeyPad[2][0] = "L"
    case 3:
        KeyPad[0][2] = "R"
    case 6:
        KeyPad[1][2] = "R"
    case 9:
        KeyPad[2][2] = "R"

    case 2:
        KeyPad[0][1] = finger
    case 5:
         KeyPad[1][1] = finger
    case 8:
          KeyPad[2][1] = finger
    case 0:
          KeyPad[3][1] = finger
    default:
        break
    }

}

func findFinger(_ finger : String) -> (y :Int, x :Int)?{

    for Y in 0..<KeyPad.count{
        for X in 0..<KeyPad[Y].count{

            if KeyPad[Y][X] == finger{
                return (Y,X)
            }

        }
    }

    return nil
}

딱 봐도 너무 길고 

안 좋아 보입니다..... 가독성도 떨어지고,,,

DFS로 풀려고 하니 코드가 너무 길어져 버렸습니다.... 흑 ㅠㅠ

728x90
반응형

댓글