콘텐츠로 건너뛰기
Home » swift » Page 12

swift

오일러 프로젝트 25

피보나치 수열은 아래와 같은 점화식으로 정의됩니다.

F_n = F_{n - 1} + F_{n - 2} \\(F_1 = 1, F_2 = 1)

이에 따라 수열을 12번째 항까지 차례대로 계산하면 다음과 같습니다.

F1 = 1
F2 = 1
F3 = 2
F4 = 3
F5 = 5
F6 = 8
F7 = 13
F8 = 21
F9 = 34
F10 = 55
F11 = 89
F12 = 144 

수열의 값은 F12에서 처음으로 3자리가 됩니다. 피보나치 수열에서 값이 처음으로 1000자리가 되는 것은 몇 번째 항입니까?

http://euler.synap.co.kr/prob_detail.php?id=25
더 보기 »오일러 프로젝트 25

오일러 프로젝트 24

어떤 대상을 순서에 따라 배열한 것을 순열이라고 합니다. 예를 들어 3124는 숫자 1, 2, 3, 4로 만들 수 있는 순열 중 하나입니다. 이렇게 만들 수 있는 모든 순열을 숫자나 문자 순으로 늘어놓은 것을 사전식(lexicographic) 순서라고 합니다. 0, 1, 2로 만들 수 있는 사전식 순열은 다음과 같습니다.

012,   021,   102,   120,   201,   210…

0, 1, 2, 3, 4, 5, 6, 7, 8, 9로 만들 수 있는 사전식 순열에서 1,000,000번째는 무엇입니까?

http://euler.synap.co.kr/prob_detail.php?id=24
더 보기 »오일러 프로젝트 24

오일러 프로젝트 23

자신을 제외한 약수(진약수)를 모두 더하면 자기 자신이 되는 수를 완전수라고 합니다. 예를 들어 28은 1 + 2 + 4 + 7 + 14 = 28 이므로 완전수입니다. 또, 진약수의 합이 자신보다 작으면 부족수, 자신보다 클 때는 초과수라고 합니다. 12는 1 + 2 + 3 + 4 + 6 = 16 > 12 로서 초과수 중에서는 가장 작습니다. 따라서 초과수 두 개의 합으로 나타낼 수 있는 수 중 가장 작은 수는 24 (= 12 + 12) 입니다.

해석학적인 방법을 사용하면, 28123을 넘는 모든 정수는 두 초과수의 합으로 표현 가능함을 보일 수가 있습니다. 두 초과수의 합으로 나타낼 수 없는 가장 큰 수는 실제로는 이 한계값보다 작지만, 해석학적인 방법으로는 더 이상 이 한계값을 낮출 수 없다고 합니다.

그렇다면, 초과수 두 개의 합으로 나타낼 수 없는 모든 양의 정수의 합은 얼마입니까?

http://euler.synap.co.kr/prob_detail.php?id=23
더 보기 »오일러 프로젝트 23

(Swift) Process를 이용한 외부 프로세스 이용

파이썬의 Subprocess 모듈을 사용하는 것과 비슷하게, Objective-C에서는 NSTask를 사용하여 프로세스 내에서 다른 외부 프로세스를 실행할 수 있다. Swift로 넘어오면서 NSTask는 브릿징을 통해서 그대로 사용 가능했지만, API를 좀 더 모던하게 개선한 Process라는 별도의 클래스가 새롭게 정의되었다. Process를 사용하여 외부 프로세스의 출력 결과를 가져오는 방식은 .standardOutput 프로퍼티를 이용하여 Pipe를 통해 데이터를 받을 수 있다.

외부 프로세스가 실행되는 동안 .waitUntilExit()를 통해서 프로세스 흐름을 블럭하고 기다리는 방법도 있지만, GUI를 사용하는 경우에는 UI가 멈춰버리기 때문에 .terminationHandler를 사용하여 서브 프로세스 실행이 완료되었을 때, 런루프가 지정한 적절한 시점에 콜백을 실행할 수도 있다.

