How to use fold to do boolean testing - scala

I'd like to know the idiomatic way to approach this problem in scala.
Given a start date and an end date and a collection of dates in between, determine whether the given collection of dates contains all the dates necessary to go from the start date to the end date with no gap dates in between.
Type signature:
def checkDate(start: DateTime, end: DateTime, between: IndexedSeq[DateTime]): Boolean
The "normal" or "not functional" way to do this would be something like this:
def checkDate(start: DateTime, end: DateTime, between: IndexedSeq[DateTime]): Boolean = {
i = 1
status = true
while(start != end) {
d = start.plusDays(i)
if (!between.contains(d) {
status = false
break
}
i += 1
}
return status
}
How can I do this using a Fold?
Here's my thought process so far:
def checkDate(start: DateTime, end: DateTime, between: IndexedSeq[DateTime]): Boolean = {
// A fold will assume the dates are in order and move left (or right)
// This means the dates must be sorted.
val sorted = between.sortBy(_.getMillis())
val a = sorted.foldLeft(List[Boolean]) {
(acc, current) => {
// How do I access an iterable version of the start date?
if (current == ??) {
acc :: true
} else false
}
}
// If the foldLeft produced any values that could NOT be matched
// to the between list, then the start date does not have an
// uninterrupted path to the end date.
if (a.count(_ == false) > 0) false
else true
}
I just need to figure out how to index the start parameter so I can increase the value of it as the fold iterates over the between collection. Or it's possible that fold isn't what I'm supposed to use at all.
Any help would be appreciated!

You can pass previous DateTime item in accumulator:
val a = sortedBetween.foldLeft((List[Boolean](), start)) {
case ((results, prev), current) => {
... calculate res here ...
(results ++ List(res), current)
}
}
But for this kind of check you better use sliding and forall combination:
sortedBetween.sliding(2).forall {
case List(prev,cur) => ..do the check here ..
}
Also, note that you ingnoring the result of between sorting since IndexedSeq is immutable. Fix - use another val:
val sortedBetween = between.sortBy(_.getMillis())

I think a fold isn't necessary, it's making things too hard.
Suppose you had the following functions:
private def normalizeDateTime( dt : DateTime ) : DateMidnight = ???
private def requiredBetweens( start : DateMidnight, end : DateMidnight ) : Seq[DateMidnight] = ???
Then you could write your function as follows:
def checkDate(start: DateTime, end: DateTime, between: IndexedSeq[DateTime]): Boolean = {
val startDay = normalizeDateTime( start )
val endDay = normalizeDateTime( end )
val available = between.map( normalizeDateTime ).toSet
val required = requiredBetweens( startDay, endDay ).toSet
val unavailable = (required -- available)
unavailable.isEmpty
}
Note that this function imposes no requirement as to the ordering of the betweens, treats the elements as a Set, only requiring that each day be available somewhere.
To implement normalizeDateTime(...) you might get away with something as simple as dt.toDateMidnight, but you should think a bit about Chronology and time zone issues. It's critical that DateTime objects that you mean to represent a day always normalize to the same DateMidnight.
To implement requiredBetweens(...), you might consider using a Stream and takeWhile(...) for an elegant solution. You might want to require that (end isAfter start).

I would use filter and then zip and take the difference, the dates should always be one day apart, so check they are all 1.
# val ls = Array(1, 2, 3, 4, 5, 6, 7) // can use dates in the same way
ls: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7)
# val ls2 = ls.filter { i => (2 < i) && (i < 6) }
ls2: Array[Int] = Array(3, 4, 5)
# ls2.zip(ls2.drop(1))
res21: Array[(Int, Int)] = Array((3, 4), (4, 5))
# ls2.zip(ls2.drop(1)).map { case (x, y) => y-x }
res22: Array[Int] = Array(1, 1)
# ls2.zip(ls2.drop(1)).map { case (x, y) => y-x }.forall { _ == 1 }
res23: Boolean = true
You also have to check that no dates are missing:
# ls2.length == 6 - 2 - 1 // beware off-by-one errors
res25: Boolean = true
You may also be able to do this more simply by using the Range object:
# ls2.zipAll(3 to 5 by 1, 0, 0).forall { case (x, y) => x == y }
res46: Boolean = true
This should work, but may need a slight tweak for DateTime...
# val today = LocalDate.now
today: LocalDate = 2017-10-19
# val a = (0 to 9).reverse.map { today.minusDays(_) }
a: collection.immutable.IndexedSeq[LocalDate] = Vector(2017-10-10, 2017-10-11, 2017-10-12, 2017-10-13, 2017-10-14, 2017-10-15, 2017-10-16, 2017-10-17, 2017-10-18, 2017-10-19)
# a.zip(a.drop(1)).map { case (x, y) => x.until(y) }.forall { _ == Period.ofDays(1) }
res71: Boolean = true

