Calculating the sum of integers from x to y with a while loop - scala

I'm trying to write a code in Scala to calculate the sum of elements from x to y using a while loop.
I initialize x and y to for instance :
val x = 1
val y = 10
then I write a while loop to increment x :
while (x<y) x = x + 1
But println(x) gives the result 10 so I'm assuming the code basically does 1 + 1 + ... + 1 10 times, but that's not what I want.

One option would be to find the sum via a range, converted to a list:
val x = 1
val y = 10
val sum = (x to y).toList.sum
println("sum = " + sum)
Output:
sum = 55
Demo here:
Rextester

Here's how you would do it using a (yak!) while loop with vars:
var x = 1 // Note that is a "var" not a "val"
val y = 10
var sum = 0 // Must be a "var"
while(x <= y) { // Note less than or equal to
sum += x
x += 1
}
println(s"Sum is $sum") // Sum = 55 (= 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10)
Here's another, more functional, approach using a recursive function. Note the complete lack of var types.
val y = 10
#scala.annotation.tailrec // Signifies add must be tail recursive
def add(x: Int, sum: Int): Int = {
// If x exceeds y, then return the current sum value.
if(x > y) sum
// Otherwise, perform another iteration adding 1 to x and x to sum.
else add(x + 1, sum + x)
}
// Start things off and get the result (55).
val result = add(1, 0)
println(s"Sum is $result") // Sum is 55
Here's a common functional approach that can be used with collections. Firstly, (x to y) becomes a Range of values between 1 and 10 inclusive. We then use the foldLeft higher-order function to sum the members:
val x = 1
val y = 10
val result = (x to y).foldLeft(0)(_ + _)
println(s"Sum is $result") // Sum is 55
The (0) is the initial sum value, and the (_ + _) adds the current sum to the current value. (This is Scala shorthand for ((sum: Int, i: Int) => sum + i)).
Finally, here's a simplified version of the elegant functional version that #TimBiegeleisen posted above. However, since a Range already implements a .sum member, there is no need to convert to a List first:
val x = 1
val y = 10
val result = (x to y).sum
println(s"Sum is $result") // Sum is 55
(sum can be thought of as being equivalent to the foldLeft example above, and is typically implemented in similar fashion.)
BTW, if you just want to sum values from 1 to 10, the following code does this very succinctly:
(1 to 10).sum
Although you can use Scala to write imperative code (which uses vars, while loops, etc. and which inherently leads to shared mutable state), I strongly recommend that you consider functional alternatives. Functional programming avoids the side-effects and complexities of shared mutable state and often results in simpler, more elegant code. Note that all but the first examples are all functional.

var x = 1
var y = 10
var temp = 0
while (x < y) {
temp = temp+x
x = x + 1
}
println(temp)
This gives required result

Related

Recursive sum function, How do i limit the sum?

The goal is to code this sum into a recursive function.
Sum
I have tried so far to code it like this.
def under(u: Int): Int = {
var i1 = u/2
var i = i1+1
if ( u/2 == 1 ) then u + 1 - 2 * 1
else (u + 1 - 2 * i) + under(u-1)
}
It seems like i am running into an issue with the recursive part but i am not able to figure out what goes wrong.
In theory, under(5) should produce 10.
Your logic is wrong. It should iterate (whether through loop, recursion or collection is irrelevant) from i=1 to i=n/2. But using n and current i as they are.
(1 to (n/2)).map(i => n + 1 - 2 * i).sum
You are (more or less) running computations from i=1 to i=n (or rather n down to 1) but instead of n you use i/2 and instead of i you use i/2+1. (sum from i=1 to i=n of (n/2 + 1 - 2 * i)).
// actually what you do is more like (1 to n).toList.reverse
// rather than (1 to n)
(1 to n).map(i => i/2 + 1 - 2 * (i/2 + 1)).sum
It's a different formula. It has twice the elements to sum, and a part of each of them is changing instead of being constant while another part has a wrong value.
To implement the same logic with recursion you would have to do something like:
// as one function with default args
// tail recursive version
def under(n: Int, i: Int = 1, sum: Int = 0): Int =
if (i > n/2) sum
else under(n, i+1, sum + (n + 2 - 2 * i))
// not tail recursive
def under(n: Int, i: Int = 1): Int =
if (i > n/2) 0
else (n + 2 - 2 * i) + under(n, i + 1)
// with nested functions without default args
def under(n: Int): Int = {
// tail recursive
def helper(i: Int, sum: Int): Int =
if (i > n/2) sum
else helper(i + 1, sum + (n + 2 - 2 * i))
helper(1, 0)
}
def under(n: Int): Int = {
// not tail recursive
def helper(i: Int): Int =
if (i > n/2) 0
else (n + 2 - 2 * i) + helper(i + 1)
helper(1)
}
As a side note: there is no need to use any iteration / recursion at all. Here is an explicit formula:
def g(n: Int) = n / 2 * (n - n / 2)
that gives the same results as
def h(n: Int) = (1 to n / 2).map(i => n + 1 - 2 * i).sum
Both assume that you want floored n / 2 in the case that n is odd, i.e. both of the functions above behave the same as
def j(n: Int) = (math.ceil(n / 2.0) * math.floor(n / 2.0)).toInt
(at least until rounding errors kick in).

