2011-12-24 2 views
6

stream을 스칼라에서 알고리즘으로 정의하는 방법이 있습니까?역 추적 알고리즘을 스트림으로 변환하는 방법은 무엇입니까?

예를 들어, 다음 backtracking 알고리즘은 주어진 크기의 모든 "2 진"문자열을 인쇄합니다.

def binaries(s:String, n:Int) { 
    if (s.size == n) 
    println(s) 
    else { 
    binaries(s + '0', n) 
    binaries(s + '1', n) 
    } 
}

은 내가 다른 반복 알고리즘을 사용하여 주어진 크기의 "이진"문자열 stream을 정의 할 수 있습니다 생각합니다. 그러나 알고리즘을 stream으로 역 추적 할 수 있는지 궁금합니다.

답변

11

이 꽤 솔직하다 :

def binaries(s: String, n: Int): Stream[String] = 
    if (s.size == n) Stream(s) 
    else binaries(s + "0", n) append binaries(s + "1", n) 

append의 사용 -이 방법은 다른 비 표준 이는 매개 변수별로 매개 변수를 가져와야하기 때문에 요구 사항입니다.

+0

고마워, 정확히 내가 뭘 찾고있어 :) 그것은 원래의 backtracking 버전보다 더 효율적으로 (스택 메모리 소비면에서) 보이지 않습니까? – Michael

+0

@Michael 아마도. 나는'Stream'을 사용하는 코드의 분석 효율이 좋지 않습니다. 사용하는 것이 필요한 경우 REPL에서 코드가 오버플로되지 않았는지 테스트해야합니다. –

+0

@Michael, 스트림 버전은 스택 프레임 사용면에서 효율성이 떨어집니다. 각각의 재귀 호출은 4 개의 스택 프레임을 사용합니다. 실제로는이 예제에서는 문제가되지 않습니다. 힙 메모리 사용과 관련하여 Stream 클래스는 저장된 참조 당 메모리 사용량 중 스칼라 콜렉션 중 가장 효율적이지 않지만 일반적으로 스트림의 헤드를 우연히 들지 않으면 대개 괜찮습니다 ... – huynhjl

3

당신은 할 수 있지만,이 게으르게 평가하지 않습니다 예를 들어

def bin(s: String, n: Int): Stream[String] = { 
    if (s.length == n) { 
    println("got " + s) // for figuring out when it's evaluated 
    Stream(s) 
    } else { 
    val s0 = s + '0' 
    val s1 = s + '1' 
    bin(s0, n) ++ bin(s1, n) 
    } 
} 

, bin("", 2).take(2).foreach(println)을 실행하면 다음과 같은 출력을 얻을 것이다 :

scala> bin("", 2).take(2).foreach(println) 
got 00 
got 01 
got 10 
got 11 
00 
01 

당신이 괜찮다면 TraversableView을 사용하면 https://stackoverflow.com/a/3816012/257449에 설명 된 변환을 사용할 수 있습니다. 그럼 코드가된다 : 다음

def toTraversable[T](func : (T => Unit) => Unit) = new Traversable[T] { 
    def foreach[X](f : T => X) = func(f(_) : Unit)      
} 

def bin2(str: String, n: Int) = { 
    def recurse[U](s: String, f: (String) => U) { 
    if (s.length == n) { 
     println("got " + s) // for figuring out when it's evaluated 
     f(s) 
    } else { 
     recurse(s + '0', f) 
     recurse(s + '1', f) 
    } 
    } 
    toTraversable[String](recurse(str, _)) view 
} 

scala> bin2("", 2).take(2).foreach(println) 
got 00 
00 
got 01 
01 
got 10 
+0

ScalaDoc scrounging의 약간은 먼 길을 갈 수 있습니다. :-) –

+0

@ DanielC.Sobral, 실제로 사용하지 않거나 전에 'append'한 적이 없습니다. – huynhjl

관련 문제