Function to shift a range - scala

Is there an existing function that shifts a Range producing another Range, like
val r = 1 to 5
val s = r.map(_ + 2) // produces Vector(3, 4, 5, 6, 7)
I would like to get 3 to 7.

Here is how I would implement it:
implicit class RangeHasShift(val r: Range) extends AnyVal {
def shift(n: Int): Range = {
val start1 = r.start + n
val end1 = r.end + n
// overflow check
if ((n > 0 && (start1 < r.start || end1 < r.end)) ||
(n < 0 && (start1 > r.start || end1 > r.end)))
throw new IllegalArgumentException(s"$r.shift($n) causes number overflow")
if (r.isInclusive)
new Range.Inclusive(start1, end1, r.step)
else
new Range (start1, end1, r.step)
}
}
def check(r: Range) = assert(r == r.shift(123).shift(-123))
check(1 to 10)
check(1 to -1)
check(1 to -1 by -1)
check(1 to 10 by 3)
check(1 until 10)
check(1 until -1)
check(1 until -1 by -1)
check(1 until 10 by 3)
I wonder if this exists somewhere in the API?

If your main goal is not to have all values in memory when shifting the range you could use a View:
scala> (1 to 999999999).view.map(_ + 2)
res0: scala.collection.SeqView[Int,Seq[_]] = SeqViewM(...)
That would resemble the old implementation of Range which returned a lazy sequence.

Another simple approach that returns an Inclusive Range
val newRange = previousRange.start + shift to previousRange.end + shift
or
val newRange = Range.inclusive(previousRange.start + shift, previousRange.end + shift)

Related

Running different objects in IDEA - Scala

I have 3 different objects that I've written in IDEA, labelled PartA, PartB, and PartC. However, when I attempt to run any of these objects, the only one that gives me the option to run is PartB. When I right click on the code for PartA and PartC, I have no option to run them. Only PartB has the option to run. What's going on here, and how can I fix it so I can run the different objects I have written?
Edit: Sorry, first time posting a question here. Here's the code I have written.
object PartB extends App {
def easter(Y:Int): Int = {
val N = Y - 1900
val A = N - (N/19) * 19
val B = (7 * A + 1) / 19
val C = 11 * A + 4 - B
val M = C - (C / 29) * 29
val Q = N / 4
val S = N + Q + 31 - M
val W = S - (S / 7) * 7
val DATE = 25 - M - W
return DATE
}
println("Enter a year: ")
val year = scala.io.StdIn.readInt()
val date = easter(year)
var easter_day : String = ""
if (date == 0) {
easter_day = "March, 31"
} else if (date < 0) {
easter_day = "March, " + (31 + year)
} else {
easter_day = "April, " + date
}
println("In " + year + ", Easter is on " + easter_day + ".")
}
////////////////////////////////////////////////////////////////////////////////
object PartC {
def ack(m:Int, n:Int) : Int = {
if (m == 0) {
return n + 1
} else if (n == 0) {
return ack(m - 1, 1)
} else {
return ack(m - 1, ack(m, n - 1))
}
}
println("Enter a value for m: ")
val m = scala.io.StdIn.readInt()
println("Enter a value for n: ")
val n = scala.io.StdIn.readInt()
println(ack(m, n))
}
PartB extends App, but PartC doesn't. Presumably PartA doesn't either.
The App trait can be used to quickly turn objects into executable programs... the whole class body becomes the “main method”.
So PartB defines a main method.

Merge for mergesort in scala

I'm migrating from Java to Scala and I am trying to come up with the procedure merge for mergesort algorithm. My solution:
def merge(src: Array[Int], dst: Array[Int], from: Int,
mid: Int, until: Int): Unit = {
/*
* Iteration of merge:
* i - index of src[from, mid)
* j - index of src[mid, until)
* k - index of dst[from, until)
*/
#tailrec
def loop(i: Int, j: Int, k: Int): Unit = {
if (k >= until) {
// end of recursive calls
} else if (i >= mid) {
dst(k) = src(j)
loop(i, j + 1, k + 1)
} else if (j >= until) {
dst(k) = src(j)
loop(i + 1, j, k + 1)
} else if (src(i) <= src(j)) {
dst(k) = src(i);
loop(i + 1, j, k + 1)
} else {
dst(k) = src(j)
loop(i, j + 1, k + 1)
}
}
loop(from, mid, from)
}
seems to work, but it seems to me that it is written in quite "imperative" style
(despite i have used recursion and no mutable variables except for the arrays, for which the side effect is intended). I want something like this:
/*
* this code is not working and at all does the wrong things
*/
for (i <- (from until mid); j <- (mid until until);
k <- (from until until) if <???>) yield dst(k) = src(<???>)
But i cant come up with the proper solution of such kind. Can you please help me?
Consider this:
val left = src.slice(from, mid).buffered
val right = src.slice(mid, until).buffered
(from until until) foreach { k =>
dst(k) = if(!left.hasNext) right.next
else if(!right.hasNext || left.head < right.head) left.next
else right.next
}

How do you memoization with cases in Scala?