파이프를 통한 결과 획득

Process 객체를 생성하고 실행할 때 standardOutput, standardInput 등의 속성에 Pipe 객체를 지정해주면, 해당 프로세스의 표준 입출력을 프로그램에서 사용할 수 있다. 프로세스는 생성한 후에 launchPatharguments 를 지정하여 실행할 명령의 경로와 인자를 전달한다. 그런다음 실행(launch)한 후에 .waitUntilExit()를 통해서 해당 프로세스가 종료될때까지 기다렸다가 파이프에 들어온 데이터를 읽으면 된다.

import Foundation

let task = Process()
let pipe = Pipe()
task.launchPath = "/bin/ls"
task.standardOutput = pipe
try? task.run()
task.waitUntilExit()
// FileHandle.availableData: Data (Data? 타입이 아님)
if case let data = pipe.fileHandleForReading.availableData, data.count > 0 {
    String(data:data, encoding:.utf8)?.split(separator:"\n").forEach{ print($0) }
}

파이프를 한 번 읽고나면 파이프는 닫히기 때문에, waitUntilExit()를 호출해서 프로세스가 완전히 끝날 때까지 대기해야한다. GUI에서는 이 메소드가 블럭하면서 UI가 프리징될 수 있기 때문에, 핸들러를 통한 처리 방식을 사용할 것이 권장된다.

더 보기 »(Swift) Process를 이용한 외부 프로세스 이용

(Swift) 키보드로부터 문자열을 입력받기

Swift의 표준 함수 중에서 input() 과 같은 함수가 없었는데, readLine() 함수가 생겼다. 원형은 다음과 같다. 이 함수는 키보드로부터 입력받은 문자열을 (UTF-8로 가정한다) 리턴해준다. 물론 디코딩상의 문제가 있을 수 있어서 출력되는 값은 옵셔널이다. Swift에서는 C함수를 그대로 사용할 수 있고, C의 표준 라이브러리들은 기본적으로 Foundation 프레임워크에 포함되어 있는데, 요상하게 입출력에 관련된 함수 (scanf, printf 등)은 호출할 수가 없었다. 이 함수가 추가하기 전에는 표준입력을 NSFileHandle로 구현해서 다음과 같이 구현해야 했다. 프롬프트를 포함하는 키보드 입력 받기 대신 readLine() 함수는 파이썬의 input() 처럼 프롬프트를 지정할… 더 보기 »(Swift) 키보드로부터 문자열을 입력받기

오일러 프로젝트 17

1부터 5까지의 숫자를 영어로쓰면 one, two, three, four, five이고 각 단어의 길이를 더하면 3+3+5+4+4+=19이므로 사용된 글자는 모두 19개입니다. 1부터 1,000까지 영어로 썼을 때는 모두 몇 개의 글자를 사용해야 할까요? 빈칸이나 하이픈은 셈에서 제외하면 단어 사이에 and는 셈에 넣습니다. 예를 들어 342를 영어로 쓰면 three hundred and forty-two가 되어서 23글자, 115 = one hundred and fifteen의 경우에는 20글자가 됩니다. 접근 숫자를 영단어로 변환하는 함수를 작성하고, 1 ~ 1,000 의 범위에 대해 이 함수를 적용한 후, 글자 수를 모두 더하면 되겠다. 영어… 더 보기 »오일러 프로젝트 17

Functor의 개념과 Swift내의 functor

배열은 Swift에서 동일 타입의 원소를 하나 이상 가질 수 있는 순서있는 집합을 나타내는 자료 구조이다. 배열은 Swift 뿐만 아니라 거의 모든 프로그래밍 언어에서 가장 기본적이며 중요한 자료 구조 중 하나인데, 특히 함수형 프로그래밍 언어에서는 배열을 리스트라고 하는 재귀적인 데이터 구조를 사용하여 일련의 연속적인 값들을 집합으로 다루게 된다. 배열 혹은 리스트에 대한 연산 중에서 가장 대표적인 것은 맵핑 연산이다.  하스켈의 fmap 은 임의의 타입의 원소를 갖는 리스트의 각 원소에 대해 주어진 함수를 적용하여 새로운 리스트를 생성한다. 그리고 대부분의 배열을 지원하는 현대 언어들도 비슷한 기능을 가지고 있다. 자바 스크립트의 Array와 Swift의 Array도 공통적으로 map이라는 메소드를 통해서 변형(transform)함수를 받아 자신의 원소들에게 적용하여 유사한 동작을 수행한다.

