티스토리 툴바


Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Find the sum of all the even-valued terms in the sequence which do not exceed four million.


피보나치 수열 구하는 문제입니다. 4백만 이하의 짝수인 피보나치 수열을 더해라는 거죠. 피보나치 수열만 구한다면야 쉽게 할 수 있을 것 같습니다. 고등학교 수학 시간에 수열을 배우면서 가장 까다로운 수열 중 하나로 피보나치 수열을 배웠던 것 같습니다. 일반항이 좀 복잡했었죠. 하지만, 그렇게까지 할 필요는 없을테고, 루프를 돌면서 수열을 구하면 될 것 같습니다.

생각해보니 recursion을 배울 때도, dynamic programming을 배울 때도, 피보나치 수열을 구하는 것을 예제로 했었네요. 

아래 코드는 recursion을 쓰는 방법입니다만, 두 가지 이유에서 사용할 수 없습니다. 첫번째 문제는 Stack Overflow가 있겠고, 두번째 문제는 비효율적이라는 거죠. 

def f( n: Int ): Int = {
if (n == 0) 0
else if (n == 1) 1
else f(n-1) + f(n-2)
}

그렇다면 dynamic programming 단원에서 배운 방법으로 약간 최적화 해보는 건 어떨까요?

val fibonacciNumbers = new scala.collection.mutable.HashMap[Int,Long]
fibonacciNumbers(1) = 1
fibonacciNumbers(2) = 2 

def f( n: Int ): Long = {
fibonacciNumbers.get(n) match {
case None => {
val fv = f(n-1) + f(n-2)
fibonacciNumbers(n) = fv
fv
}
case x => x.get
}
}

하지만, 이 경우에도 Stack Overflow가 발생하는 문제는 어쩔 수 없습니다. 자꾸 Stack Overflow라고 하니까 tail call 최적화가 생각이 나네요. 그런데, 재귀 호출을 한 번만 하면 괜찮겠는데, 두 번 해서 합을 구해야 하니까, 얼핏 생각해보면 잘 안될 것 같습니다. 하지만, 손으로 풀어보면 이런 식으로 변형이 되는데요. 이걸 보니까 아이디어가 떠오릅니다. 

f(n) = f(n-1) + f(n-2) = (f(n-2) + f(n-3)) + f(n-2) = 2*f(n-2) + f(n-3)
a*f(n) + b*f(n-1) = a*(f(n-1)+f(n-2)) + b*f(n-1) = (a+b)*f(n-1) + a*f(n-2)

프로그램으로 짜보면 

def sumOfTwoFn( n: Int, a: Long, b: Long ): Long = {
if (n == 3) {
2 * a + 1 * b
} else {
sumOfTwoFn( n-1, a + b, a)
}
}

def f( n: Int ): Long = {
n match {
case 1 => 1
case 2 => 2
case _ => sumOfTwoFn( n, 1, 1)
}
}

빠르고 좋긴 한데, 문제를 다시 한 번 읽어보면, 범위 내에 있는 수열 중에서 조건을 만족하는 놈들의 합을 구해야 하니까, 범위 내의 모든 피보나치 수열을 구해야 합니다. 그럼 위의 방법은 비효율적이죠. 

그냥 이전 것과 이전 이전 것만 알면, 현재 값을 구할 수 있다는 수열의 성질을 이용하면, 효율적으로 범위 내의 피보나치 수열을 구할 수 있겠습니다. generator를 한 번 만들어보죠.

class FibonacciIterator extends Iterator[Int] {
var a = 0
var b = 1
def hasNext: Boolean = true
def next: Int = {
val c = a + b
a = b
b = c
c
}
}

이 피보나치 수열 생성기를 이용하면, 문제는 다음과 같이 간단히 해결됩니다. 

val f1 = new FibonacciIterator
val ans1 = f1.takeWhile( _ < 4000000).filter( _ % 2 == 0).reduceLeft[Int](_+_)
println(ans1)

Posted by 한니발

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

1000 미만의 자연수 중에서 3의 배수이거나 5의 배수인 수의 합을 구하라는 것이죠.
그냥 스트레이트하게 프로그램을 작성해보면 다음과 같습니다.

val values = List.range(1, 1000)
val validNumbers = values.filter( n => n % 3 == 0 || n % 5 == 0 )
val sumOfValidNumbers = validNumbers.reduceLeft[Int](_ + _)
println(sumOfValidNumbers)

Line 1
values에다가 1부터 999까지의 숫자를 넣었죠. range는 첫번째 인수는 포함하고, 두번째 인수는 포함하지 않기 때문에, range(1,1000)이 1부터 999가 맞습니다. 이런 식으로 두번째 인수가 범위에서 제외되는게 편리한 이유는 다음과 같은 식이 성립하기 때문입니다.

List.range(a,b) ::: List.range(b,c) == List.range(a,c)

만일 두번째 인수도 범위에 포함된다면, b가 중복이 되어서 식이 성립하지 않겠죠.

List 대신에 Range를 써서 더 코드를 줄여보면 다음과 같습니다.
println((1 until 1000).filter( n => n%3 == 0 || n%5 == 0).reduceLeft[Int](_+_))

Line 2
values의 값을 필터링 했습니다. 필터링 함수는 values가 List[Int] 형이니까 filter의 인수는 (Int) => Boolean 즉 Int형을 받아서 Boolean형을 반환하는 함수여야 합니다. 3의 배수이거나 5의 배수인지 확인하는 것이었으니까, Int를 받아서 Boolean을 반환하는 함수가 맞네요. Scala가 상당히 유연하기는 해도 정적 타입 언어라서 특별히 형을 지정하지 않아도 컴파일러가 자동적으로 형을 추측해서 처리해줍니다. Java처럼 답답하지도 않으면서, Ruby처럼 불안하지도 않달까요.

Line 3.
valueNumbers의 값을 모두 더합니다. 첫번째 원소와 두번째 원소를 합하고(+), 그 결과를 다시 세번째와 합하고, 이것을 끝까지 반복합니다. 앞에서부터 할거니까 reduceLeft를 썼습니다. 여기서 _는 위치에 따라 앞 원소, 뒤 원소를 의미합니다. 그러니까 _ + _ 는 (a, b) => a + b와 동일한 의미입니다.

풀어놓고 보니까, 문제 자체를 그냥 그대로 코드로 옮겼다는 생각이 들 정도입니다. 알고리즘이고 뭐고 없이요.

다른 풀이 방법을 보겠습니다.

n(A union B) = n(A) + n(B) - n(A intersection B)의 관계를 이용하면, 3의 배수와 5의 배수와 15의 배수의 합을 각각 구해서 계산할 수 있을 것 같습니다. 코드로 써보면 다음과 같겠죠.

val values = List.range(1,1000)
def sum(n: Int): Int = { values.filter( _ % n == 0).reduceLeft[Int](_+_) }
val ans = sum(3) + sum(5) - sum(15)
println(ans)


그런데, 3의 배수의 합은 3 + 6 + 9 + ... + 999 = 3 * (1 + 2 + ... + 333)이니까, 1부터 999/3까지의 합을 구한 다음에, 3을 곱하면 되겠네요. 1부터 k까지의 합이 k*(k+1)/2라는 사실을 이용해서 코드로 쓰면 다음과 같겠네요.

val max = 999
def sum(n: Int): Int = { val k = max/n; k * (k + 1) / 2 * n}
val ans = sum(3) + sum(5) - sum(15)
println(ans)


1부터 999까지를 범위로 하지 않고, 1억 정도 까지로 범위를 잡았으면, 첫번째 방법이나, 두번째 방법으로는 너무 오래 걸렸겠습니다. 역시 머리를 안쓰면, 손발이 고생해요. 이 경우에는 CPU지만요.

Posted by 한니발

Project Euler