Scala for loop to calculate sum of powers

I am very new to Scala and am trying to create a loop that will calculate the sum of powers (1^1 + 2^2 + ... + 10^10) without using an exponent operator.
I discovered that 1^1 through 9^9 calculate correctly. But for some reason 10^10 evaluates to 1410065409 in my current code and messes up my final output of the sum. What is causing this mathematical error?
My current code is:
var i = 1
var ex = 1
var sum = 0
while (i <= 10)
{
for (j <- 1 to i)
{
ex = ex * i
}
sum += ex
ex = 1
i += 1
}
println(s"The sum is $sum")
Here's how it's done in Scala.
List.tabulate(10)(n => List.fill(n+1)(n.toLong+1).product).sum
//res0: Long = 10405071317
Another option you have, is to use Math.pow:
val result1 = 1.to(10).map(x => Math.pow(x, x)).sum
Please note that result1 is of type Double, and has the value 1.0405071317E10.
If you want to have it as long, you can do:
val result2 = 1.to(10).map(x => Math.pow(x, x).toLong).sum
Then result2 will have the value 10405071317.

Adding elements to a list in a for loop

var locations: List[Location] = List[Location]()
for (x <- 0 to 10; y <- 0 to 10) {
println("x: " + x + " y: " + y)
locations ::: List(Location(x, y))
println(locations)
}
The code above is supposed to concatenate some lists. But the result is an empty list. Why?
Your mistake is on the line locations ::: List(Location(x, y)). This is concatenating the lists, but the doing nothing with the result. If you replace it with locations = locations ::: List(Location(x, y)) you would have your desired result.
However there are more idiomatic ways to solve this problem in Scala. In Scala, writing immutable code is the preferred style (i.e. use val rather than var where possible).
Here's a couple of ways to do it:
Using yield:
val location = for (x <- 0 to 10; y <- 0 to 10) yield Location(x, y)
Using tabulate:
val location = List.tabulate(11, 11) { case (x, y) => Location(x, y) }
Even shorter:
val location = List.tabulate(11, 11)(Location)
Edit: just noticed you had 0 to 10 which is inclusive-inclusive. 0 until 10 is inclusive-exclusive. I've changed the args to tabulate to 11.

Complexity estimation for simple recursive algorithm

I wrote a code on Scala. And now I want to estimate time and memory complexity.
Problem statement
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
My code
def numSquares(n: Int): Int = {
import java.lang.Math._
def traverse(n: Int, ns: Int): Int = {
val max = ((num: Int) => {
val sq = sqrt(num)
// a perfect square!
if (sq == floor(sq))
num.toInt
else
sq.toInt * sq.toInt
})(n)
if (n == max)
ns + 1
else
traverse(n - max, ns + 1)
}
traverse(n, 0)
}
I use here a recursion solution. So IMHO time complexity is O(n), because I need to traverse over the sequence of numbers using recursion. Am I right? Have I missed anything?