What is the best way to convert this code which uses memoization into proper Scala using cases and functional programming?
def uniquePathsMemoization(n:Int, m:Int, row:Int, col:Int, seen:Array[Array[Int]]):Int = {
if (row == m && col == n) 1
if (row > m || col > n) 0
if (seen(row+1)(col) == -1) seen(row+1)(col) = uniquePathsMemoization(n, m, row + 1, col, seen)
if (seen(row)(col + 1) == -1 ) seen(row)(col) = uniquePathsMemoization(n,m, row, col + 1, seen)
seen(row+1)(col) + seen(row)(col + 1)
}
This is a modified version of your code that uses match and case
def uniquePathsMemoization(n:Int, m:Int, row:Int, col:Int, seen:Array[Array[Int]]):Int = (row,col) match{
case (row,col) if row == m && col == n =>
1
case (row,col) if row > m || col > n =>
0
case (row,col) =>
if (seen(row+1)(col) == -1) seen(row+1)(col) = uniquePathsMemoization(n, m, row + 1, col, seen)
if (seen(row)(col + 1) == -1 ) seen(row)(col) = uniquePathsMemoization(n,m, row, col + 1, seen)
seen(row+1)(col) + seen(row)(col + 1)
}
It is not easy to convert this code to a pure functional version, due to the state stored in the seen array. But this state can be hidden for the rest of the application, using a function decorator:
def uniquePathsMemoizationGenerator( maxRows: Int, maxCols:Int ) : (Int,Int,Int,Int) => Int = {
def uniquePathsMemoization(n:Int, m:Int, row:Int, col:Int, seen:Array[Array[Int]]):Int = (row,col) match{
case (row,col) if row == m && col == n =>
1
case (row,col) if row > m || col > n =>
0
case (row,col) =>
if (seen(row+1)(col) == -1) seen(row+1)(col) = uniquePathsMemoization(n, m, row + 1, col, seen)
if (seen(row)(col + 1) == -1 ) seen(row)(col) = uniquePathsMemoization(n,m, row, col + 1, seen)
seen(row+1)(col) + seen(row)(col + 1)
}
val seen = Array.fill(maxRows,maxCols)(-1)
uniquePathsMemoization(_,_,_,_,seen)
}
val maxRows = ???
val maxCols = ???
val uniquePaths = uniquePathsMemoizationGenerator( maxRows, maxCols )
// Use uniquePaths from this point, instead of uniquePathsMemoization

Scala functional solution for spoj "Prime Generator"

I worked on the Prime Generator problem for almost 3 days.
I want to make a Scala functional solution(which means "no var", "no mutable data"), but every time it exceed the time limitation.
My solution is:
object Main {
def sqrt(num: Int) = math.sqrt(num).toInt
def isPrime(num: Int): Boolean = {
val end = sqrt(num)
def isPrimeHelper(current: Int): Boolean = {
if (current > end) true
else if (num % current == 0) false
else isPrimeHelper(current + 1)
}
isPrimeHelper(2)
}
val feedMax = sqrt(1000000000)
val feedsList = (2 to feedMax).filter(isPrime)
val feedsSet = feedsList.toSet
def findPrimes(min: Int, max: Int) = (min to max) filter {
num => if (num <= feedMax) feedsSet.contains(num)
else feedsList.forall(p => num % p != 0 || p * p > num)
}
def main(args: Array[String]) {
val total = readLine().toInt
for (i <- 1 to total) {
val Array(from, to) = readLine().split("\\s+")
val primes = findPrimes(from.toInt, to.toInt)
primes.foreach(println)
println()
}
}
}
I'm not sure where can be improved. I also searched a lot, but can't find a scala solution(most are c/c++ ones)
Here is a nice fully functional scala solution using the sieve of eratosthenes: http://en.literateprograms.org/Sieve_of_Eratosthenes_(Scala)#chunk def:ints
Check out this elegant and efficient one liner by Daniel Sobral: http://dcsobral.blogspot.se/2010/12/sieve-of-eratosthenes-real-one-scala.html?m=1
lazy val unevenPrimes: Stream[Int] = {
def nextPrimes(n: Int, sqrt: Int, sqr: Int): Stream[Int] =
if (n > sqr) nextPrimes(n, sqrt + 1, (sqrt + 1)*(sqrt + 1)) else
if (unevenPrimes.takeWhile(_ <= sqrt).exists(n % _ == 0)) nextPrimes(n + 2, sqrt, sqr)
else n #:: nextPrimes(n + 2, sqrt, sqr)
3 #:: 5 #:: nextPrimes(7, 3, 9)
}

Need pointers for optimization of Merge Sort implementation in Scala

I have just started learning Scala and sideways I am doing some algorithms also. Below is an implementation of merge sort in Scala. I know it isn't very "scala" in nature, and some might even reckon that I have tried to write java in scala. I am not totally familiar with scala, i just know some basic syntax and i keep googling if i need something more. So please give me some pointers on to what can i do in this code to make it more functional and in accord with scala conventions and best practices. Please dont just give correct/optimized code, i will like to do it myself. Any suggestions are welcomed !
def mergeSort(list: Array[Int]): Array[Int] = {
val len = list.length
if (len == 1) list
else {
var x, y = new Array[Int](len / 2)
val z = new Array[Int](len)
Array.copy(list, 0, x, 0, len / 2)
Array.copy(list, len / 2, y, 0, len / 2)
x = mergeSort(x)
y = mergeSort(y)
var i, j = 0
for (k <- 0 until len) {
if (j >= y.length || (i < x.length && x(i) < y(j))) {
z(k) = x(i)
i = i + 1
} else {
z(k) = y(j)
j = j + 1
}
}
z
}
}
[EDIT]
This code works fine and I have assumed for now that input array will always be of even length.
UPDATE
Removed vars x and y
def mergeSort(list: Array[Int]): Array[Int] = {
val len = list.length
if (len == 1) list
else {
val z = new Array[Int](len)
val x = mergeSort(list.dropRight(len/2))
val y = mergeSort(list.drop(len/2))
var i, j = 0
for (k <- 0 until len) {
if (j >= y.length || (i < x.length && x(i) < y(j))) {
z(k) = x(i)
i = i + 1
} else {
z(k) = y(j)
j = j + 1
}
}
z
}
}
Removing the var x,y = ... would be a good start to being functional. Prefer immutability to mutable datasets.
HINT: a method swap that takes two values and returns them ordered using a predicate
Also consider removing the for loop(or comprehension).