컴퓨팅 2009/04/25 02:24
Project Euler는 프로그램을 짜서 해결할 수 있는 수학적인 문제를 제시하고, 이를 함께 풀어보는 사이트입니다. 예를 든면 2백만 이하의 모든 소수의 합을 구하라는 식의 문제가 나오죠. 특정 범위의 모든 소수를 구하는 방법은 에라토스테네스의 체가 떠오릅니다. 중학교 때 배웠던 것 같죠? 하지만 방법을 안다고 해서 2백만까지의 소수를 실제로 구할 수는 없으니까, 프로그램을 짜야 합니다. 재미있기도 하지만, 프로그래밍 언어 자체를 공부하는데 아주 그만이죠.

그런데 왜 이 프로젝트를 소개하냐 하면, 제가 이제부터 Project Euler의 문제를 하나 하나 풀면서 이 블로그에 올릴 생각이기 때문입니다. Scala라는 언어를 배우다가 동기부여를 위해 이 프로젝트의 문제를 풀어보고 있는데, 참 도움이 많이 되고 있어서 프로그래밍을 공부하는 다른 분들도 도움에 될 것 같거든요.

문제를 풀기 전에 일단 Scala 언어를 간단히 소개하자면, jvm 위에서 실행되는 객체지향 함수형 언어입니다. Ruby처럼 하면 할수록 재미있고, 즐거운 언어입니다. 상당히 학구적이면서도 jvm 위에서 실행되기 때문에 Java API를 그대로 쓸 수도 있고, 다른 자바 프로그램에 붙일 수도 있어서, 실용성도 꽤나 높습니다. 최근에는 twitter의 백엔드를 Scala로 개발했다죠. 더 자세한 정보는 구글링해보실 거라고 믿고, Scala와 함께하는 Project Euler 여행을 시작하겠습니다.
Posted by 한니발
WWDC의 세션 발표 전 기다리는 동안 나오는 동영상이 참 재미있어서 찍어봤습니다. 세션 발표 중 영상은 공개는 말할 것도 없고, 촬영도 금지입니다만, 세션 시작 전이니까 문제 없을 것 같습니다. 동영상을 잘 보시면 이번 WWDC의 세 가지 주제인 Mac, iPhone, Information Technologies에 포함된 기술들을 대표하는 아이콘들이 iPhone의 UI를 배경으로 표시됩니다. 아이디어가 참 괜찮죠?
애플은 한 가지 기술테마에 대해서 아이콘을 만들어서, 웹에서건 문서에서건 발표자료에서건 써먹는 것을 좋아하는 것 같습니다. WWDC 기간 내내 하도 많이 봤더니, 아이콘만 봐도 뭔 얘기하는지 알겠더라구요.

Posted by 한니발
TAG WWDC
Mac OS X의 다음 버전은 10.6으로 Snow Leopard라는 코드네임을 가지고 있습니다. Snow Leopard에 대한 내용은 이번 WWDC가 시작하기 전에 발표되었습니다만, WWDC에서 들은 내용을 토대로 제 소감을 적어보면 다음과 같습니다.

일단 Apple에서 공식적으로 발표한 자료는 다음 사이트에 가시면 볼 수 있습니다.

http://www.apple.com/macosx/snowleopard/

Snow Leopard가 가지는 큰 두 가지 의미는 첫째로 Exchange서버 지원을 통해서 엔터프라이즈 환경에 좀 더 친화적이 된다는 것이고, 두번째는 미래의 하드웨어 환경에 대해준비한다는 점입니다.

기업환경에서 Exchange서버가 차지하는 역할은 개인 사용자나 학생들 입장에서는 그렇게 와닿는 부분이 아닐 것입니다. 최근들어 개인용 컴퓨터로 맥에 대한 선호도가 점점 높아지고 있기 때문에 IBM 같은 다국적 기업에서도 맥을 업무용으로 사용하는 것을 심각하게 고려하고 있고, 실제로 시범적인 적용을 해보고 있다고 합니다. 직원들의 만족도가 굉장히 높다고 하네요. 하지만, 맥을 업무용으로 제대로 사용하기 위해서는 Lotus Notes나 MS Exchange서버 같은 협업 솔루션 지원을 해줘야 합니다. 지금까지는 3rd party 애플리케이션을 통해서 어렵게 사용하거나, 웹 기반으로 해야 했었는데, 윈도우 환경에서 Outlook을 쓰는 편안함에 비할바는 아니었습니다. 따라서 이번에 Snow Leopard에서 Exchange를 지원한다는 건 기업용 시장에서 맥의 입지에 큰 영향을 줄 것입니다. iPhone이 기업환경에서 열광적인 반응을 얻고 있는 상황에서, 맥 기본 애플리케이션에서의 Exchange 지원은 이런 분위기를 더욱 더 고조시키는 역할을 할 것 같습니다.

