[Swift] [18일차] 방문길이

·2024년 12월 25일
0

SwiftAlgorithm

목록 보기
21/105
post-thumbnail

Programmers- 방문길이

var map = Array(repeating: Array(repeating: 0, count: 10), count: 10)

문제접근

단순히 좌표만 볼게 아니였고, 같은 길을 타는지를 묻는거라 <같은 길을 지난다>의 의미를 한번 짚고 가자면..
1. 출발지가 이미 왔던 곳
2. 도착지도 이미 왔던 곳
3. 출발지 -> 도착지 순서로 이전에 왓었는지 혹은 반대도 가능 (아무튼 붙어있어야함)

그럼 이제 이거를 어떻게 구하지? 생각했을 때 지금 생각 나는 것은..
1. 지나오는 길을 전부 좌표로서 기록을 해두고 싶었다.
2. 혹은 커맨드랑 현재 도착을 묶어서 "R"로 3,3에 왔어요! 이런식으로 구분할 수 있게 해주고 싶었다.


주구장창 깨지고, 엄청 코드가 꼬인 후에햐 훨씬 간결하게 나눴다.

var current: [Character: (Int, Int)] = ["N": (0, 0)] 이런 말도 안되는 기록 방식 집어치우고 그냥 어딘가 도착했을때 (현재->다음위치) 뿐만 아니라 (다음 위치 -> 현재 ) 이걸 둘다 판단해주는 방식으로 해줄 것이다 !

완성 코드

import Foundation
var command_dict: [String: (Int, Int)] = [
    "U": (1, 0),
    "D": (-1, 0),
    "L": (0, -1),
    "R": (0, 1)
]

func solution(_ dirs: String) -> Int {
    var answer = 0
    var CONSTRAINT = 5 // 맵의 크기
    var commands = Array(dirs) // 명령어 분리

//    명령어랑 현재도착지 같이 새겨주기
    var current = (0, 0)
    var visitedLoad = Set<String>()

    for command in commands {
        let lastPosition = current
        let direction = command_dict[String(command)]!
        // 튜플 끼리 덧셈
        let nextPosition = (lastPosition.0 + direction.0, lastPosition.1 + direction.1) // 다음 위치가 나왔음
        if nextPosition.0 < -CONSTRAINT || nextPosition.0 > CONSTRAINT || nextPosition.1 < -CONSTRAINT || nextPosition.1 > CONSTRAINT {
            continue
        }
        else {
            // 이제 방향키랑 위치를 같이 넣어준다 !
            if
                visitedLoad
                .contains("\(current)to\(nextPosition)") || visitedLoad
                .contains("\(nextPosition)to\(current)")
            {
                current = nextPosition
                continue
            }
            else { // 왔던길이 아닐 때
                visitedLoad.insert("\(current)to\(nextPosition)")
                current = nextPosition
                answer += 1
            }
        }
    }
    return answer
}

1.SET로 저장을 해주는데 \(nextPosition)to\(current) 구분하기 쉽게 이렇게 그냥 문자열로서 경로를 저장해주었다 억지로 튜플 두개 쓰고 하면 복잡해지다보니, 더 간단한 해결책을 찾고자했다 !
2. SET로 저장해주면 찾는데 걸리는 시간이 상수 시간대니까 배열로 억지로 찾는거보다 더 효율적이겠다 싶었다.


타인의 코드

import Foundation

struct Point: Hashable {
    let x: Int
    let y: Int

    func move(to: Character) -> Point? {
        switch to {
        case Character("U"):
            guard self.y < 5 else {
                return nil
            }
            return Point(x: self.x, y: self.y+1)
        case Character("D"):
            guard self.y > -5 else {
                return nil
            }
            return Point(x: self.x, y: self.y-1)
        case Character("L"):
            guard x > -5 else {
                return nil
            }
            return Point(x: self.x-1, y: self.y)
        case Character("R"):
            guard x < 5 else {
                return nil
            }
            return Point(x: self.x+1, y: self.y)
        default:
            return nil
        }
    }
}

struct Path: Hashable {
    let start: Point
    let end: Point
}

func solution(_ dirs:String) -> Int {

    var current = Point(x: 0, y: 0)
    var paths: Set<Path> = Set()

    for d in dirs {
        if let next = current.move(to: d) {
            paths.insert(Path(start: current, end: next))
            paths.insert(Path(start: next, end: current))

            current = next
        }
    }

    return paths.count / 2
}
  • 내가 Hashable 에러 때문에 문자열로 해주었는데, 다른분 코드는 이렇게 구조체로 로직과 함께 만들어준다음에 처리해준 걸 볼 수가 있었다.
  • 완전 모범답안으로 느껴졌다. 다른 언어를 풀다와서 웬만하면 하나의 스코프안에서 해결해주고 싶었는데, 이런식으로 구조체 선언해주는걸 다음 풀이 때 좀 적용해봐야겠다는 생각을 했다.
profile
기억보단 기록을

0개의 댓글