Scala 如何创建递归生成项目的Akka流源

Scala 如何创建递归生成项目的Akka流源,scala,akka-stream,Scala,Akka Stream,我试图找出如何创建一个生成许多Seq[Int]的Akka Streams源 基本上,给定一个intn,我想生成1到n的所有Seq[int] 下面是一些实现此功能的代码: def combinations(n: Int): Seq[Seq[Int]] = { def loop(acc: (Seq[Int], Seq[Seq[Int]]), remaining: Seq[Int]): Seq[Seq[Int]] = { remaining match {

我试图找出如何创建一个生成许多Seq[Int]的Akka Streams源

基本上,给定一个int
n
,我想生成1到n的所有
Seq[int]

下面是一些实现此功能的代码:

def combinations(n: Int): Seq[Seq[Int]] = {
    def loop(acc: (Seq[Int], Seq[Seq[Int]]),
             remaining: Seq[Int]): Seq[Seq[Int]] = {
      remaining match {
        case s if s.size == 1 => {
          val total: Seq[Seq[Int]] = acc._2
          val current: Seq[Int] = acc._1
          total :+ (current :+ s.head)
        }
        case _ => {
          for {
            x <- remaining
            comb <- loop((acc._1 :+ x, acc._2), remaining.filter(_ != x))
          } yield comb
        }
      }
    }

    loop((Seq(), Seq()), (1 to n))
  }
def组合(n:Int):Seq[Seq[Int]={
def回路(附件:(序号[Int],序号[Int]]),
剩余:Seq[Int]:Seq[Seq[Int]={
剩余比赛{
如果s.size==1=>{
val总计:序号[序号[内部]]=附件2
val电流:序号[Int]=附件1
总计:+(当前:+s.水头)
}
案例=>{
为了{

x这里有一个使用Johnson Trotter算法进行排列的解决方案。
tPermutations
创建一个懒散列表,可以根据需要进行评估。要进行更多排列,只需将不同的值传递给
Printnitations

使用Johnson Trotter算法的原因是它打破了置换查找算法的递归结构。这对于能够计算置换的连续实例并将它们存储在某种惰性列表或流中非常重要

object PermutationsTest {
  def main(args: Array[String]) = {
    printNIterations(50, tcopermutations(5).iterator)
  }

  def printNIterations(n: Int, it: Iterator[Seq[Int]]): Unit = {
    if (n<=0) ()
    else {
      if (it.hasNext) {
        println(it.next())
        printNIterations(n - 1, it)
      } else ()
    }

  }

  def naivepermutations(n: Int): Seq[Seq[Int]] = {
    def loop(acc: Seq[Int], remaining: Seq[Int]): Seq[Seq[Int]] = {
      remaining match {
        case s if s.size == 1 => {
          val current: Seq[Int] = acc
          Seq((current :+ s.head))
        }
        case _ => {
          for {
            x <- remaining
            comb <- loop(acc :+ x, remaining.filter(_ != x))
          } yield comb
        }
      }
    }

    loop(Seq(), (1 to n))
  }

  def tcopermutations(n: Int): LazyList[Seq[Int]] = {
    val start = (1 to n).map(Element(_, Left))

    def loop(v: Seq[Element]): LazyList[Seq[Element]] = {
      johnsonTrotter(v) match {
        case Some(s) => v #:: loop(s)
        case None => LazyList(v)
      }
    }
    loop(start).map(_.map(_.i))
  }

  def checkIfMobile(seq: Seq[Element], i: Int): Boolean = {
    val e = seq(i)

    def getAdjacent(s: Seq[Element], d: Direction, j: Int): Int = {
      val adjacentIndex = d match {
        case Left => j - 1
        case Right => j + 1
      }
      s(adjacentIndex).i
    }

    if (e.direction == Left && i == 0) false
    else if (e.direction == Right && i == seq.size - 1) false
    else if (getAdjacent(seq, e.direction, i) < e.i) true
    else false
  }

  def findLargestMobile(seq: Seq[Element]): Option[Int] = {
    val mobiles = (0 until seq.size).filter{j => checkIfMobile(seq, j)}
    if (mobiles.isEmpty) None
    else {
      val folded = mobiles.map(x=>(x,seq(x).i)).foldLeft(None: Option[(Int, Int)]){ case (acc, elem) =>
        acc match {
          case None => Some(elem)
          case Some((i, value)) => if (value > elem._2) Some((i, value)) else Some(elem)
        }
      }
      folded.map(_._1)
    }
  }

  def swapLargestMobile(seq: Seq[Element], index: Int): (Seq[Element], Int) = {
    val dir = seq(index).direction
    val value = seq(index).i
    dir match {
      case Right =>
        val folded = seq.foldLeft((None, Seq()): (Option[Element], Seq[Element])){(acc, elem) =>
          val matched = elem.i == value
          val newAccOpt = if (matched) Some(elem) else None
          val newAccSeq = acc._1 match {
            case Some(swapMe) => acc._2 :+ elem :+ swapMe
            case None => if (matched) acc._2 else acc._2 :+ elem
          }
          (newAccOpt, newAccSeq)
        }
        (folded._2, index + 1)
      case Left =>
        val folded = seq.foldRight((None, Seq()): (Option[Element], Seq[Element])){(elem, acc) =>
          val matched = elem.i == value
          val newAccOpt = if (matched) Some(elem) else None
          val newAccSeq = acc._1 match {
            case Some(swapMe) => swapMe +: elem +: acc._2
            case None => if (matched) acc._2 else elem +: acc._2
          }
          (newAccOpt, newAccSeq)
        }
        (folded._2, index - 1)
    }
  }

  def revDirLargerThanMobile(seq: Seq[Element], mobile: Int) = {
    def reverse(e: Element) = {
      e.direction match {
        case Left => Element(e.i, Right)
        case Right => Element(e.i, Left)
      }
    }
    seq.map{ elem =>
      if (elem.i > seq(mobile).i) reverse(elem)
      else elem
    }
  }

  def johnsonTrotter(curr: Seq[Element]): Option[Seq[Element]] = {
    findLargestMobile(curr).map { m =>
      val (swapped, newMobile) = swapLargestMobile(curr, m)
      revDirLargerThanMobile(swapped, newMobile)
    }
  }

  trait Direction
  case object Left extends Direction
  case object Right extends Direction

  case class Element(i: Int, direction: Direction)
}
对象置换测试{
def main(参数:数组[字符串])={
打印操作(50,t置换(5).迭代器)
}
def打印操作(n:Int,it:Iterator[Seq[Int]]):单位={
如果(n){
val当前值:序号[Int]=acc
序号(当前:+s.head))
}
案例=>{
为了{
x懒汉名单(五)
}
}
循环(开始).map(0.map(0.i))
}
def checkIfMobile(seq:seq[Element],i:Int):布尔={
val e=序号(i)
def getnexting(s:Seq[Element],d:Direction,j:Int):Int={
val邻接索引=d匹配{
案例左=>j-1
案例右侧=>j+1
}
s(邻接索引)
}
如果(e.direction==Left&&i==0)为false
如果(e.direction==Right&&i==seq.size-1)为false,则为else
否则,如果(GetNextant(seq,e.direction,i)checkIfMobile(seq,j)}
如果(mobiles.isEmpty)无
否则{
val fold=mobiles.map(x=>(x,seq(x.i)).foldLeft(无:选项[(Int,Int)]){case(acc,elem)=>
acc比赛{
案例无=>部分(要素)
case Some((i,value))=>if(value>elem._2)Some((i,value))else Some(elem)
}
}
折叠。映射(u.u 1)
}
}
def swapLargestMobile(seq:seq[Element],index:Int):(seq[Element],Int)={
val dir=序列(索引)。方向
val值=序号(索引).i
直接匹配{
案例右侧=>
val folded=seq.foldLeft((无,seq()):(Option[Element],seq[Element]){(acc,elem)=>
val matched=elem.i==值
val newacopt=如果(匹配)某些(元素)其他无
val newAccSeq=附件1匹配{
案例部分(swapMe)=>附件2:+elem:+swapMe
案例无=>如果(匹配)附件2其他附件2:+elem
}
(新会计科目,新会计科目)
}
(折叠。2,索引+1)
案例左=>
val folded=seq.foldRight((无,seq()):(选项[Element],seq[Element]){(elem,acc)=>
val matched=elem.i==值
val newacopt=如果(匹配)某些(元素)其他无
val newAccSeq=附件1匹配{
案例部分(swapMe)=>swapMe+:元素+:附件2
案例无=>如果(匹配)附件2其他元素+:附件2
}
(新会计科目,新会计科目)
}
(折叠式._2,索引-1)
}
}
def revDirLargerThanMobile(seq:seq[Element],mobile:Int)={
def倒档(e:元件)={
e、 方向匹配{
案例左=>元素(即,右)
案例右=>元素(e.i,左)
}
}
seq.map{elem=>
如果(要素i>序号(移动)i)反向(要素)
埃尔斯元素
}
}
def Johnson Trotter(当前:序号[元素]):选项[序号[元素]]={
findLargestMobile(curr).map{m=>
val(交换,新移动)=交换移动(当前,m)
revDirLargerThanMobile(交换,新移动)
}
}
性状方向
案例对象向左延伸方向
case对象右扩展方向
案例类元素(i:Int,方向:direction)
}

我对你的问题投了赞成票,因为它很有趣。但是,我不确定你是否需要Akka Streams。正常的Streams实现应该足以实现这一点。虽然你的问题没有问这个问题,但我想知道如何优化你的代码尾部调用,使其工作时不会出现堆栈溢出的危险。是的,我想知道也在,但它似乎不像没有耗尽内存那样紧迫;)我建议编辑您的问题,将“scala”包括在内标记。这样,其他人可能会找到它。无论如何,我会考虑你的问题。这很有趣。这非常有效,谢谢!因为我还想在Akka Streams上尝试这一点,所以我可以只做Source.fromIterator(()=>tcopermutations(12)。iterator),它工作得非常好!