모노산달로스의 행보

Swift로 백준 프로그래밍 문제 입력 빠르게 받기 본문

ProgrammingLanguage/Swift

Swift로 백준 프로그래밍 문제 입력 빠르게 받기

모노산달로스 2022. 11. 29. 18:34

초보 개발자가 초보 개발자에게 

 

 

필자는 Swift로 백준 문제를 풀면서 시간제한에 걸려 골 머리를 썩힌 경험이 있다

시간 초과의 향연

시간 초과에 걸리지 않도록 하는 방법은 여러 가지가 있지만 입력을 받는 양이 많은 경우 입력을 빠르게 받아 시간을 줄이는 방법을 사용하면 시간 초과를 피할 수 있다

이 글에서는 그 방법에 대해 좀 더 자세하게 소개하겠다

 

1. 커맨드 라인으로 입력 받기

 

 

아래 블로그에 잘 설명되어 있으니 참고하자

https://zeddios.tistory.com/68

 

 

 

2. 파일 입출력으로 입력받기

final class FileIO {
    private let buffer: Data
    private var index: Int = 0

    init(fileHandle: FileHandle = FileHandle.standardInput) {
        self.buffer = try! fileHandle.readToEnd()! // 인덱스 범위 넘어가는 것 방지
    }

    @inline(__always) private func read() -> UInt8 {
        defer {
            index += 1
        }
        guard index < buffer.count else { return 0 }

        return buffer[index]
    }

    @inline(__always) func readInt() -> Int {
        var sum = 0
        var now = read()
        var isPositive = true

        while now == 10
                || now == 32 { now = read() } // 공백과 줄바꿈 무시
        if now == 45 { isPositive.toggle(); now = read() } // 음수 처리
        while now >= 48, now <= 57 {
            sum = sum * 10 + Int(now-48)
            now = read()
        }

        return sum * (isPositive ? 1:-1)
    }


    @inline(__always) func readString() -> String {
            var str = ""
            var now = read()

            while now == 10
                    || now == 32 { now = read() } // 공백과 줄바꿈 무시

            while now != 10
                    && now != 32 && now != 0 {
                str += String(bytes: [now], encoding: .ascii)!
                now = read()
            }
        return str
    }
}

 

구글에 검색해 보면 라이노 님의 코드라고 나오는 코드이다

위 코드를 통해 파일 입출력으로 값을 받아 좀 더 빠르게 작동시켜 시간 초과에서 벗어날 수 있다

import Foundation 아래에 추가해 주기만 하면 된다 그리고

 

let file = FileIO()

let N = file.readInt()
let T = file.readString()

 

위와 같이 file을 통해 FileIO Class를 사용할 수 있게 인스턴스를 생성해 준 다음

file.readInt()을 통해 정수를 file.readString()을 통해 문자열을 입력받을 수 있다

 

하지만 이렇게 하고 Xcode에서 실행시켜 보면 입력을 받고 난 다음 출력이 되지 않는데 ctrl + D를 누르면 출력 값이 나온다

이는 몇 번 해 보면 바로 이해가 되는 부분이다

 

하지만 필자는 여기에 readLine()으로 받을 때와 차이점에 대해 이야기하고 싶은데

 

 

파일 입출력으로 입력을 받을 때는 입력을 모두 받고 처리하는 듯하다 그래서

readLine()으로 공백으로 구분하는 문자열을 Int로 받을 때처럼 여러 개의 값을 입력할 때

readLine()!. split(separator: " ") 같은 식으로 입력받지 말고 readInt()를 여러 번 실행시켜 주면 같은 결과를 얻어낼 수 있다

 

즉 예를 들어 5 3 7 8 9와 같은 값을 입력받는다면

단순하게 for문을 통해 readInt()를 5번 실행시켜주기만 하면 값을 동일하게 입력받을 수 있다는 것이다

필자는 이 간단한 사실을 알지 못하고 헤매는데 시간을 써 버렸다

 

이 글을 보는 다른 초보 개발자 여러분이 있다면 도움이 되기를 바란다