Suggest a cleaner functional way

Here is some imperative code:
var sum = 0
val spacing = 6
var x = spacing
for(i <- 1 to 10) {
sum += x * x
x += spacing
}
Here are two of my attempts to "functionalize" the above code:
// Attempt 1
(1 to 10).foldLeft((0, 6)) {
case((sum, x), _) => (sum + x * x, x + spacing)
}
// Attempt 2
Stream.iterate ((0, 6)) { case (sum, x) => (sum + x * x, x + spacing) }.take(11).last
I think there might be a cleaner and better functional way to do this. What would be that?
PS: Please note that the above is just an example code intended to illustrate the problem; it is not from the real application code.
Replacing 10 by N, you have spacing * spacing * N * (N + 1) * (2 * N + 1) / 6
This is by noting that you're summing (spacing * i)^2 for the range 1..N. This sum factorizes as spacing^2 * (1^2 + 2^2 + ... + N^2), and the latter sum is well-known to be N * (N + 1) * (2 * N + 1) / 6 (see Square Pyramidal Number)
I actually like idea of lazy sequences in this case. You can split your algorithm in 2 logical steps.
At first you want to work on all natural numbers (ok.. not all, but up to max int), so you define them like this:
val naturals = 0 to Int.MaxValue
Then you need to define knowledge about how numbers, that you want to sum, can be calculated:
val myDoubles = (naturals by 6 tail).view map (x => x * x)
And putting this all together:
val naturals = 0 to Int.MaxValue
val myDoubles = (naturals by 6 tail).view map (x => x * x)
val mySum = myDoubles take 10 sum
I think it's the way mathematician will approach this problem. And because all collections are lazily evaluated - you will not get out of memory.
Edit
If you want to develop idea of mathematical notation further, you can actually define this implicit conversion:
implicit def math[T, R](f: T => R) = new {
def ∀(range: Traversable[T]) = range.view map f
}
and then define myDoubles like this:
val myDoubles = ((x: Int) => x * x) ∀ (naturals by 6 tail)
My personal favourite would have to be:
val x = (6 to 60 by 6) map {x => x*x} sum
Or given spacing as an input variable:
val x = (spacing to 10*spacing by spacing) map {x => x*x} sum
or
val x = (1 to 10) map (spacing*) map {x => x*x} sum
There are two different directions to go. If you want to express yourself, assuming that you can't use the built-in range function (because you actually want something more complicated):
Iterator.iterate(spacing)(x => x+spacing).take(10).map(x => x*x).foldLeft(0)(_ + _)
This is a very general pattern: specify what you start with and how to get the next given the previous; then take the number of items you need; then transform them somehow; then combine them into a single answer. There are shortcuts for almost all of these in simple cases (e.g. the last fold is sum) but this is a way to do it generally.
But I also wonder--what is wrong with the mutable imperative approach for maximal speed? It's really quite clear, and Scala lets you mix the two styles on purpose:
var x = spacing
val last = spacing*10
val sum = 0
while (x <= last) {
sum += x*x
x += spacing
}
(Note that the for is slower than while since the Scala compiler transforms for loops to a construct of maximum generality, not maximum speed.)
Here's a straightforward translation of the loop you wrote to a tail-recursive function, in an SML-like syntax.
val spacing = 6
fun loop (sum: int, x: int, i: int): int =
if i > 0 then loop (sum+x*x, x+spacing, i-1)
else sum
val sum = loop (0, spacing, 10)
Is this what you were looking for? (What do you mean by a "cleaner" and "better" way?)
What about this?
def toSquare(i: Int) = i * i
val spacing = 6
val spaceMultiples = (1 to 10) map (spacing *)
val squares = spaceMultiples map toSquare
println(squares.sum)
You have to split your code in small parts. This can improve readability a lot.
Here is a one-liner:
(0 to 10).reduceLeft((u,v)=>u + spacing*spacing*v*v)
Note that you need to start with 0 in order to get the correct result (else the first value 6 would be added only, but not squared).
Another option is to generate the squares first:
(1 to 2*10 by 2).scanLeft(0)(_+_).sum*spacing*spacing