미래의 하드웨어 환경은 누구나가 동의하듯이 멀티코어 CPU와 고성능 GPU로 정리할 수 있을 것 같습니다. 멀티코어 CPU는 기존의 프로세스나 쓰레드 기반의 프로그래밍 패러다임을 바꾸어야할 필요성을 낳고 있습니다. 다중 쓰레드 기반 프로그램이 가지는 문제점이라면 논리적으로 흐름을 따라가기가 어렵고, 재현하기 어렵고 그래서 디버그 하기도 어려운 문제점을 발생시키며, 심지어 간단한 계산 조차도 생각해서 해야 하는 불편함이 있다는 것입니다. 게다가 가용한 코어의 수에 따라 쓰레드를 적당하게 만들어서 처리해야 하는 불편함도 있습니다. 통신망이 써킷망에서 패킷망으로 진화했다는 사실을 상기해보면, 컴퓨터의 프로세싱도 그렇게 하는 편이 좋을 거라는 아이디어는 쉽게 도출할 수 있습니다. Sony의 Cell 프로세스의 개념도 이것과 다르지 않죠. Snow Leopard에 도입될 새로운 계산 방식이 이런 아이디어에 바탕을 두고 있습니다.

그러면 GPU는 무슨 의미가 있을까요? 멀티미디어 처리를 효율적으로 하기 위해서 SSE 명령어 세트가 도입되었다는 사실을 상기해봅시다. 그리고, GPU는 3D 그래픽을 처리하기 위해서 부동소수점 연산을 병렬적으로 많이 할 수 있도록 만들어진 특수 목적의 전용 칩이라는 것을 생각해봅시다. 그렇다면 부동소수점 연산을 아주 효율적으로 하는 전용칩을 게임용으로나 쓸 거냐는 의문을 쉽게 가질 수 있습니다. 옛날 co-processor가 했던 것처럼, CPU를 보완하는 용도로 활용하면 좋겠다는 거죠. 그렇습니다. 그렇게 하면 되는 것이죠. 그런데 어떻게요? 이 물음에 대해서 애플식으로 대답을 내놓은 것이 바로 OpenCL입니다. 앞에서 얘기했던 컴퓨팅을 패킷 처럼 끊어서 할 수 있게 하고, 그렇게 끊은 조각을 여러 CPU 코어와 GPU에 나누어 줄 수 있다면, 엄청난 성능 향상을 할 수 있을 것이라고 추측할 수 있습니다.

멀티코어 분산처리와 OpenCL의 성능을 보여주는 데모로 나왔던 시뮬레이션은 전통적인 방식으로 2G-flops에 지나지 않았던 것을 8 core를 쓰고 SSE를 쓰고 GPU의 도움도 받고 해서, 260G-flops로 향상시키는 것을 보여줍니다. 한 마디로 엄청난 것이죠. 불과 얼마 전에 슈퍼컴퓨터들이 하던 것입니다. 물론 개인용 컴퓨터에서 과학 시뮬레이션을 할 수는 없겠지만, 응용 분야는 그런 것만 있는 것이 아니죠. 음성인식, 화상인식, 인공지능 등 지금까지 상상도 못했던 것들이 가능해질 겁니다.

Snow Leopard가 지금까지 맥의 주요 고객이었던 일반 개인 사용자들에게 당장 그렇게 큰 의미가 있지는 않겠지만, 앞으로 미칠 영향은 대단할 거라고 생각합니다. 벌써부터 10.7 내지는 11에서 어떤 새로운 기능들이 도입될까 생각해보게 하네요.