Solution with tail recursion. I'm using ZonedDateTime from Java 8 for DateTime representation. Here is online version on codepad.remoteinterview.io:
import scala.annotation.tailrec
import java.time.ZonedDateTime
object TailRecursionExample {
def checkDate(start: ZonedDateTime, end: ZonedDateTime,
between: Seq[ZonedDateTime]): Boolean = {
// We have dates in range (inclusive) [start, end] with step = 1 day
// All these days should be in between collection
// set for fast lookup
val set = between.toSet
#tailrec
def checkDate(curr: ZonedDateTime, iterations: Int): (Int, Boolean) = {
if (curr.isAfter(end)) (iterations, true)
else if (set.contains(curr)) checkDate(curr.plusDays(1), iterations + 1)
else (iterations, false)
}
val (iterations, result) = if (start.isAfter(end))
(0, false)
else
checkDate(start, 0)
println(s"\tNum of iterations: $iterations")
result
}
def main(args: Array[String]): Unit = {
testWhenStartIsAfterEnd()
println
testWhenStartIsBeforeEnd()
println
testWhenStartIsBeforeEndButBetweenSkipOneDay()
println
()
}
def testWhenStartIsAfterEnd(): Unit = {
val start = ZonedDateTime.now().plusDays(5)
val end = ZonedDateTime.now()
val between = (0 to 5).map(i => start.plusDays(i))
verboseTest("testWhenStartIsAfterEnd", start, end, between)
}
def testWhenStartIsBeforeEnd(): Unit = {
val start = ZonedDateTime.now().minusDays(5)
val end = ZonedDateTime.now()
val between = (0 to 5).map(i => start.plusDays(i))
verboseTest("testWhenStartIsBeforeEnd", start, end, between)
}
def testWhenStartIsBeforeEndButBetweenSkipOneDay(): Unit = {
val start = ZonedDateTime.now().minusDays(5)
val end = ZonedDateTime.now()
val between = (1 to 5).map(i => start.plusDays(i))
verboseTest("testWhenStartIsBeforeEndButBetweenSkipOneDay", start, end, between)
}
def verboseTest(name: String, start: ZonedDateTime, end: ZonedDateTime,
between: Seq[ZonedDateTime]): Unit = {
println(s"$name:")
println(s"\tStart: $start")
println(s"\tEnd: $end")
println(s"\tBetween: ")
between.foreach(t => println(s"\t\t$t"))
println(s"\tcheckDate: ${checkDate(start, end, between)}")
}
}

Related

Scala - Perfect Number usage in higher order function - anything wrong?

