Scala downwards or decreasing for loop? - scala

In Scala, you often use an iterator to do a for loop in an increasing order like:
for(i <- 1 to 10){ code }
How would you do it so it goes from 10 to 1? I guess 10 to 1 gives an empty iterator (like usual range mathematics)?
I made a Scala script which solves it by calling reverse on the iterator, but it's not nice in my opinion, is the following the way to go?
def nBeers(n:Int) = n match {
case 0 => ("No more bottles of beer on the wall, no more bottles of beer." +
"\nGo to the store and buy some more, " +
"99 bottles of beer on the wall.\n")
case _ => (n + " bottles of beer on the wall, " + n +
" bottles of beer.\n" +
"Take one down and pass it around, " +
(if((n-1)==0)
"no more"
else
(n-1)) +
" bottles of beer on the wall.\n")
}
for(b <- (0 to 99).reverse)
println(nBeers(b))

scala> 10 to 1 by -1
res1: scala.collection.immutable.Range = Range(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

The answer from #Randall is good as gold, but for sake of completion I wanted to add a couple of variations:
scala> for (i <- (1 to 10).reverse) {code} //Will count in reverse.
scala> for (i <- 10 to(1,-1)) {code} //Same as with "by", just uglier.

Scala provides many ways to work on downwards in loop.
1st Solution: with "to" and "by"
//It will print 10 to 0. Here by -1 means it will decremented by -1.
for(i <- 10 to 0 by -1){
println(i)
}
2nd Solution: With "to" and "reverse"
for(i <- (0 to 10).reverse){
println(i)
}
3rd Solution: with "to" only
//Here (0,-1) means the loop will execute till value 0 and decremented by -1.
for(i <- 10 to (0,-1)){
println(i)
}

Having programmed in Pascal, I find this definition nice to use:
implicit class RichInt(val value: Int) extends AnyVal {
def downto (n: Int) = value to n by -1
def downtil (n: Int) = value until n by -1
}
Used this way:
for (i <- 10 downto 0) println(i)

You can use Range class:
val r1 = new Range(10, 0, -1)
for {
i <- r1
} println(i)

You can use :
for (i <- 0 to 10 reverse) println(i)

for (i <- 10 to (0,-1))
The loop will execute till the value == 0, decremented each time by -1.

Related

Code efficiency in Scala loops, counting up or counting down?

Clearly, if you need to count up, count up. If you need to count down, count down. However, other things being equal, is one faster than the other?
Here is my Scala code for a well-known puzzle - checking if a number is divisible by 13.
In the first example, I reverse my array and count upwards in the subsequent for-loop. In the second example I leave the array alone and do a decrementing for-loop. On the surface, the second example looks faster. Unfortunately, on the site where I run the code, it always times out.
// works every time
object Thirteen {
import scala.annotation.tailrec
#tailrec
def thirt(n: Long): Long = {
val getNum = (n: Int) => Array(1, 10, 9, 12, 3, 4)(n % 6)
val ni = n.toString.split("").reverse.map(_.toInt)
var s: Long = 0
for (i <- 0 to ni.length-1) {
s += ni(i) * getNum(i)
}
if (s == n) s else thirt(s)
}
}
// times out every time
object Thirteen {
import scala.annotation.tailrec
#tailrec
def thirt(n: Long): Long = {
val getNum = (n: Int) => Array(1, 10, 9, 12, 3, 4)(n % 6)
val ni = n.toString.split("").map(_.toInt)
var s: Long = 0
for (i <- ni.length-1 to 0 by -1) {
s = s + ni(i) * getNum(i)
}
if (s == n) s else thirt(s)
}
}
I ask the following questions:
Is there an obvious rule I am unaware of?
What is an easy way to test two code versions for performance – reliably measuring performance in the JVM appears difficult.
Does it help to look at the underlying byte code?
Is there a better piece of code solving
the same problem, If so, I'd be very grateful to see it.
Whilst I've seen similar questions, I can't find a definitive answer.
Here's how I'd be tempted to tackle it.
val nums :Stream[Int] = 1 #:: 10 #:: 9 #:: 12 #:: 3 #:: 4 #:: nums
def thirt(n :Long) :Long = {
val s :Long = Stream.iterate(n)(_ / 10)
.takeWhile(_ > 0)
.zip(nums)
.foldLeft(0L){case (sum, (i, num)) => sum + i%10 * num}
if (s == n) s else thirt(s)
}

How to print a value outside a for loop in scala?

I am new to scala and would like to know way to access val which is defined inside for loop and would like to write that val to a file outside for loop.
def time[A](logFile: String, description: String)(job: => A): Unit = {
var totalDuration: Long = 0
for (i <- 1 to 3) {
val currentTime = System.currentTimeMillis
val result = job
val finalTime = System.currentTimeMillis
val duration = finalTime - currentTime
totalDuration = if (totalDuration == 0) duration else totalDuration.min(duration)
}
val pw = new PrintWriter(new FileOutputStream(new File(logFile),true))
pw.write(description + " " + result + " " + totalDuration +" ms"+"\n")
pw.flush()
pw.close
}
In the above code i am calculating my result which contains the length of bytes read from other function and would like to calculate the time it takes to read the total bytes. I would like to iterate 3 times and take the minimum of all the three. The val result contains the bytes length which also needs to be written in a file. i get a error because i am accessing the result val outside the scope of for loop. Can someone please help me solve this error. How can i access the val result outside for loop to write it to a file ?
Thanks in advance!!
While your question is answered, the for loop is not in it's typical form, which would look more like this:
def time[A] (logFile: String, description: String) (job: => A): Unit = {
val (result, totalDuration): (A, Long) = (for { i <- 1 to 3
currentTime = System.currentTimeMillis
result = job
finalTime = System.currentTimeMillis
duration = finalTime - currentTime
} yield (result, duration)).minBy {case (r, d) => d}
val pw = new PrintWriter (new FileOutputStream (new File (logFile), true))
pw.write (description + " " + result + " " + totalDuration +" ms"+"\n")
pw.flush()
pw.close
}
If I understood your code correctly. I don't know whether a side effect yields to different results for each job invocation.
I missed the internal discussion of the for-loop invention/definition, why the keyword val should be omitted here, but it is quiet handy.
What is more important, is, that you usually have all temporary assignments in the for (...(here part)...) { not here}. The consequences of round or curly braces in the first part aren't totally clear to me, but if you use round parens, you have terminate most statements with a semicolon.
scala> for (i <- 1 to 3;
| j <- 4 to 5;
| k = j-i;
| l = k/2) yield l * l;
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 0, 1)
Note that neither i, nor j, k, l where declared as val or var.
scala> for {i <- 1 to 3
| j <- 4 to 5
| k = j-i
| l = k/2} yield l * l;
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 0, 1)
You will find multiple questions here, which explain, how a for-loop is and can be translatet to a flatMap/map-combination, eventually with filter:
scala> for {i <- 1 to 3
| j <- 4 to 5
| k = j-i
| if (k > 1)
| l = k/2 } yield l * l;
res5: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 1)
And instead of yielding just one value, you can yield a tuple, and assign by
val (a:X, b:Y) = (for ..... yield (aa, bb))
The
yield (result, duration)).minBy {case (r, d) => d}
takes a tuple (result, duration) and selects the minimum by duration, but yields both values.
you can use yield. Yield will return data from for loop after completion of loop and use that data accordingly. Since I do not have your code. see this example
val j = for (i <- 1 to 10) yield i
println(j)
output of j will be
Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
For replacing your for loop to calculate the total duration of some jobs that are executed sequentially, you could use foldLeft
Make use of yield or you can use any of the fold method. Or if you are good with recursion you can use a tailrec method which returns what is Desired. Yield is the most simplest way to do it.
val answer = for(i<- 1 to 10) yield i
println(answer) // Vector(1,2,3,4,5,6,7,8,9,10)