Snow Leopard가 "기능 구현 없이 안정성을 강화하는데 주력할 거다"라고 오해하시는 분들이 종종 보이는데요, 안정성이 아니라 성능이라고 생각하는 것이 제대로 이해하는 것이겠네요.

Posted by 한니발
이번 keynote에서 가장 볼만했던 건 3rd party 애플리케이션들입니다.

애플의 appstore 안내에 가시면 오늘 제가 본 app들을 보실 수 있습니다. 그냥 그렇게 보는 거하고, 실제 움직이는 걸 보는 것하고는 많이 다르긴 하지만, 실제가 훨씬 더 보기 좋다는 걸 감안하시면 될 것 같습니다.
 
제가 가장 인상 깊게 본 것은 의료영상 브라우저 입니다. 스마트폰으로 저렇게 할 수 있을지는 정말 예상 못했습니다. 요구사항 분석에 1주, 구현에 3주가 걸렸답니다. 원래부터 의료영상관련 소프트웨어를 만들던 회사니까 컨텐츠나 알고리즘은 미리 보유하고 있었겠죠. 기존에 있던 것이라고 해도 플랫폼을 옮겨서 이렇게나 빨리 내놓을 수 있다는 건 대단한 겁니다. 하긴 iPhone 관련 발표에서 2주만에 이렇게 개발했어요 라는 얘기를 하도 많이 들어서 이제 놀랍지도 않지만요.

사용자 삽입 이미지

의료 영상을 보여주고 해석하는 여러가지 방법들을 구현해 놓아서, 의사들이 언제든 빠르게 정보를 접근하고, 공유할 수 있도록 되어 있습니다. 위의 사진은 그 영상정보를 3차원으로 돌려보는 모습입니다.

사용자 삽입 이미지

이건 제가 Stanford의 Bookstore에 가서 본 것과 같은, 의학공부를 위한 암기장을 iPhone 애플리케이션으로 만든 것입니다. 정말 실용적으로 보입니다. 다른 종류의 기기로는 이런 목적을 달성하게 하기가 무척이나 어렵죠.

사용자 삽입 이미지

마지막으로 이건, 게임입니다. iPhone에서 고사양의 게임을 시연하는 광경은 새삼스러울 것이 없습니다만, 이 게임은 매 프레임마다 충돌체크를 한다고 합니다. 상당한 CPU 파워가 필요한 일인데요. 이런 것도 해낼 수 있답니다.


Posted by 한니발
TAG iPhone, WWDC
이번 Keynote의 주제는 처음부터 끝까지 iPhone였습니다. iPhone 3rd party 응용프로그램들이 얼마나 대단한지, 그리고 그것들이 App Store라는 worldwide한 채널에서 어떻게 배포될 것인지를 얘기했고, 3G iPhone에 대해서 이야기 했습니다. 새로운 맥이나 OS에 대한 얘기가 없을 것이라는 것을 예상했기 때문에 별 다른 실망감은 없었습니다. 바로 다음 장면까지는 말이죠.
 
사용자 삽입 이미지

이번에 WWDC에 참석했던 한국 사람들이 어떤 심정이었는지는 이 한장의 사진이 말해줍니다. 심지어 남미와 아프리카에 인도까지 있는데, 한국이 빠진 거죠. 러시아와 중국도 없다고 말해봤자 절대 위로가 되지 않습니다.

6개국에서 시작해서 70개국으로 늘어나는 동안, 환호하는 각국의 사람들을 속쓰리게 바라봐야만했습니다. 게다가 70번째가 일본이었습니다.

iPhone을 개인적으로 써보고 싶었는데, 못쓰게 되었다든가 하는 감상도 있었지만, 근본적으로 전세계에서 가장 기술적으로 앞서있는 스마트폰이 국내에 들어오지 못하게 됨으로써 얼마나 세계 시장에서 뒤처질지가 걱정이 됩니다.

이렇게 된 데에는 국내 사업자들과 협상 문제도 있었겠지만, 가장 큰 문제는 WIPI였을 거라고 생각합니다. WIPI를 처음에 만들 때 문제의식을 모르는 바는 아니지만, 이제는 더 이상 성장하기 어려운 플랫폼인데, 언제까지는 이것을 들고 버티라는 건지 안타깝기만 하네요.