Apologies , but am new to scala... learning it, now.
I have been trying to complete a excercise where the ask was as follows :-
// Write a function isPerfectNumber which takes integer input and returns String output.
// It finds if a number is perfect, and returns true if perfect, else returns false
// Write a higher order function myHigherOrderFunction which takes isPerfectNumber and intList as input, and returns a List of Strings which contain the output if the number is perfect or not using map.
Perfect Number :
https://rosettacode.org/wiki/Perfect_numbers
just go to the scala section
My Code :
object ListMapHigherOrder{
def main(args:Array[String])
{
val intRes = args.toList
val intList: List[Int] = intRes.map(_.toInt).toList
def isPerfectNumber(input: Int) :String =
{
var check_sum = ( (2 to math.sqrt(input).toInt).collect { case x if input % x == 0 => x + input / x} ).sum
if ( check_sum == input - 1 )
return "true"
else
return "false"
}
def myHigherOrderFunction(argFn: Int => String, argVal:List[Int]): List[String] = { argVal.map(argFn) }
println(myHigherOrderFunction(isPerfectNumber, intList))
}
}
Code execution : scala ScalaExcercise12.scala 1 6 13
Expected Output : List(false , true , false)
the code gives expected output, am not sure how the backend testing is being done.... it just dosent pass the test.
Is there any issue with the code? - i did like to fix it , but cant i see anything wrong/missing especially because i am getting the same output as desired :(
object ListMapHigherOrder{
def main(args:Array[String])
{
val intRes = args.toList
val intList: List[Int] = intRes.map(x=>x.toInt)
def isPerfectNumber(input: Int) :String =
{
var sum = 0
for(i <- 1 until input){
if(input % i == 0)
sum = sum+i
}
if ( sum == input )
return "true"
else
return "false"
}
def myHigherOrderFunction(argFn: Int => String, argVal:List[Int]): List[String] = { argVal.map(argFn) }
println(myHigherOrderFunction(isPerfectNumber, intList))
}
}
**This worked for me

Scala String Equality Question from Programming Interview

Since I liked programming in Scala, for my Google interview, I asked them to give me a Scala / functional programming style question. The Scala functional style question that I got was as follows:
You have two strings consisting of alphabetic characters as well as a special character representing the backspace symbol. Let's call this backspace character '/'. When you get to the keyboard, you type this sequence of characters, including the backspace/delete character. The solution you are to implement must check if the two sequences of characters produce the same output. For example, "abc", "aa/bc". "abb/c", "abcc/", "/abc", and "//abc" all produce the same output, "abc". Because this is a Scala / functional programming question, you must implement your solution in idiomatic Scala style.
I wrote the following code (it might not be exactly what I wrote, I'm just going off memory). Basically I just go linearly through the string, prepending characters to a list, and then I compare the lists.
def processString(string: String): List[Char] = {
string.foldLeft(List[Char]()){ case(accumulator: List[Char], char: Char) =>
accumulator match {
case head :: tail => if(char != '/') { char :: head :: tail } else { tail }
case emptyList => if(char != '/') { char :: emptyList } else { emptyList }
}
}
}
def solution(string1: String, string2: String): Boolean = {
processString(string1) == processString(string2)
}
So far so good? He then asked for the time complexity and I responded linear time (because you have to process each character once) and linear space (because you have to copy each element into a list). Then he asked me to do it in linear time, but with constant space. I couldn't think of a way to do it that was purely functional. He said to try using a function in the Scala collections library like "zip" or "map" (I explicitly remember him saying the word "zip").
Here's the thing. I think that it's physically impossible to do it in constant space without having any mutable state or side effects. Like I think that he messed up the question. What do you think?
Can you solve it in linear time, but with constant space?
This code takes O(N) time and needs only three integers of extra space:
def solution(a: String, b: String): Boolean = {
def findNext(str: String, pos: Int): Int = {
#annotation.tailrec
def rec(pos: Int, backspaces: Int): Int = {
if (pos == 0) -1
else {
val c = str(pos - 1)
if (c == '/') rec(pos - 1, backspaces + 1)
else if (backspaces > 0) rec(pos - 1, backspaces - 1)
else pos - 1
}
}
rec(pos, 0)
}
#annotation.tailrec
def rec(aPos: Int, bPos: Int): Boolean = {
val ap = findNext(a, aPos)
val bp = findNext(b, bPos)
(ap < 0 && bp < 0) ||
(ap >= 0 && bp >= 0 && (a(ap) == b(bp)) && rec(ap, bp))
}
rec(a.size, b.size)
}
The problem can be solved in linear time with constant extra space: if you scan from right to left, then you can be sure that the /-symbols to the left of the current position cannot influence the already processed symbols (to the right of the current position) in any way, so there is no need to store them.
At every point, you need to know only two things:
Where are you in the string?
How many symbols do you have to throw away because of the backspaces
That makes two integers for storing the positions, and one additional integer for temporary storing the number of accumulated backspaces during the findNext invocation. That's a total of three integers of space overhead.
Intuition
Here is my attempt to formulate why the right-to-left scan gives you a O(1) algorithm:
The future cannot influence the past, therefore there is no need to remember the future.
The "natural time" in this problem flows from left to right. Therefore, if you scan from right to left, you are moving "from the future into the past", and therefore you don't need to remember the characters to the right of your current position.
Tests
Here is a randomized test, which makes me pretty sure that the solution is actually correct:
val rng = new util.Random(0)
def insertBackspaces(s: String): String = {
val n = s.size
val insPos = rng.nextInt(n)
val (pref, suff) = s.splitAt(insPos)
val c = ('a' + rng.nextInt(26)).toChar
pref + c + "/" + suff
}
def prependBackspaces(s: String): String = {
"/" * rng.nextInt(4) + s
}
def addBackspaces(s: String): String = {
var res = s
for (i <- 0 until 8)
res = insertBackspaces(res)
prependBackspaces(res)
}
for (i <- 1 until 1000) {
val s = "hello, world"
val t = "another string"
val s1 = addBackspaces(s)
val s2 = addBackspaces(s)
val t1 = addBackspaces(t)
val t2 = addBackspaces(t)
assert(solution(s1, s2))
assert(solution(t1, t2))
assert(!solution(s1, t1))
assert(!solution(s1, t2))
assert(!solution(s2, t1))
assert(!solution(s2, t2))
if (i % 100 == 0) {
println(s"Examples:\n$s1\n$s2\n$t1\n$t2")
}
}
A few examples that the test generates:
Examples:
/helly/t/oj/m/, wd/oi/g/x/rld
///e/helx/lc/rg//f/o, wosq//rld
/anotl/p/hhm//ere/t/ strih/nc/g
anotx/hb/er sw/p/tw/l/rip/j/ng
Examples:
//o/a/hellom/, i/wh/oe/q/b/rld
///hpj//est//ldb//y/lok/, world
///q/gd/h//anothi/k/eq/rk/ string
///ac/notherli// stri/ig//ina/n/g
Examples:
//hnn//ello, t/wl/oxnh///o/rld
//helfo//u/le/o, wna//ova//rld
//anolq/l//twl//her n/strinhx//g
/anol/tj/hq/er swi//trrq//d/ing
Examples:
//hy/epe//lx/lo, wr/v/t/orlc/d
f/hk/elv/jj//lz/o,wr// world
/anoto/ho/mfh///eg/r strinbm//g
///ap/b/notk/l/her sm/tq/w/rio/ng
Examples:
///hsm/y//eu/llof/n/, worlq/j/d
///gx//helf/i/lo, wt/g/orn/lq/d
///az/e/notm/hkh//er sm/tb/rio/ng
//b/aen//nother v/sthg/m//riv/ng
Seems to work just fine. So, I'd say that the Google-guy did not mess up, looks like a perfectly valid question.
You don't have to create the output to find the answer. You can iterate the two sequences at the same time and stop on the first difference. If you find no difference and both sequences terminate at the same time, they're equal, otherwise they're different.
But now consider sequences such as this one: aaaa/// to compare with a. You need to consume 6 elements from the left sequence and one element from the right sequence before you can assert that they're equal. That means that you would need to keep at least 5 elements in memory until you can verify that they're all deleted. But what if you iterated elements from the end? You would then just need to count the number of backspaces and then just ignoring as many elements as necessary in the left sequence without requiring to keep them in memory since you know they won't be present in the final output. You can achieve O(1) memory using these two tips.
I tried it and it seems to work:
def areEqual(s1: String, s2: String) = {
def charAt(s: String, index: Int) = if (index < 0) '#' else s(index)
#tailrec
def recSol(i1: Int, backspaces1: Int, i2: Int, backspaces2: Int): Boolean = (charAt(s1, i1), charAt(s2, i2)) match {
case ('/', _) => recSol(i1 - 1, backspaces1 + 1, i2, backspaces2)
case (_, '/') => recSol(i1, backspaces1, i2 - 1, backspaces2 + 1)
case ('#' , '#') => true
case (ch1, ch2) =>
if (backspaces1 > 0) recSol(i1 - 1, backspaces1 - 1, i2 , backspaces2 )
else if (backspaces2 > 0) recSol(i1 , backspaces1 , i2 - 1, backspaces2 - 1)
else ch1 == ch2 && recSol(i1 - 1, backspaces1 , i2 - 1, backspaces2 )
}
recSol(s1.length - 1, 0, s2.length - 1, 0)
}
Some tests (all pass, let me know if you have more edge cases in mind):
// examples from the question
val inputs = Array("abc", "aa/bc", "abb/c", "abcc/", "/abc", "//abc")
for (i <- 0 until inputs.length; j <- 0 until inputs.length) {
assert(areEqual(inputs(i), inputs(j)))
}
// more deletions than required
assert(areEqual("a///////b/c/d/e/b/b", "b"))
assert(areEqual("aa/a/a//a//a///b", "b"))
assert(areEqual("a/aa///a/b", "b"))
// not enough deletions
assert(!areEqual("aa/a/a//a//ab", "b"))
// too many deletions
assert(!areEqual("a", "a/"))
PS: just a few notes on the code itself:
Scala type inference is good enough so that you can drop types in the partial function inside your foldLeft
Nil is the idiomatic way to refer to the empty list case
Bonus:
I had something like Tim's soltion in mind before implementing my idea, but I started early with pattern matching on characters only and it didn't fit well because some cases require the number of backspaces. In the end, I think a neater way to write it is a mix of pattern matching and if conditions. Below is my longer original solution, the one I gave above was refactored laater:
def areEqual(s1: String, s2: String) = {
#tailrec
def recSol(c1: Cursor, c2: Cursor): Boolean = (c1.char, c2.char) match {
case ('/', '/') => recSol(c1.next, c2.next)
case ('/' , _) => recSol(c1.next, c2 )
case (_ , '/') => recSol(c1 , c2.next)
case ('#' , '#') => true
case (a , b) if (a == b) => recSol(c1.next, c2.next)
case _ => false
}
recSol(Cursor(s1, s1.length - 1), Cursor(s2, s2.length - 1))
}
private case class Cursor(s: String, index: Int) {
val char = if (index < 0) '#' else s(index)
def next = {
#tailrec
def recSol(index: Int, backspaces: Int): Cursor = {
if (index < 0 ) Cursor(s, index)
else if (s(index) == '/') recSol(index - 1, backspaces + 1)
else if (backspaces > 1) recSol(index - 1, backspaces - 1)
else Cursor(s, index - 1)
}
recSol(index, 0)
}
}
If the goal is minimal memory footprint, it's hard to argue against iterators.
def areSame(a :String, b :String) :Boolean = {
def getNext(ci :Iterator[Char], ignore :Int = 0) : Option[Char] =
if (ci.hasNext) {
val c = ci.next()
if (c == '/') getNext(ci, ignore+1)
else if (ignore > 0) getNext(ci, ignore-1)
else Some(c)
} else None
val ari = a.reverseIterator
val bri = b.reverseIterator
1 to a.length.max(b.length) forall(_ => getNext(ari) == getNext(bri))
}
On the other hand, when arguing FP principals it's hard to defend iterators, since they're all about maintaining state.
Here is a version with a single recursive function and no additional classes or libraries. This is linear time and constant memory.
def compare(a: String, b: String): Boolean = {
#tailrec
def loop(aIndex: Int, aDeletes: Int, bIndex: Int, bDeletes: Int): Boolean = {
val aVal = if (aIndex < 0) None else Some(a(aIndex))
val bVal = if (bIndex < 0) None else Some(b(bIndex))
if (aVal.contains('/')) {
loop(aIndex - 1, aDeletes + 1, bIndex, bDeletes)
} else if (aDeletes > 0) {
loop(aIndex - 1, aDeletes - 1, bIndex, bDeletes)
} else if (bVal.contains('/')) {
loop(aIndex, 0, bIndex - 1, bDeletes + 1)
} else if (bDeletes > 0) {
loop(aIndex, 0, bIndex - 1, bDeletes - 1)
} else {
aVal == bVal && (aVal.isEmpty || loop(aIndex - 1, 0, bIndex - 1, 0))
}
}
loop(a.length - 1, 0, b.length - 1, 0)
}

is it possible to write functional version for below imperative code in scala

I wrote sum code in scala to find the majority element(the element which appears more than n/2 times where 'n' is the no.of elements in an array.I want to know where there is functional / scala native style of version(which includes match cases and transformations like "map/"flatmap" etc..) for the below imperative style of scala code which includes looping. The code which i used in:
object MajorityElement{
def printMajority(arr:Array[Int]) ={
var cand:Int=findCandidate(arr);
if(isMajority(arr,cand))
println(cand);
else
println("No Majority Element");
}
def isMajority(arr:Array[Int],Cand:Int):Boolean ={
var count=0;
for(i <- 0 until arr.length){
if(arr(i)== Cand)
count+=1;
}
if (count > arr.size/2)
return true;
else false
}
def findCandidate(arr:Array[Int]):Int ={
val s = arr.size
var majIndex:Int = 0;
var count = 1;
for(i <- 0 until arr.length){
if(arr(majIndex) == arr(i))
count+=1;
else
count-=1;
if(count==0)
{
majIndex = i;
count =1
}
}
return arr(majIndex);
}
}
please let me know, whether it is possible to write/ convert imperative style to functional version in scala(which uses match cases) for any scenario.
If you're only interested in the final result (and so you don't need isMajority etc), it's very simple
def findMajority(xs: List[Int]) = {
val mostFrequent = xs.groupBy(identity).values.maxBy(_.length)
if (mostFrequent.length >= xs.length / 2) Some(mostFrequent.head) else None
}
findMajority(List(1, 2, 2, 2, 3, 3, 3, 3, 3, 4))
//Option[Int] = Some(3)
Group equal elements into lists (the values of the Map returned by GroupBy). Pick the longest list. If its length is more than half the list, then it's a majority, return Some(the head) (any element will do, they're all the same value). Otherwise, return None
The transition from imperative thinking to functional thinking takes time and study. One approach is to find code examples here on SO and, with the help of the Standard Library, break it down until you understand what's going on.
Here's a little something to get you started.
def isMajority(arr:Array[Int],cand:Int):Boolean =
arr.count(_ == cand) > arr.size/2
Threr is no Native Scala Style, but code can be Functional Style(value oriented)
(No var, No Side-Effect, Pure Function)
object MajorityElement {
case class Candidate(idx: Int, count: Int)
def solve(arr: Array[Int]): Option[Int] = {
val candidate = findCandidate(arr)
if (isMajority(arr, candidate)) Option(arr(candidate.idx))
else None
}
def isMajority(arr: Array[Int], candidate: Candidate) =
arr.count(_ == arr(candidate.idx)) > arr.size / 2
def findCandidate(arr: Array[Int]): Candidate =
arr.indices.foldLeft(Candidate(0, 1)) { (acc, idx) =>
val newAcc =
if (arr(acc.idx) == arr(idx)) acc.copy(count = acc.count + 1)
else acc.copy(count = acc.count - 1)
if (newAcc.count == 0) Candidate(idx, 1)
else newAcc
}
}
val arr = Array(1, 1, 1, 2, 3, 4, 1)
val ret = MajorityElement.solve(arr)
ret match {
case Some(n) => println(s"Found Majority Element: $n")
case None => println("No Majority Element")
}

'forward reference extends over definition of variable dateList' while generating daterange

I am trying to make an List of all dates between 2 given dates in scala. This is the program that I have written:
object testingscala
{
def main(args: Array[String])
{
println(calculateDates(LocalDate.of(2014,1,1), LocalDate.of(2014,2,5)))
}
def calculateDates(from: LocalDate, until: LocalDate): List[LocalDate] =
{
var arr = List[LocalDate]()
var dateList = calculateDatesRecur(from, until) // forward reference extends over definition of variable
dateList
def calculateDatesRecur(from: LocalDate, until: LocalDate): List[LocalDate] =
{
if (from.compareTo(until) > 1) {return arr}
else
{ arr = arr :+ from; calculateDatesRecur(from.plusDays(1), until)}
}
return dateList
}
}
I am relatively new at Scala so I am not able to figure out what is wrong with the implementation.
The function just takes two parameters and prints out all the dates between the two dates. I have used recursion.
That is because Scala have no literal syntax for arrays/lists. You have to go with
var arr = List.empty[LocalDate]
or
var arr = List[LocalDate]()
Not that list isn't array in scala.
Although you haven't asked, I do believe this code could be written in a much more concise way:
object testingscala extends App
{
type LD = LocalDate
println(calculateDatesRecur(LocalDate.of(2014,1,1), LocalDate.of(2014,2,5)))
#annotation.tailrec
def calculateDatesRecur(from: LD, until: LD, xs: List[LD] = List.empty[LD]): List[LD] =
if (from.compareTo(until) > 1) xs.reverse
else calculateDatesRecur(from.plusDays(1), until, from::xs)
}
Haven't tested it though.
And answering your comment:
swap recursive function and dateList variable, so function definition comes first.
...
def calculateDatesRecur(from: LocalDate, until: LocalDate): List[LocalDate] =
{
if (from.compareTo(until) > 1) {return arr}
else
{ arr = arr :+ from; calculateDatesRecur(from.plusDays(1), until)}
}
var dateList = calculateDatesRecur(from, until)
...
you're trying to assign function result, but since it is used like a nested function it is not known apriory so compiler don't know what to set to dateList (actually it do knows, but prevents you from doing nasty things).
Similar to Given a range, getting all dates within that range in Scala
With Lamma Date simply (2014, 5, 5) to (2014, 5, 10) foreach println

Is there a combination of foldLeft and for-yield?

I must handle with sequences of orders (here Int for simplification):
// the handleOrder methods are in fact much more complicated:
def handleOrders(prev: Double, orders: Seq[Int]): Double = prev + orders.sum
def handleOrder(prev: Double, order: Int): Double = prev / order
As a result from a so called
def nextGroup(prev: Double, orders: Seq[Int]): Seq[Double]
function I get a sequence of another class (here Double for simplification).
From this I've implemented two versions.
Version 1 (foldLeft and explicit builder):
def nextGroup1(prev: Double, orders: Seq[Int]): Seq[Double] = {
import collection.mutable.Builder
import collection.immutable.VectorBuilder
val bld: Builder[Double, Seq[Double]] = new VectorBuilder[Double]
var first = true
orders.foldLeft(prev) { (prev, order) =>
val step = if (first) handleOrders(prev, orders) else prev
val next = handleOrder(step, order)
first = false
bld += next
next
}
bld.result
}
Version 2 (var and for yield builder):
def nextGroup2(prev: Double, orders: Seq[Int]): Seq[Double] = {
var first = true
var präv = prev
for (order <- orders) yield {
if (first) präv = handleOrders(präv, orders)
präv = handleOrder(präv, order)
first = false
präv
}
}
I'd like to save either explicit builder in version 1 or mutable var in version 2.
Is this possible? Perhaps with a combination of foldLeft and for-yield?
And still something sample data:
val orders = Seq(1, 2, 3)
nextGroup1(1d, orders) // => Vector(7.0, 3.5, 1.1666666666666667)
nextGroup2(1d, orders) // => List(7.0, 3.5, 1.1666666666666667)
nextGroup1(2d, orders) // => Vector(8.0, 4.0, 1.3333333333333333)
nextGroup2(2d, orders) // => List(8.0, 4.0, 1.3333333333333333)
The nextGroup results handled as Seq[Double], so Vector or List is no difference.
orders.tail.scanLeft(handleOrders(prev, orders)) { (p, o) => handleOrder(p, o) }
scanLeft does the same as foldLeft does but keeps all intermediate results. You can get rid of the special case by excluding the head of the collection which you can do using orders.tail.