Algorithm/Programmers

Programmers Lv3) 방문 길이

삼쓰 웅쓰 2020. 7. 10. 13:54
728x90

출처: programmers.co.kr/learn/courses/30/lessons/49994

분류: Lv3


접근방식

-5 ~ 5 까지의 정사각형에서 U, D, R, L 중 하나로 이동 방향들이 주어질 때,

처음 이동한 길의 개수를 세는 문제입니다. 

저는 처음에 Set<Chracter> 로 이루어진 11x11 맵을 만들고 각 칸에 이동한 위치를 넣는 엄청나게 무식한 방법을 사용했는데,
단순히 새로운 길의 개수만 알면 되기 때문에 이럴 필요 없이 그냥 좌표만 가지고도 해결할 수 있는 문제입니다.

갈 수 있는 길이라면 그 길을 그냥 Set<String> 에 String 으로 때려박으면 매우 간단해집니다.

주의할 점은 (0, 0) -> (0, 1) 로 이동했다면 반대로 오는 (0, 1) -> (0, 0) 도 같은 길로 체크해야 합니다.

 

해결방법

 

typealias Point = (row: Int, col: Int)
var moved = Set<String>()

func canMove(at point: Point) -> Bool {
    return -5...5 ~= point.row && -5...5 ~= point.col
}

func move(at current: inout Point, order: Character) {
    var row = current.row
    var col = current.col
    switch order {
        case "U": row -= 1
        case "D": row += 1
        case "R": col += 1
        case "L": col -= 1
        default: break
    }
    guard canMove(at: (row: row, col: col)) else { return }
    let next = Point(row: row, col: col)
    moved.insert("\(current)\(next)")
    current = next
}

func solution(_ dirs:String) -> Int {
    var current = Point(row: 0, col: 0)
    dirs.forEach {
        move(at: &current, order: $0)
    }
    
    return moved.count
}

 

 

처음 풀었던, 조금 멍청했던 풀이

struct Point {
    var row: Int
    var col: Int
}

func isInRange(at point: Point) -> Bool {
    return 0...10 ~= point.row && 0...10 ~= point.col
}

func move(at point: Point, order: Character) -> Point {
    switch order {
        case "U": return Point(row: point.row-1, col: point.col)
        case "D": return Point(row: point.row+1, col: point.col)
        case "R": return Point(row: point.row, col: point.col+1)
        case "L": return Point(row: point.row, col: point.col-1)
        default: return point
    }
}

func solution(_ dirs:String) -> Int {
    var board = [[Set<Character>]](repeating: [Set<Character>](repeating: Set<Character>(), count: 11), count: 11)
    var newPointCount = 0
    
    var current = Point(row: 5, col: 5)
    for dir in dirs {
        let next = move(at: current, order: dir)
        guard isInRange(at: next) else { continue }
        if !board[current.row][current.col].contains(dir) {
            newPointCount += 1
            board[current.row][current.col].insert(dir)
            switch dir {
                case "U": board[next.row][next.col].insert("D")
                case "D": board[next.row][next.col].insert("U")
                case "R": board[next.row][next.col].insert("L")
                case "L": board[next.row][next.col].insert("R")
                default: break
            }
        }
        current = next
    }
    
    return newPointCount
}

 

배운점

간단한 Point는 struct보다 typealias를 이용해 튜플로 사용하면 간---편

강력한 Set을 똑똑하게 사용하자.