본문 바로가기

Algorithm

Swift Algorithm

728x90

스위프트로 알고리즘을 공부하기로 마음을 먹었습니다. 근데 이제 환경을 어떻게 해야 하는가? 에 대한 의문이 들어 구글링을 해본 결과 playground에서는 입력값을 받지 못해서 입력을 받고 싶다면, actual application인 Command Line Tool을 이용해야 한다고 합니다.

 

🤔 왜 playground는 안되는건데?

플레이그라운드는 샌드박스이므로 input이 없습니다. 

*샌드박스 : 외부로부터 들어온 프로그램이 보호된 영역에서 동작하도록 해서 시스템이 안 좋게 조작되는 것을 막는 보안 형태를 취하는 프로그램입니다.

 

Command Line Tool 

그렇다면 Command Line Tool을 어떻게 사용하는지 알아보도록 하겠습니다!

 

1. 먼저, 엑스 코드를 실행합니다.

 

2. macOS >> Command Line Tool을 엽니다. 그리고 언어를 Swift로 설정합니다.

 

그러면 위와 같이 스위프트 파일이 만들어지는 것을 확인할 수 있습니다.

이렇게 환경은 만들어졌고!! Input 값을 어떻게 받는지 살펴보도록 하겠습니다!!

 

Input 값을 받아보자

먼저, Swift 언어에서 input 값은 readline()를 사용해서 입력을 받을 수 있습니다.

readline 메서드를 살펴보면

public func readLine(strippingNewLine: Bool = true) -> String?

으로 되어 있는 것을 확인할 수 있습니다. 반환 값의 형태를 보면 옵셔널 타입으로 되어 있는 것을 확인할 수 있습니다.

>> 그러므로, (물론 입력값이 거의 대부분의 경우에 있기 때문에 옵셔널 강제 언래핑도 가능하지만) if let을 통해 옵셔널 바인딩을 통해서 입력값을 처리해보겠습니다.

 

// 입력 대기
var input = readLine()

// 입력값 처리
if let input = input {
    print(input)
}

이렇게 코드를 작성하고 command + R을 눌러주면, 다음과 같이 입력값을 칠 수 있습니다.

 

위와 같이 원하는 입력값을 치고 엔터를 누르면, 그대로 다음 코드가 실행되고 프로그램이 종료되는 것을 볼 수 있습니다.

>> readLind 메서드는 말 그대로 🔥한 줄만 읽고 그 값을 Optional String으로 반환합니다. 그러므로 엔터를 치면 한 줄이 끝났다는 것으로 인식하고 입력받은 작업을 끝내는 것입니다.

 

그러면, 만약 입력값이 여러 개인 경우에는 어떻게 코드를 작성해야 할까요?

(= 처음 입력값을 누르고 엔터를 치고 > 다음 값을 누르고 엔터를 치고 >.. 등의 과정에서는 어떻게 해야 할까요?)

✅ 두 번 쓰면 됩니다!!

// 첫번째 입력값
var input = readLine()

if let input = input {
    print(input)
}

// 두번째 입력값
var nextInput = readLine()

if let nextInput = nextInput {
    print(nextInput)
}

이렇게 작성한 코드에 대해서 실행 후 입력값을 치면, 다음과 같은 화면을 볼 수 있습니다.

 

그러면 다음과 같이 원하는 값을 입력하고 엔터를 두 번 쳐야 프로그램이 종료되는 것을 확인할 수 있습니다.

 

Input 값을 구분하고 싶다면?

알고리즘 문제를 풀다 보면 입력값을 여러 개 받고 해당 값들이 대한 연산을 처리하는 문제가 많습니다.

만약 위에서의 코드로 입력값을 받게 되면 두 가지 입력값에 대해서 각 input 타입은 String 형이므로 각 값에 접근할 수 있는 것이 아니라 "1 2"와 같은 문자열의 형태로 저장되어 있습니다. 이는 우리가 연산을 할 때 각 값을 사용하기 때문에 저희가 원하는 형태가 아님을 알 수 있습니다.

 

>> 따라서, 이와 같은 값의 형태를 원하는 형태로 구분 지어 주는 작업이 필요합니다.

"1 2"의 경우, 입력값을 공백을 기준으로 구분하고 있으므로 이 공백을 기준으로 입력받은 값을 배열의 요소로 저장하면 됩니다.

 

String의 값을 원하는 모양으로 쪼개서 배열로 만들어주는 메서드가 있는데 보통 두 가지를 사용합니다.

split VS components

두 메서드의 가장 큰 차이는 Foundation의 import 유무반환 값입니다.

 

func split(separator: Character, maxSplits: Int = Int.max, omittinEmptySubsequences: Bool = true) -> [Substring]

>> split

- import Foundation (X)

- Return Type : [Substring]

- Foundation을 import 하지 않기 때문에 용량이 늘어나지 않습니다.

- Return Type이 Substring 배열입니다. (-> map 함수를 사용해서 해결할 수 있습니다.)

func components(separaterdBy separator: String) -> [String]

>> components

- import Foundation (O)

- Return Type : [String]

- Foundation을 import 하지 않기 때문에 용량이 늘어납니다.

 

 

✅ 각각의 예시 코드를 보면 다음과 같습니다.

var input = readLine()

if let input = input {
    let inputs = input.split(separator: " ")
    print(inputs)
}
var input = readLine()

if let input = input {
    let inputs = input.components(separatedBy: " ")
    print(inputs)
}

두 가지 코드에 대해서 결과 화면은 아래와 같습니다.

 

components의 경우 바로 string 값으로 반환되지만, Foundation 프레임워크를 import 하면 알고리즘 코드의 용량이 커진다는 단점이 있습니다. (근데 이제 그것을 막기 위해 split를 사용하고 map 함수를 사용하면 시간 비용이 발생할 수 있다는.. )