iPhone이 단순하게 더 좋은 휴대폰이 아니라, 모바일 플랫폼의 혁명적인 변화를 이끌어가고 있는 기기라는 것을 체감하지 못하고 있다는 것이 아쉽습니다. 큰 흐름은 거스르는 것이 아니라 타고 가야 하는데 말이죠.


Posted by 한니발
TAG iPhone, WWDC
S석을 잡았습니다. 앞에서 15째 정도 되고, 5개 블럭 중에서 왼쪽 두 번째 입니다. 기대되네요. ㅋㅋ

사용자 삽입 이미지

Posted by 한니발
TAG WWDC

Waiting for Keynote

컴퓨팅 2008/06/10 13:11
WWDC keynote는 아침 일찍 줄을 서야 하는 것으로 악명이 높은데요, 농담처럼 새벽3시에 보자고 합니다만, 그런 경우는 정말 앞쪽에서 보고 싶은 경우구요. 대부분은 7시나 8시 정도에 가면 됩니다.
사용자 삽입 이미지

지금 저는 같이 온 한국 분들과 함께 자리 잡고 앉아 있습니다. 앞으로 1시간 반은 더 기다려야 하네요. 한국 시간으로는 12시가 조금 넘은 시간이라, 안 자고 있는 사람들이랑 채팅도 하면서 있습니다. 키노트 생중계를 보고 주무시겠다는 분도 있네요. ^^

참고로 말씀드리면 이곳 Moscone West 컨벤션 센터는 전체적으로 무선랜이 잘 잡히고 있구요. 곳곳에 앉아서 컴퓨터를 쓸 수 있도록 책상이 배치되어 있습니다. 참가하는 사람들이 거의 대부분 맥북을 가지고 오기 때문이죠.

지금 대화의 화제는 일단 이번 키노트에서 뭐가 발표될까 하는 겁니다. 3G iPhone은 이미 알려진 사실이라 새로울 건 없지만, 또 다른게 뭐가 있을라나.. 이러는 거죠. WWDC keynote의 보안은 철저하기로 유명한데, 심지어 Apple 직원들도 루머사이트에 들어가서 본다고 하는 정도니까요. 여기 컨벤션 센터에서도 간간히 검은 색 천으로 가려져 있는 광고판이 많이 보입니다. keynote가 끝나면 천을 치우려고 하는거죠. 
사용자 삽입 이미지

3G iPhone
Mac OS X 10.6 Snow Leopard
윈도우용으로 포팅되는 킬러앱

정도가 예상되는 이슈로 얘기되고 있습니다만, 확실한 건.... 들어봐야겠죠?



Posted by 한니발
TAG WWDC

Bike the Bridge

문화 2008/06/10 10:00
San Francisco에서 유명한 관광 코스 중 하나인 Bike the Bridge를 체험했습니다. Fisherman's Whalf에서 출발해서 북쪽 해변을 따라 달리다가 금문교를 건너 Sausalito까지 간 다음, Ferry를 타고 귀환하는 코스죠. 원래 일정은 아니었는데, 즉흥적인 결정으로 해보게 되었습니다.
사용자 삽입 이미지

다리로 올라가는 오르막도 힘들었고, 특히 맞바람이 워낙 세서 무척 힘들었지만, 재밌는 체험이었습니다. 가격이 좀 비싼데요. 생각보다 오래 걸리기 때문에 시간당 $7씩 4시간과 페리요금 $9이 들어서 전체적으로 $37가 들었습니다. 가는데 70분이 걸린다는 얘기를 듣고 결정했던 건데, 자전거를 아주 잘 타는 사람들 얘기였던 거죠.
사용자 삽입 이미지

돌아오는 길에 영화 The Rock의 배경인 Alkatraz 섬을 가깝게 지나갑니다. 이렇게 아름다운 풍경을 바라만 봐야 한다면 정말 고문이 따로 없을 것 같다는 생각이 드네요.
사용자 삽입 이미지


Posted by 한니발