Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

Scala로 풀어 본 읽고 말하기 수열

몇일전에 포스팅 했던대로 Scala 스터디가 끝나고 다들 실습의 부족함을 느끼고 실습 트레이닝을 하고 있습니다. 간단한 퀴즈를 구현해 보는 방식인데 첫 문제는 읽고 말하기 수열(혹은 개미수열)이었습니다. 읽고 말하기 수열은 베르나르 베르베르의 소설 개미에서 나온 수열로 소설의 이름을 따서 개미수열이라고도 불립니다. 링크에 자세한 설명이 있지만 간단히 설명하자면

1을 '1개의 1'로 읽어서 11로 표기하고 11은 '2개의 1'로 읽어서 21로 표기하고 21은 '1개의 2와 1개의 1로'로 읽어서 1211로 표기하는 식으로 무한히 늘어가게 됩니다.



class AntSequence {
    def run(source: String, count:Int) = {
        var str = source
        for(i <- 1 to count) {
            str = compute(str)
            println(str)
        }
    }

    def compute(source: String):String = {
        var count = 0
        var baseChar = source.substring(0, 1)
        var result = ""

        source.foreach( arg =>
            if (baseChar != arg.toString) {
                result += compute(source.substring(source.indexOf(arg)))
                return count + baseChar + result
            } else {
                count += 1
            }
        )

        count + baseChar + result
    }
}

//  val t = new AntSequence
// t.run("1", 10)

사실 뭐 공개할 만큼 잘 짠 소스는 아니지만 위 코드가 제가 짠 소스입니다.  run은 반복횟수만큼 루프돌리는 함수이고 compute가 수열을 계산하는 함수입니다. String의 첫글자를 baseChar에 저장하고 같은 글자일때는 횟수를 올리고 다른 글자일때는 남을 문자열로 다시 compute를 재귀호출합니다. 중간에 return문이 있는 것은 스칼라 2.7.7에는 아직 break문이 추가되지 않았기 때문입니다.(2.8부터 break문이 추가되었지만 break을 쓴 것은 그다지 깔끔한 처리는 아니었던것 같습니다.

아직 스칼라는 Imperative/Functional Style를 둘다 사용할 수 있는 Hybrid 언어이지만 Functional 스타일을 권장하고 있고 나름 열심히 스칼라의 맛을 살려보려고 했지만 아직 익숙치 않고 개념도 부족하여 거의 Imperative Style로 작성한 느낌입니다. Imperative Style로 짠 덕에 소스는 그다지 복잡하지 않습니다. Functional Style로 한 것은 그나마 재귀호출 정도군요.



nephilim님이 작성하신 코드는 너무 고급스러워서 오히려 저한테는 좀 어려웠고 Miracle이 작성한 소스가 저한테는 가장 인상적이고 깔끔한 느낌이었습니다. 아래소스가 Miracle이 작성한 개미수열입니다.(Miracle의 허락하에 올립니다. ㅎㅎㅎ)


// Miracle
def LookandSay(list : List[Int]) : List[Int] = {
    val count = list.takeWhile(_ == list.head).size
    val remainList = list.drop(count)

    remainList match {
        case Nil => List(count, list.head)
        case _  => count :: list.head :: LookandSay(remainList) 
    }
  
}

//테스트
var count = 7
var list = List(1)

while(count > 0) {
    list = LookandSay(list)
    println(list)
    count -= 1
}

같이 공부했는데 센스에서 차이가 나는군요... 그래도 이렇게 퀴즈를 풀어보는 게 상당히 재미있네요. 자신이 잘하는 언어로 한번씩 구현해 보시는 것도 재미있을 것 같습니다.
2010/08/30 23:56 2010/08/30 23:56