더 보기 »Functor의 개념과 Swift내의 functor

오퍼레이션 큐 (Operation Queue)

코코아에서 비동기 작업이나 백그라운드 작업을 실행하는 OOP 스타일의 전통적인 방식은 NSOperation 클래스를 사용하는 것이었다. 이 클래스는 실행할 작업을 객체로 감싸면서 백그라운드 실행이나 의존성, 실행 상황에 대한 KVO 등 많은 기능들을 제공해주기는 했지만, 그 자체로는 추상 클래스였기 때문에 이 클래스를 상속하여 커스텀 클래스를 작성해서 사용해야 하는 불편함이 있었다. 이후 Objective-C 2.0에서 코드 블럭이 본격적으로 활용되기 시작하면서 NSBlockOperation 과 같은 코드 블럭을 사용한 간편한 작업 객체 생성이 가능했는데, 우선순위나 의존성 등의 오퍼레이션 객체의 기능이 요구되지 않는 상황에서는 작업 큐 만으로 동기/비동기 작업을 간단히 관리할 수 있게 되었다.

비동기 작업을 위한 큐는 크게 오퍼레이션 큐와 디스패치 큐의 두 종류가 있다. 사실 내부적으로 이 둘은 모두 GCD를 사용하기 때문에(iOS 4.0부터 NSOperationQueue는 GCD를 사용하기 시작했다.) 본질적으로는 같다고 볼 수 있다. 대신에 오퍼레이션 큐는 추가된 코드블럭을 내부적으로 NSBlockOperation으로 만들어서 관리하며, 기존의 오퍼레이션 객체를 추가할 수 있다. 따라서 의존성에 따른 실행 순서를 지정해야 하거나, 특정 타임 아웃 내에 작업을 중단해야 하는 등의 추가적인 관리 기능을 사용할 수 있다.

용도 측면에서 본다면 디스패치 큐는 성능이나 메모리의 오버헤드를 최소화하여 오래 걸리지 않는 작은 규모의 작업을 한꺼번에 실행하면서 CPU 성능을 최적으로 활용하고 싶을 때 사용할 수 있으며, 오퍼레이션 큐는 개별 작업을 관리해야 하고, 시간이 오래 걸릴 수 있는 (그래서 중간에 중지해야 할 수도 있는) 작업을 수행할 때 더 적합하다 하겠다.

더 보기 »오퍼레이션 큐 (Operation Queue)

(Swift) iOS, OSX에서 이미지 저장하기

이미지를 저장하기

이미지를 JPEG, PNG 데이터로 만드는 것은 UIKit의 표준함수를 이용할 수 있다.

func UIImageJPEGRepresentation(_ image: UIImage!, _ compressionQuality: CGFloat) -> NSData!
func UIImagePNGRepresentation(_ image:UIImage!) -> NSData!

이를 이용해서 데이터를 저장할 수 있다. NSData로 만들어서 그냥 저장하면 되니까.

func saveImage(image: UIImage, toURL url: NSURL, withFormat format:ImageSavingFormat = .PNG) {
    let data: NSData
    switch format {
    case .PNG:
        data = UIImagePNGRepresentation(image)
    case .JPEG:
        data = UIImageJPEGRepresentation(image, 1.0)
    }
    var error: NSError?
    data.writeToURL(url, atomically: false, error: &error)
    if error != nil {
        println("Fail to save image")
    } else {
        println("successfully saved.")
    }
}

더 보기 »(Swift) iOS, OSX에서 이미지 저장하기