Acting on inner and outer loops for multidimensional array in idiomatic scala

I have this nested loop:
for ( y <- 0 to 5) {
for ( x <- 0 to 5) {
print(x, y)
}
println()
}
Is there a cleaner way of expressing this in scala -- bearing in mind I want to do something once for every outer loop iteration, as well as the internal?
The following is the closest I've got:
for {
y <- 0 to 5
x <- 0 to 5
} {
print (x, y) + " "
if(x == 5) println()
}
for {
y <- 0 to 5
x <- 0 to 5
_ = if (x ==5) println()
} print(x, y)
Seems like the most concise way to me.
I don't think for comprehensions are a good option here, why not just use foreach? like this:
(0 to 5).foreach{ y =>
(0 to 5).foreach{ x =>
print (x, y) + " "
}
println()
}

Basic Scala for loop Issue

I am trying to learn scala, here I am using basic for loop, but I am getting errors while compiling.
object App {
def main(args: Array[String]) {
for (i <- 1 to 10; i % 2 == 0)
Console.println("Counting " + i)
}
}
Errors while compiling :
fortest.scala:5: error: '<-' expected but ')' found.
for (i <- 1 to 10; i % 2 == 0)
^
fortest.scala:7: error: illegal start of simple expression
}
^
two errors found
I am using scala version 2.9.1
Any idea what is the problem..............?
for (i <- 1 to 10 if i % 2 == 0)
println("Counting " + i)
Scala is not Java, thus you cannot use a regular Java syntax. Instead you have to do:
for{
i <- 1 to 10
if(i % 2 == 0)
}{println("Counting " + i)}
or with ; delimeters, inside the (,) parentheses:
for(i <- 1 to 10;if(i % 2 == 0)){
println("Counting " + i)
}
Also, note that Scala's for expressions, have some pretty nifty capabilities.
you can use a for expression with multiple "loop iterators" and conditions.
For instance, instead of writing:
for(i <- 1 to n; if(someCondition(i)){
for(j <- 1 to m; if(otherCondition(j)){
//Do something
}
}
You can simply write:
for{
i <- 1 to n
if(someCondition(i))
j <- 1 to m
if(otherCondition(j))
}{
//Do something
}
SIDE NOTE:
When you extend App (there's a trait of that name in Predef), you don't need to define a main method. You can simply write your code between the curly braces of object:
object MyClazz extends App {
for(i <- 1 to 10;if(i % 2 == 0)){
println("Counting " + i)
}
}
Take a look at the "by" method of the Range class to count by 2
object App {
def main(args: Array[String]) {
for (i <- 2 to 10 by 2)
Console.println("Counting " + i)
}
}
Or, like others have already stated you can fix your loop by doing
object App {
def main(args: Array[String]) {
for {
i <- 1 to 10
if i % 2 == 0
}
Console.println("Counting " + i)
}
}
Or another way:
object App {
def main(args: Array[String]) {
val evenNumbers = for {
i <- 1 to 10
if i % 2 == 0
} yield i
Console.println(evenNumbers.mkString("\n"))
}
}
The modulo 2 condition can be moved to an if clause.
object App {
def main(args: Array[String]) {
for (i <- 1 to 10)
if(i % 2 == 0)
Console.println("Counting " + i)
}
}
Here is the simply example;
for (i <- List(1, 2, 3) if i < 2) println(i)
The best way to exam your code is to use scala shell.
Basically, you are trying to use for-loop + iterator gaurd. Please find below syntax
for ( i <- 1 to 10 if (i%2==0) ) yield i

help rewriting in functional style

I'm learning Scala as my first functional-ish language. As one of the problems, I was trying to find a functional way of generating the sequence S up to n places. S is defined so that S(1) = 1, and S(x) = the number of times x appears in the sequence. (I can't remember what this is called, but I've seen it in programming books before.)
In practice, the sequence looks like this:
S = 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7 ...
I can generate this sequence pretty easily in Scala using an imperative style like this:
def genSequence(numItems: Int) = {
require(numItems > 0, "numItems must be >= 1")
var list: List[Int] = List(1)
var seq_no = 2
var no = 2
var no_nos = 0
var num_made = 1
while(num_made < numItems) {
if(no_nos < seq_no) {
list = list :+ no
no_nos += 1
num_made += 1
} else if(no % 2 == 0) {
no += 1
no_nos = 0
} else {
no += 1
seq_no += 1
no_nos = 0
}
}
list
}
But I don't really have any idea how to write this without using vars and the while loop.
Thanks!
Pavel's answer has come closest so far, but it's also inefficient. Two flatMaps and a zipWithIndex are overkill here :)
My understanding of the required output:
The results contain all the positive integers (starting from 1) at least once
each number n appears in the output (n/2) + 1 times
As Pavel has rightly noted, the solution is to start with a Stream then use flatMap:
Stream from 1
This generates a Stream, a potentially never-ending sequence that only produces values on demand. In this case, it's generating 1, 2, 3, 4... all the way up to Infinity (in theory) or Integer.MAX_VALUE (in practice)
Streams can be mapped over, as with any other collection. For example: (Stream from 1) map { 2 * _ } generates a Stream of even numbers.
You can also use flatMap on Streams, allowing you to map each input element to zero or more output elements; this is key to solving your problem:
val strm = (Stream from 1) flatMap { n => Stream.fill(n/2 + 1)(n) }
So... How does this work? For the element 3, the lambda { n => Stream.fill(n/2 + 1)(n) } will produce the output stream 3,3. For the first 5 integers you'll get:
1 -> 1
2 -> 2, 2
3 -> 3, 3
4 -> 4, 4, 4
5 -> 5, 5, 5
etc.
and because we're using flatMap, these will be concatenated, yielding:
1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, ...
Streams are memoised, so once a given value has been calculated it'll be saved for future reference. However, all the preceeding values have to be calculated at least once. If you want the full sequence then this won't cause any problems, but it does mean that generating S(10796) from a cold start is going to be slow! (a problem shared with your imperative algorithm). If you need to do this, then none of the solutions so far is likely to be appropriate for you.
The following code produces exactly the same sequence as yours:
val seq = Stream.from(1)
.flatMap(Stream.fill(2)(_))
.zipWithIndex
.flatMap(p => Stream.fill(p._1)(p._2))
.tail
However, if you want to produce the Golomb sequence (that complies with the definition, but differs from your sample code result), you may use the following:
val seq = 1 #:: a(2)
def a(n: Int): Stream[Int] = (1 + seq(n - seq(seq(n - 2) - 1) - 1)) #:: a(n + 1)
You may check my article for more examples of how to deal with number sequences in functional style.
Here is a translation of your code to a more functional style:
def genSequence(numItems: Int): List[Int] = {
genSequenceR(numItems, 2, 2, 0, 1, List[Int](1))
}
def genSequenceR(numItems: Int, seq_no: Int, no:Int, no_nos: Int, numMade: Int, list: List[Int]): List[Int] = {
if(numMade < numItems){
if(no_nos < seq_no){
genSequenceR(numItems, seq_no, no, no_nos + 1, numMade + 1, list :+ no)
}else if(no % 2 == 0){
genSequenceR(numItems, seq_no, no + 1, 0, numMade, list)
}else{
genSequenceR(numItems, seq_no + 1, no + 1, 0, numMade, list)
}
}else{
list
}
}
The genSequenceR is the recursive function that accumulates values in the list and calls the function with new values based on the conditions. Like the while loop, it terminates, when numMade is less than numItems and returns the list to genSequence.
This is a fairly rudimentary functional translation of your code. It can be improved and there are better approaches typically used. I'd recommend trying to improve it with pattern matching and then work towards the other solutions that use Stream here.
Here's an attempt from a Scala tyro. Keep in mind I don't really understand Scala, I don't really understand the question, and I don't really understand your algorithm.
def genX_Ys[A](howMany : Int, ofWhat : A) : List[A] = howMany match {
case 1 => List(ofWhat)
case _ => ofWhat :: genX_Ys(howMany - 1, ofWhat)
}
def makeAtLeast(startingWith : List[Int], nextUp : Int, howMany : Int, minimumLength : Int) : List[Int] = {
if (startingWith.size >= minimumLength)
startingWith
else
makeAtLeast(startingWith ++ genX_Ys( howMany, nextUp),
nextUp +1, howMany + (if (nextUp % 2 == 1) 1 else 0), minimumLength)
}
def genSequence(numItems: Int) = makeAtLeast(List(1), 2, 2, numItems).slice(0, numItems)
This seems to work, but re-read the caveats above. In particular, I am sure there is a library function that performs genX_Ys, but I couldn't find it.
EDIT Could be
def genX_Ys[A](howMany : Int, ofWhat : A) : Seq[A] =
(1 to howMany) map { x => ofWhat }
Here is a very direct "translation" of the definition of the Golomb seqence:
val it = Iterator.iterate((1,1,Map(1->1,2->2))){ case (n,i,m) =>
val c = m(n)
if (c == 1) (n+1, i+1, m + (i -> n) - n)
else (n, i+1, m + (i -> n) + (n -> (c-1)))
}.map(_._1)
println(it.take(10).toList)
The tripel (n,i,m) contains the actual number n, the index i and a Map m, which contains how often an n must be repeated. When the counter in the Map for our n reaches 1, we increase n (and can drop n from the map, as it is not longer needed), else we just decrease n's counter in the map and keep n. In every case we add the new pair i -> n into the map, which will be used as counter later (when a subsequent n reaches the value of the current i).
[Edit]
Thinking about it, I realized that I don't need indexes and not even a lookup (because the "counters" are already in the "right" order), which means that I can replace the Map with a Queue:
import collection.immutable.Queue
val it = 1 #:: Iterator.iterate((2, 2, Queue[Int]())){
case (n,1,q) => (n+1, q.head, q.tail + (n+1))
case (n,c,q) => (n,c-1,q + n)
}.map(_._1).toStream
The Iterator works correctly when starting by 2, so I had to add a 1 at the beginning. The second tuple argument is now the counter for the current n (taken from the Queue). The current counter could be kept in the Queue as well, so we have only a pair, but then it's less clear what's going on due to the complicated Queue handling:
val it = 1 #:: Iterator.iterate((2, Queue[Int](2))){
case (n,q) if q.head == 1 => (n+1, q.tail + (n+1))
case (n,q) => (n, ((q.head-1) +: q.tail) + n)
}.map(_._1).toStream