How do you memoization with cases in Scala? - 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

Related

Facing Issues in Recursion of Perfect Number Problem

I've been working on the scala recursion problem. I used to develop the program using loops and then use the concept of recursion to convert the existing loop problem in a recursive solution.
So I have written the following code to find the perfect number using loops.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
while ( {
i * i <= n
}) {
if (n % i == 0) if (i * i != n) sum = sum + i + n / i
else sum = sum + i
i += 1
}
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum == n && n != 1) return true
false
}
Here is my attempt to convert it into a recursive solution. But I'm getting the incorrect result.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
def loop(i:Int, n:Int): Any ={
if(n%i == 0) if (i * i != n) return sum + i + n / i
else
return loop(i+1, sum+i)
}
val sum_ = loop(2, n)
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum_ == n && n != 1) return true
false
}
Thank you in advance.
Here is a tail-recursive solution
def isPerfectNumber(n: Int): Boolean = {
#tailrec def loop(d: Int, acc: List[Int]): List[Int] = {
if (d == 1) 1 :: acc
else if (n % d == 0) loop(d - 1, d :: acc)
else loop(d - 1, acc)
}
loop(n-1, Nil).sum == n
}
As a side-note, functions that have side-effects such as state mutation scoped locally are still considered pure functions as long as the mutation is not visible externally, hence having while loops in such functions might be acceptable.

Check if number is prime in O(sqrt(n)) in Scala

When checking if n is a prime number in Scala, the most common solutions is concise one-liner which can be seen in almost all similar questions on SO
def isPrime1(n: Int) = (n > 1) && ((2 until n) forall (n % _ != 0))
Moving on, it's simple to rewrite it to check only odd numbers
def isPrime2(n: Int): Boolean = {
if (n < 2) return false
if (n == 2) return true
if (n % 2 == 0) false
else (3 until n by 2) forall (n % _ != 0)
}
However, to be more efficient I would like to combine checking only odds with counting up to sqrt(n), but without using Math.sqrt. So, as i < sqrt(n) <==> i * i < n, I would write C-like loop:
def isPrime3(n: Int): Boolean = {
if (n < 2) return false
if (n == 2) return true
if (n % 2 == 0) return false
var i = 3
while (i * i <= n) {
if (n % i == 0) return false
i += 2
}
true
}
The questions are:
1) How to achieve the last version in the first version nice Scala functional style?
2) How can I use Scala for to this? I thought of something similar to below, but don't know how.
for {
i <- 3 until n by 2
if i * i <= n
} { ??? }
Here is a method to verify if n is prime until sqrt(n) without using sqrt:
def isPrime3(n: Int): Boolean = {
if (n == 2) {
true
} else if (n < 2 || n % 2 == 0) {
false
} else {
Stream.from(3, 2).takeWhile(i => i * i < n + 1).forall(i => n % i != 0)
}
}
If you want to do it until n/2, which is also a possible optimization (worse than sqrt(n)), you can replace the last line with:
(3 to n/2 + 1 by 2).forall(i => n % i != 0)
If you prefer, you could also make a tail recursive version, something along these lines:
import scala.annotation.tailrec
def isPrime3(n: Int): Boolean = {
if (n == 2 || n == 3) {
true
} else if (n < 2 || n % 2 == 0) {
false
} else {
isPrime3Rec(n, 3)
}
}
#tailrec
def isPrime3Rec(n:Int, i: Int): Boolean = {
(n % i != 0) && ((i * i > n) || isPrime3Rec(n, i + 2))
}

Function to shift a range

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)

How to get unique elements from two lists of strings in scala?

I have two list to compare:
List one:
List("one","two","three","four")
List two:
List("one","two")
how can I get the unique values from these two lists?
If your two lists are r1 and r2, and assuming you want the values in each list that are not present in the other:
r1.filterNot(r2.contains) ::: r2.filterNot(r1.contains)
or
r1.diff(r2) ::: r2.diff(r1)
Turn them into sets, and get the intersection. You may then turn it back to Seq if you want, but first ask yourself if they had to be Seq in first place, instead of Set.
scala> List("one","two","three","four").toSet & List("one","two").toSet
res0: scala.collection.immutable.Set[String] = Set(one, two)
Use The difference operator for Set &~
http://www.scala-lang.org/api/current/scala/collection/immutable/Set.html
I use List(1, 2, 3, 4) ::: List(1, 2, 5) distinct for this issue. It returns List(1, 2, 3, 4, 5).
I would suggest using the following for O(m+n) running time (assumes input arrays are sorted).
def mergeUniqueSortedArrays( A: Array[String], B: Array[String] ): Array[String]= {
val n = A.length
val m = B.length
var C = Array[String]()
var i = 0
var j = 0
while (i < n && j < m) {
if (i == n) {
if ( B(j) != A(i-1) ) {
C :+= B(j)
}
j+=1
}
else if (j == m) {
if ( A(i) != B(j-1) ) {
C :+= A(j)
}
i+=1
}
else {
if ( A(i) < B(j) ) {
if (C.length == 0 || A(i) != C(C.length-1)) {
C :+= A(i)
}
i+=1
}
else if ( B(j) < A(i) ) {
if (C.length == 0 || B(j) != C(C.length-1)) {
C :+= B(j)
}
j+=1
}
else {
if (C.length == 0 || A(i) != C(C.length-1)) {
C :+= A(i)
}
i+=1
j+=1
}
}
}
return C
}
--
NOTE: If the input arrays are not sorted, then you can easily sort the input arrays and it will run in in O( max{(n + m), (n log n)}) time, assuming n>m.
NOTE: O(n + m) time technically assumes that string length is bounded by constant k, but you aren't going to get around that anyway.

