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
}
같이 공부했는데 센스에서 차이가 나는군요... 그래도 이렇게 퀴즈를 풀어보는 게 상당히 재미있네요. 자신이 잘하는 언어로 한번씩 구현해 보시는 것도 재미있을 것 같습니다.
"너무도 고급스럽..."지 않습니다. 멤버들에게 스칼라의 특징을 최대한 보여주기 위해 약간 고민은 했지요. 아웃사이더 님의 코드도 의미가 있다고 생각합니다. 다양한 접근법을 다 알아가면 되겠지요. :D 다만 제목의 "일고" => "읽고"... (앗, 이거슨 function literal !?)
사실 elegance하다고 할려다가... 한국말로....
저도 빨리 상황에 맞는 기법을 적절히 쓰고 싶어요..ㅎㅎㅎ
오히려 동일한 내용을 자바로 한번 짜보면 어때?
코드리뷰하면서 언어별로 언어의 특성별로 하나씩 짜봐도 재밌겠다 생각은 했는데.... 시간이 좀 여의치 않네요 ㅎ
"개미수열" 로 검색해서 들어왔어요.
제가 "개미 수열 프로그래밍"이란 작은 책을 하나 쓰면서 다른 분들은 어떻게 풀었을까 궁금해서 자주 검색해 보거든요. :-)
"특성별로 하나씩 짜봐도.."라는 댓글을 보고 혹시 관심 있으실까봐 댓글 남깁니다.
저는 언어보다는 다양한 방식 (정규표현식, 이터레이터/제너레이터, 코루틴, CPS, CSP, 지연리스트 등)을 살펴보는데 중점을 뒀답니다.
Scala는 스트림(지연리스트)이 있기 때문에 지연리스트가 지원되는 다른 언어들(Haskell Clojure 등)과 비슷하게 나옵니다.
def ant = Stream.iterate(Stream(1))(s => group(s).flatMap(g => Stream(g.length, g(0))))
group은 takeWhile과 dropWhile의 조합인데, span이 있으니까 다음과 같습니다.
def group[A](s:Stream[A]):Stream[Stream[A]] = s match { case h#::t => val (pre,sub) = s.span(_ == h); pre #:: group(sub); case _ => Stream.empty }
워낙 오래된 글이라.. 이렇게 댓글 달아도 되나 싶어요. :-)
너무 오래전에 작성해서 저도 다 까먹었네요. 오래된 글이지만 한주영님처럼 검색해서 들어오시는 분들이 있으니 새로운 접근에 대한 글을 남겨주시는건 좋다고 생각합니다. ^^
제가 스칼라 한지가 너무 오래되서 의견을 더 내지 못하는게 아쉬울 뿐이네요.