光の経路ループ(Lv.2)


質問リンク

に答える

import Foundation

func solution(_ grid:[String]) -> [Int] {
    var nodes: [[Node]] = []
    (0..<grid.count).forEach { _ in // nodes 행 채우기
        nodes.append([])
    }

    let args = grid.map { $0.map { String($0) } }
    for (i, arg) in args.enumerated() {
        for (j, str) in arg.enumerated() {
            let node = Node(Node.NType(rawValue: str)!)
            if i != 0 { // 첫 행이 아니라면
                node.uNode = nodes[i - 1][j]
                nodes[i - 1][j].dNode = node
                
                if i == grid.count - 1 {    // 마지막 행
                    node.dNode = nodes[0][j]
                    nodes[0][j].uNode = node
                }
            }
            
            if j != 0 { // 첫 열이 아니라면
                node.lNode = nodes[i][j - 1]
                nodes[i][j - 1].rNode = node
                
                if j == arg.count - 1 { // 마지막 열
                    node.rNode = nodes[i][0]
                    nodes[i][0].lNode = node
                }
            } 
            
            nodes[i].append(node)
        }
    }
    
    var result: [Int] = []
    
    nodes.forEach {
        $0.forEach {
            for direction in Node.Direction.allCases {
                var count = 0
                var nextDirection = direction
                var nextNode =  $0
                while let args = nextNode.next(nextDirection) {
                    count += 1
                    nextDirection = args.0
                    nextNode = args.1
                }

                if count != 0 {
                    result.append(count)   
                }
            }
        }
    }
    
    result = result.sorted(by: <)
    
    return result
}

class Node {
    enum NType: String {
        case S = "S"
        case L = "L"
        case R = "R"
    }
    
    enum Direction: CaseIterable {
        case left
        case right
        case up
        case down
        
        // 다음에 갈 방향
        func next(_ type: NType) -> Direction {
            switch type {
                case .S:
                    return self
                case .L:
                    switch self {
                        case .left:
                            return .down
                        case .right:
                            return .up
                        case .up:
                            return .left
                        case .down:
                            return .right
                    }
                case .R:
                    switch self {
                        case .left:
                            return .up
                        case .right:
                            return .down
                        case .up:
                            return .right
                        case .down:
                            return .left
                    }
            }
        }
    }
    
    let type: NType
        
    // 한번 거친 노드는 nil 대입한다.
    var lNode: Node? // 왼쪽 노드
    var rNode: Node? // 오른쪽 노드
    var uNode: Node? // 위쪽 노드
    var dNode: Node? // 아래쪽 노드
    
    init(_ type: NType) {
        self.type = type
        self.lNode = self
        self.rNode = self
        self.uNode = self
        self.dNode = self
    }
    
    func next(_ direction: Direction) -> (Direction, Node)? {
        let nextDirection = direction.next(type)
        switch nextDirection {
            case .left:
                if let nextNode = lNode {
                    lNode = nil
                    return (nextDirection, nextNode)
                } else {
                    return nil  // 한번 지나간적 있을경우
                }
            case .right:
                if let nextNode = rNode {
                    rNode = nil
                    return (nextDirection, nextNode)
                } else {
                    return nil
                }
            case .up:
                if let nextNode = uNode {
                    uNode = nil
                    return (nextDirection, nextNode)
                } else {
                    return nil
                }
            case .down:
                if let nextNode = dNode {
                    dNode = nil
                    return (nextDirection, nextNode)
                } else {
                    return nil
                }
        }
    }
}

ポスト


グラフィックの問題を理解する必要があります.
コードが長くなりましたが、頭の中にグラフを描き、移動を想像しながらゆっくりと解けました.
まだ熱々の問題かどうかはわかりませんが、プログラマーの回答ではswift部分が21番目にアップされています!
私はSWIFT開発者全体で21人目の解読者のようです!ははは