Integer partitioning in Scala

Given n ( say 3 people ) and s ( say 100$ ), we'd like to partition s among n people.
So we need all possible n-tuples that sum to s
My Scala code below:
def weights(n:Int,s:Int):List[List[Int]] = {
List.concat( (0 to s).toList.map(List.fill(n)(_)).flatten, (0 to s).toList).
combinations(n).filter(_.sum==s).map(_.permutations.toList).toList.flatten
}
println(weights(3,100))
This works for small values of n. ( n=1, 2, 3 or 4).
Beyond n=4, it takes a very long time, practically unusable.
I'm looking for ways to rework my code using lazy evaluation/ Stream.
My requirements : Must work for n upto 10.
Warning : The problem gets really big really fast. My results from Matlab -
---For s =100, n = 1 thru 5 results are ---
n=1 :1 combinations
n=2 :101 combinations
n=3 :5151 combinations
n=4 :176851 combinations
n=5: 4598126 combinations
---
You need dynamic programming, or memoization. Same concept, anyway.
Let's say you have to divide s among n. Recursively, that's defined like this:
def permutations(s: Int, n: Int): List[List[Int]] = n match {
case 0 => Nil
case 1 => List(List(s))
case _ => (0 to s).toList flatMap (x => permutations(s - x, n - 1) map (x :: _))
}
Now, this will STILL be slow as hell, but there's a catch here... you don't need to recompute permutations(s, n) for numbers you have already computed. So you can do this instead:
val memoP = collection.mutable.Map.empty[(Int, Int), List[List[Int]]]
def permutations(s: Int, n: Int): List[List[Int]] = {
def permutationsWithHead(x: Int) = permutations(s - x, n - 1) map (x :: _)
n match {
case 0 => Nil
case 1 => List(List(s))
case _ =>
memoP getOrElseUpdate ((s, n),
(0 to s).toList flatMap permutationsWithHead)
}
}
And this can be even further improved, because it will compute every permutation. You only need to compute every combination, and then permute that without recomputing.
To compute every combination, we can change the code like this:
val memoC = collection.mutable.Map.empty[(Int, Int, Int), List[List[Int]]]
def combinations(s: Int, n: Int, min: Int = 0): List[List[Int]] = {
def combinationsWithHead(x: Int) = combinations(s - x, n - 1, x) map (x :: _)
n match {
case 0 => Nil
case 1 => List(List(s))
case _ =>
memoC getOrElseUpdate ((s, n, min),
(min to s / 2).toList flatMap combinationsWithHead)
}
}
Running combinations(100, 10) is still slow, given the sheer numbers of combinations alone. The permutations for each combination can be obtained simply calling .permutation on the combination.
Here's a quick and dirty Stream solution:
def weights(n: Int, s: Int) = (1 until s).foldLeft(Stream(Nil: List[Int])) {
(a, _) => a.flatMap(c => Stream.range(0, n - c.sum + 1).map(_ :: c))
}.map(c => (n - c.sum) :: c)
It works for n = 6 in about 15 seconds on my machine:
scala> var x = 0
scala> weights(100, 6).foreach(_ => x += 1)
scala> x
res81: Int = 96560646
As a side note: by the time you get to n = 10, there are 4,263,421,511,271 of these things. That's going to take days just to stream through.
My solution of this problem, it can computer n till 6:
object Partition {
implicit def i2p(n: Int): Partition = new Partition(n)
def main(args : Array[String]) : Unit = {
for(n <- 1 to 6) println(100.partitions(n).size)
}
}
class Partition(n: Int){
def partitions(m: Int):Iterator[List[Int]] = new Iterator[List[Int]] {
val nums = Array.ofDim[Int](m)
nums(0) = n
var hasNext = m > 0 && n > 0
override def next: List[Int] = {
if(hasNext){
val result = nums.toList
var idx = 0
while(idx < m-1 && nums(idx) == 0) idx = idx + 1
if(idx == m-1) hasNext = false
else {
nums(idx+1) = nums(idx+1) + 1
nums(0) = nums(idx) - 1
if(idx != 0) nums(idx) = 0
}
result
}
else Iterator.empty.next
}
}
}
1
101
5151
176851
4598126
96560646
However , we can just show the number of the possible n-tuples:
val pt: (Int,Int) => BigInt = {
val buf = collection.mutable.Map[(Int,Int),BigInt]()
(s,n) => buf.getOrElseUpdate((s,n),
if(n == 0 && s > 0) BigInt(0)
else if(s == 0) BigInt(1)
else (0 to s).map{k => pt(s-k,n-1)}.sum
)
}
for(n <- 1 to 20) printf("%2d :%s%n",n,pt(100,n).toString)
1 :1
2 :101
3 :5151
4 :176851
5 :4598126
6 :96560646
7 :1705904746
8 :26075972546
9 :352025629371
10 :4263421511271
11 :46897636623981
12 :473239787751081
13 :4416904685676756
14 :38393094575497956
15 :312629484400483356
16 :2396826047070372396
17 :17376988841260199871
18 :119594570260437846171
19 :784008849485092547121
20 :4910371215196105953021