我编写的代码使用zipper + comonad找到第一个equilibrium index:
import scalaz._
import Scalaz._
val in = NonEmptyList(-7, 1, 5, 2, -4, 3, 0)
in.toZipper
.cobind { z => z.lefts.sum == z.rights.sum }
.findNext(identity)
.map(_.index)
// returns Some(3)
// I would like to return Some(3, 6) or even a scalaz stream?
我如何调整它以返回所有均衡指数而不仅仅是第一个?
答案 0 :(得分:1)
我想出了这个:
in.toZipper
.cobind { z => z.lefts.sum == z.rights.sum }
.toStream
.zipWithIndex
.filter(_._1)
.map(_._2)
但我不认为它的表现非常好(由于子列表的重复总结)
答案 1 :(得分:1)
我无法帮助您使用scalaz解决方案,但找到平衡指数的更简单的解决方案可能是:
def equilibriaIndices(numbers: List[Int]): List[Int] = {
// sum numbers left side, sum numbers right side, indices equilibiria
val startAcc = (0, numbers.sum, List.empty[Int])
val (_, _, equilibria) = numbers.zipWithIndex.foldLeft(startAcc) {
case ((sumLeft, sumRight, indices), (x, index)) =>
val newIndices = if (sumLeft == sumRight - x) index :: indices else indices
(sumLeft + x, sumRight - x, newIndices)
}
equilibria.reverse
}
哪会给你:
scala> equilibriaIndices(List(-7, 1, 5, 2, -4, 3, 0))
res5: List[Int] = List(3, 6)
答案 2 :(得分:1)
我认为不可能用Zipper
和cobind
编写O(n)解决方案。但是,很容易想出一个没有Zipper
(但仍然有效)的解决方案:
val in = NonEmptyList(-7, 1, 5, 2, -4, 3, 0).list
val total = in.sum
in
.scan(0)(_ + _)
.zip(in)
.map { case (leftSum, focus) => leftSum == total - leftSum - focus }
.zipWithIndex
.filter(_._1)
.map(_._2)
答案 3 :(得分:0)
我提出了另一个解决方案:
val in = Stream(-7, 1, 5, 2, -4, 3, 0)
val sum = in.scan(0)(_ + _)
val hash = (in zip sum) map { case (e, lsum) => 2*lsum + e }
val target = sum.last
hash.zipWithIndex.collect { case (e, i) if e == target => i }
此解决方案具有O(n)运行时,并且它不依赖于scalaz。
它还具有不必预先计算总和的优点。