ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 톱니바퀴 (14891번) Swift
    알고리즘 2021. 10. 12. 14:44

    문제 내용

    4개의 톱니바퀴가 존재한다.톱니는 S, N 극으로 존재하고회전하는 톱니 A 와 맞닿은 톱니 B 가 맞닿은 부분이 같은 극이라면 회전하지 않고서로 다른 극이라면 회전한다.모두 회전하고 난 후 톱니바퀴의 12시 방향으로 총 점수를 내라.1번 톱니의 12시 방향이 S 극이면 + 1, 2번은 + 2, 3번은 + 4, 4번은 + 8


    전체 코드

    import Foundation
    
    // 1. 톱니를 저장할 배열
    var gears: [Gear] = []
    // 2. 결과를 저장할 값
    var result = 0
    
    // 3. 4개의 톱니의 값을 얻어옴
    for _ in 0..<4 {
        // 5. 얻은 톱니 정보를
        let gear = readLine()!.map{ Int(String($0))! }
        // 6. 톱니 구조체를 생성하고 배열에 저장함
        gears.append(Gear(info: gear))
    }
    
    // 7. k 값을 받음
    let k = Int(readLine()!)!
    
    for _ in 0..<k {
        let order = readLine()!.split { $0 == " " }.map { Int(String($0))! }
        // 8. 회전 정보를 담은 배열을 생성
        var rotate: [Rotate] = Array(repeating: .none, count: 4)
        
        // 9. 1일 때는 시계 방향(right), -1 일 때는 반시계 방향(left)으로 회전
        switch order[1] {
        // 시계
        case 1:
            rotate[order[0] - 1] = .right
        // 반시계
        case -1:
            rotate[order[0] - 1] = .left
        default:
            continue
        }
        
        // 10. 기준점 (order[0] - 1) 로 부터 왼쪽에 있는 톱니
        if order[0] - 2 >= 0 {
            for i in stride(from: order[0] - 2, through: 0, by: -1) {
                // 11. 만약 현재 톱니의 우측 극과
                // 현재 톱니 오른쪽에 있는 톱니의 왼쪽 극이 같으면
                // 종료
                if gears[i].right() == gears[i + 1].left() {
                    break
                    
                // 12. 그렇지 않으면
                // 오른쪽에 있는 톱니 회전의 반대 방향으로 회전함
                } else {
                    switch rotate[i + 1] {
                    case .right:
                        rotate[i] = .left
                    case .left:
                        rotate[i] = .right
                    case .none:
                        break
                    }
                }
            }
        }
        
        // 13. 기준점 (order[0] - 1) 로 부터 오른쪽에 있는 톱니
        if order[0] < 4 {
            for i in order[0] ..< 4 {
                // 14. 만약 현재 톱니의 왼쪽 극과
                // 현재 톱니 왼쪽에 있는 톱니의 오른쪽 극이 같으면
                // 종료
                if gears[i].left() == gears[i - 1].right() {
                    break
                    
                // 15. 그렇지 않으면
                // 왼쪽에 있는 톱니 회전의 반대 방향으로 회전함
                } else {
                    switch rotate[i - 1] {
                    case .right:
                        rotate[i] = .left
                    case .left:
                        rotate[i] = .right
                    case .none:
                        break
                    }
                }
            }
        }
        
        // 16. 저장한 회전 명령대로 회전
        for i in 0..<4 {
            switch rotate[i] {
            case .right:
                gears[i].moveRight()
            case .left:
                gears[i].moveLeft()
            case .none:
                continue
            }
        }
    }
    
    // 17. 주어진 규칙대로 결과 값을 저장함
    for i in 0..<4 {
        result += gears[i].top() * Int(pow(2.0, Double(i)))
    }
    
    print(result)
    
    // 18. 회전 열거형, (반시계, 시계, 회전 안함)
    enum Rotate {
        case left
        case right
        case none
    }
    
    // 19. 톱니 구조체
    struct Gear {
        // 20. 톱니의 정보를 저장함
        // 톱니 자체를 돌리는 것이 아닌 top, left, right 의 index 를 변경할 것이므로 let 으로 설정함
        let info: [Int]
        // 21. top, right, left index.
        // 외부에서 따로 접근하지 않으므로 private 로 선언
        private var topIndex: Int
        private var rightIndex: Int
        private var leftIndex: Int
        
        // 22. 초기화
        init(info: [Int]) {
            self.info = info
            // 23. 주어진 배열에 맞게 index 를 초기화함
            // 굳이 여기서 안하고 처음 생성할 때 이렇게 해도 될 듯
            self.topIndex = 0
            self.rightIndex = 2
            self.leftIndex = 6
        }
        
        // 23. 시계 방향 회전
        mutating func moveRight() {
            // 24. 시계 방향으로 회전하므로
            // index 가 전체적으로 -1 되어야 함
            self.topIndex = topIndex - 1 == -1 ? 7 : topIndex - 1
            self.rightIndex = rightIndex - 1 == -1 ? 7 : rightIndex - 1
            self.leftIndex = leftIndex - 1 == -1 ? 7 : leftIndex - 1
            
        }
        
        // 24. 반시계 방향 회전
        mutating func moveLeft() {
            // 전체적으로 +1
            self.topIndex = topIndex + 1 == 8 ? 0 : topIndex + 1
            self.rightIndex = rightIndex + 1 == 8 ? 0 : rightIndex + 1
            self.leftIndex = leftIndex + 1 == 8 ? 0 : leftIndex + 1
        }
        
        // 25. top, right, left 값 출력 함수
        func top() -> Int {
            return info[topIndex]
        }
        
        func right() -> Int {
            return info[rightIndex]
        }
        
        func left() -> Int {
            return info[leftIndex]
        }
    }

    결론

    구조체로 만들어서 풀면 확실히 코드가 길어지는 것 같은데

    구조체 생성 외에는 코드가 짧아져서 재밌고

    가독성이 높아져서 기분이 좋다.

    실제 시험 볼 때는 이렇게 안하고 배열로 할 것 같다.

     

    출처 : 백준 톱니바퀴
    https://www.acmicpc.net/problem/14891

     

    14891번: 톱니바퀴

    총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴

    www.acmicpc.net

     

Designed by Tistory.