Skip to content

Instantly share code, notes, and snippets.

@fehmicansaglam
Created April 28, 2015 10:48
Show Gist options
  • Save fehmicansaglam/e83801d98eea1108978e to your computer and use it in GitHub Desktop.
Save fehmicansaglam/e83801d98eea1108978e to your computer and use it in GitHub Desktop.
How to search for an element in an array while passing state for the next iteration
val numbers = readLine().split(" ").map(_.toInt) // an array of numbers
val leftSums = numbers.scan(0)(_ + _).init // calculate cumulative sums from left
// search from right to find the same sum from left
var sum = 0
val result = numbers.zipWithIndex.reverse.find { case (number, index) =>
if (sum == leftSums(index)) true
else {
sum = sum + number
false
}
}
@fehmicansaglam
Copy link
Author

Can I do this in a side-effect free and immutable way?

@vy
Copy link

vy commented Apr 28, 2015

val numbers = Array[Int](3, 5, 8, 1, 7, 0, 4, 4, 6, 1, 2)
val leftSums = numbers.scan(0)(_ + _).init

leftSums
  .zip(numbers)
  .reverse
  .scan((0, false)) {
    case (token: (Int, Boolean), tuple: (Int, Int)) =>
      val (sum, eql) = token
      val (lhs, rhs) = tuple
      (sum + rhs, sum == lhs)
  }
  .takeWhile { case (sum: Int, eql: Boolean) => !eql }

// Array[(Int, AnyVal)] = Array((0,false), (2,false), (3,false), (9,false), (13,false), (17,false), (17,false))

@korayal
Copy link

korayal commented Apr 28, 2015

Would this work?

def sameSum(nums: List[(Int, Int)], sums: List[Int], total: Int = -1): Option[(Int, Int)] = {
  nums match {
    case Nil => None
    case h :: t =>
      if (total < 0) {
        if (h._1 == sums.head) Some(h) else sameSum(t, sums.tail, h._1)
      } else if (total == sums.head) Some(h)
      else sameSum(t, sums.tail, total + h._1)
  }
}

val numbers = readLine().split(" ").map(_.toInt).toList // an array of numbers
val leftSums = numbers.scan(0)(_ + _).init // calculate cumulative sums from left
sameSum(numbers.zipWithIndex.reverse, leftSums)

@fehmicansaglam
Copy link
Author

@korayal i want to use provided higher order functions only. @vy your solution seems to be what I want. But afaik scan is not lazy and it will scan the whole array.

@vy
Copy link

vy commented Apr 28, 2015

@fehmicansaglam you can replace scan with a fold*/reduce variant by passing a list of accumulated values at each step.

@fehmicansaglam
Copy link
Author

@metanet unfortunately fold does not stop after it finds the solution. @vy the same answer applies for you:)

@fehmicansaglam
Copy link
Author

@metanet my answer for @korayal applies to you. And also this: https://twitter.com/fehmicans/status/593039964268552192

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment