ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Programmers Lv3) 방문 길이
    Algorithm/Programmers 2020. 7. 10. 13:54

    출처: 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을 똑똑하게 사용하자.

    댓글

Designed by Tistory.