[Swift 알고리즘] Swift - 알고리즘 입력(readLine) 처리 방법
안녕하세요. 개발 중인 정주입니다.
오늘은 알고리즘의 첫걸음인 입력에 대해 알아보겠습니다.
Swift는 iOS 개발에 주로 사용하다 보니 Swift로 알고리즘을 공부하려는 분들께서는 많이 당황하실 수 있습니다.
저도 그중 한 사람이었는데요.
한 번 알아두니 오히려 알고리즘 공부하기 정말 편하더라고요.
설명 없이 코드만 필요하시다면 맨 아래 요약을 보시면 됩니다.
Swift로 알고리즘 공부를 하는 환경 구성은 지난 포스팅을 참고해주세요.
2021.08.31 - [정주는 개발 중 :]/iOS, Swift] - [Xcode] Swift 알고리즘 - Xcode 환경 세팅
그럼 시작하겠습니다!
개발 환경
MacBook Pro (Retina, 15-inch, Mid 2015)
macOS Big Sur(11.5)
프로세서 : 2.5 GHz 쿼드 코어 Intel Core i7
메모리 : 16GB 1600 MHz DDR3
그래픽 : Intel Iris Pro 1536 MB
Xcode
Xcode 12.5.1
Apple Developer Documentation
readLine
https://developer.apple.com/documentation/swift/1641199-readline/
readLine
Swift의 입력은 readLine()을 통해 합니다.
이전 포스팅을 보셨다면 아시겠지만, readLine은 Xcode의 Playground에서는 동작을 안 하니 참고해주세요.
readLine()은 EOF가 들어오기 전의 입력을 Optional String형으로 return 합니다.
EOF란 'End of File'의 약자로 파일의 끝을 의미하는데요.
Swift 터미널 Input에서는 엔터가 입력되면 EOF 처리가 됩니다.
즉, 엔터가 한 번 입력되면 readLine() 한 개가 끝납니다.
알고리즘 문제에서 ' '를 기준으로 입력을 여러 개 받으면 readLine() 한 개로 처리하면 되고
엔터를 기준으로 입력을 여러 개 받는다면 readLine()을 여러 개 작성하면 되겠죠?
정수(Int) 한 개 입력받기
readLine()의 return형은 String? 형이기 때문에 Int형으로 사용하기 위해서는 형 변환이 필요합니다.
아래 코드를 봅시다.
let input = readLine()
print(type(of: input))
let inputOut = input!
print(type(of: inputOut))
let intVar = Int(inputOut)
print(type(of: intVar))
let result = intVar!
print(type(of: result))
//실행 결과
//3
//Optional<String>
//String
//Optional<Int>
//Int
입력은 readLine()으로 합니다.
입력 값의 type을 찍어보면 String? 형이 출력됩니다.
이것을 언래핑하면 String이 되고 이를 Int로 감싸면 Int? 가 됩니다.
이때 옵셔널이 되는 이유는 Int로 형 변환을 실패하여 nil이 할당될 수도 있기 때문입니다.
최종적으로 이 결과를 한 번 더 언래핑해야 Int형이 됩니다.
이것을 한 줄로 요약할 수 있습니다.
let input = Int(readLine()!)!
정수를 한 개 입력받을 땐 이 한 줄을 이용하면 됩니다.
정수를 여러 개 입력받는 건 아래에 작성하도록 하겠습니다.
공백 단위로 입력받기 - 1
공백 단위로 입력을 받는 것은 split()을 사용하면 됩니다.
let input = readLine()!
print(type(of: input))
let input = readLine()!
print(type(of: input))
let result = input.split(separator: " ")
print(type(of: result))
let result2 = input.split { $0 == " " } //클로저 이용
print(type(of: result2))
//실행 결과
//h e l l o
//String
//Array<Substring>
//Array<Substring>
입력값을 String으로 바꿔 이를 " " 기준으로 Array로 만들어 줍니다.
이때 주의할 점은 최종 결과값이 Array <String> 형이 아니라 Array <Substring> 형이기 때문에
String으로 형 변환하는 과정이 추가로 필요합니다.
String과 Substring의 차이점은 추후 다뤄보겠습니다.
Substring이 아닌 String으로 처리하고 싶을 땐 이어서 나올 내용을 확인해주세요.
공백 단위로 입력받기 - 2
Substring이 아닌 String으로 처리하고 싶다면 어떻게 해야 할까요?
split() 대신 components()를 사용하면 됩니다
import Foundation
let input = readLine()!
print(type(of: input))
let result = input.components(separatedBy: " ")
print(type(of: result))
//실행 결과
//h e l l o
//String
//Array<String>
split()과 components()은 몇 가지 차이점이 있는데요.
그중 하나는 split()은 swift standard library에 포함되어 있어 Foundation을 import 하지 않아도 사용이 가능하고
components()는 Foundation 프레임워크에 포함되어 있기 때문에 import Foundation을 해주지 않으면 사용하지 못합니다.
사용에 유의하시길 바랍니다.
개행 단위로 입력받기
알고리즘 문제 중 개행 단위로 여러 개의 입력받는 문제가 존재합니다.
그럴 땐 readLine()을 여러 번 사용하면 됩니다.
아래처럼요!
let input1 = readLine()!
let input2 = readLine()!
print(input1, input2)
//실행 결과
//hello
//jeongju!
//hello jeongju!
hello -> 엔터에서 1번 라인의 readLine()이 끝나고 jeongju!->엔터에서 2번 라인의 readLine()이 끝납니다.
정수 여러 개 입력받기
정수를 여러 개 입력받는 방법은 위 방법들에 map()을 이용하면 됩니다.
알고리즘 문제를 풀면서 가장 많이 사용될 방법으로 생각됩니다.
let input1 = readLine()!.split(separator: " ").map { Int(String($0))! }
print(type(of: input1))
//실행 결과
//1 2 3
//Array<Int>
갑자기 코드가 길어져서 당황할 수도 있는데 사실 map() 하나만 추가된 겁니다.
map()을 클로저로 사용하였습니다.
배열 하나하나의 아이템에 map 클로저 안의 코드를 적용시킵니다.
즉, Substring 아이템들을 Int로 하나하나 바꾼다는 의미입니다.
단순히 Int($0)! 이 아니라 Int(String($0))! 를 해준 이유는 뒤의 방법이 속도가 좀 더 빠르다고 하네요.
이유는 기회가 된다면 다시 포스팅하도록 하겠습니다.
연속적으로 입력 받기
흔하진 않지만 1, 2, 3, 4, 5를 "12345"처럼 연속적으로 값을 받아오는 문제가 있습니다.
이럴 땐 입력값을 배열로 먼저 변환하여 처리하면 됩니다.
let input = Array(readLine()!)
print(input)
print(type(of: input))
let result = input.map { Int(String($0))! }
print(result)
print(type(of: result))
//실행 결과
//["1", "2", "3", "4", "5"]
//Array<Character>
//[1, 2, 3, 4, 5]
//Array<Int>
String을 Character 하나하나 쪼개서 Array로 변환합니다.
그리고 map을 이용해 각 아이템을 Int로 변경합니다.
연속적인 입력은 이렇게 먼저 Array로 변환하여 처리하시면 됩니다.
요약 코드
정수 한 개 입력
let input = Int(readLine())!
정수 여러 개 입력
let input1 = readLine()!.split(separator: " ").map { Int(String($0))! }
문자열 한 개 입력
let input = readLine()!
문자열 여러 개 입력
let input1 = readLine()!.split(separator: " ")
let input2 = readLine()!.split { $0 == " " }
연속적인 입력
let input = Array(readLine()!).map { Int(String($0))! }
마무리
오늘은 알고리즘을 공부하기 위한 필수 과정인 입력에 대해 알아보았습니다.
언어에 익숙해지기 위해 쉬운 알고리즘 문제들만 골라서 하나씩 풀어보고 있습니다.
언어에 조금 익숙해진 뒤 본격적인 앱 개발을 하려고 하는데 벌써부터 두근거립니다.
다음 Swift 포스팅도 기대해주세요.
감사합니다!
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.