Facing Issues in Recursion of Perfect Number Problem - scala

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.

Related

Combine multiple sequential entries in Scala/Spark

I have an array of numbers separated by comma as shown:
a:{108,109,110,112,114,115,116,118}
I need the output something like this:
a:{108-110, 112, 114-116, 118}
I am trying to group the continuous numbers with "-" in between.
For example, 108,109,110 are continuous numbers, so I get 108-110. 112 is separate entry; 114,115,116 again represents a sequence, so I get 114-116. 118 is separate and treated as such.
I am doing this in Spark. I wrote the following code:
import scala.collection.mutable.ArrayBuffer
def Sample(x:String):ArrayBuffer[String]={
val x1 = x.split(",")
var a:Int = 0
var present=""
var next:Int = 0
var yrTemp = ""
var yrAr= ArrayBuffer[String]()
var che:Int = 0
var storeV = ""
var p:Int = 0
var q:Int = 0
var count:Int = 1
while(a < x1.length)
{
yrTemp = x1(a)
if(x1.length == 1)
{
yrAr+=x1(a)
}
else
if(a < x1.length - 1)
{
present = x1(a)
if(che == 0)
{
storeV = present
}
p = x1(a).toInt
q = x1(a+1).toInt
if(p == q)
{
yrTemp = yrTemp
che = 1
}
else
if(p != q)
{
yrTemp = storeV + "-" + present
che = 0
yrAr+=yrTemp
}
}
else
if(a == x1.length-1)
{
present = x1(a)
yrTemp = present
che = 0
yrAr+=yrTemp
}
a = a+1
}
yrAr
}
val SampleUDF = udf(Sample(_:String))
I am getting the output as follows:
a:{108-108, 109-109, 110-110, 112, 114-114, 115-115, 116-116, 118}
I am not able to figure out where I am going wrong. Can you please help me in correcting this. TIA.
Here's another way:
def rangeToString(a: Int, b: Int) = if (a == b) s"$a" else s"$a-$b"
def reduce(xs: Seq[Int], min: Int, max: Int, ranges: Seq[String]): Seq[String] = xs match {
case y +: ys if (y - max <= 1) => reduce(ys, min, y, ranges)
case y +: ys => reduce(ys, y, y, ranges :+ rangeToString(min, max))
case Seq() => ranges :+ rangeToString(min, max)
}
def output(xs: Array[Int]) = reduce(xs, xs.head, xs.head, Vector())//.toArray
Which you can test:
println(output(Array(108,109,110,112,114,115,116,118)))
// Vector(108-110, 112, 114-116, 118)
Basically this is a tail recursive function - i.e. you take your "variables" as the input, then it calls itself with updated "variables" on each loop. So here xs is your array, min and max are integers used to keep track of the lowest and highest numbers so far, and ranges is the output sequence of Strings that gets added to when required.
The first pattern (y being the first element, and ys being the rest of the sequence - because that's how the +: extractor works) is matched if there's at least one element (ys can be an empty list) and it follows on from the previous maximum.
The second is if it doesn't follow on, and needs to reset the minimum and add the completed range to the output.
The third case is where we've got to the end of the input and just output the result, rather than calling the loop again.
Internet karma points to anyone who can work out how to eliminate the duplication of ranges :+ rangeToString(min, max)!
here is a solution :
def combineConsecutive(s: String): Seq[String] = {
val ints: List[Int] = s.split(',').map(_.toInt).toList.reverse
ints
.drop(1)
.foldLeft(List(List(ints.head)))((acc, e) => if ((acc.head.head - e) <= 1)
(e :: acc.head) :: acc.tail
else
List(e) :: acc)
.map(group => if (group.size > 1) group.min + "-" + group.max else group.head.toString)
}
val in = "108,109,110,112,114,115,116,118"
val result = combineConsecutive(in)
println(result) // List(108-110, 112, 114-116, 118)
}
This solution partly uses code from this question: Grouping list items by comparing them with their neighbors

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))
}

Tail Recursive function for the sum of fractions

I am trying to convert this recursive function into a tail recursive function
def sumOfFractions(n: Int): Double = {
require(n > 0, "Parameter n has to be greater than 0");
if (n==1)
1.0
else
1.0 / n + sumOfFractions(n - 1)
}
I thought that this solution would work but when it runs it just returns 1.0
def sumOfFractions(n:Int):Double = {
def inner(acc:Int, n:Int): Double={
if(n <= 1)1.0
else
{
inner(acc+(1/n),n-1)
}
}
inner(0,n)
}
I think this is because the accumulator is not being updated correctly but I don't understand why. The code is in Scala but an example in any language would be helpful.
You need the base case (n <= 1) to return the accumulator, not 1.0. You'll also run into problems because the accumulator is an Int instead of a Double, which means that + (1 / n) is just adding 0 (the result of dividing 1: Int by any n: Int greater than one).
You can fix this by changing acc's type and making the numerator of the reciprocal a literal double:
def sumOfFractions(n: Int):Double = {
def inner(acc: Double, n: Int): Double =
if (n <= 1) acc else inner(acc + (1.0 / n), n - 1)
inner(0, n)
}
This should work.
Correct your code
1) Return acc (accumulator) when n <= 1
2) Your acc should be Double type
3) Division should be floating point division
def sumOfFractions(n: Int): Double = {
def inner(acc: Double, n:Int): Double = if(n <= 1) acc
else inner(acc + (1.0 / n), n - 1)
inner(0,n)
}
Using foldLeft
def sumOfFractions(n: Int): Double =
(1 to n).foldLeft(0.0)((r, c) => r + (1.0 / c))

How to Make Prime Generator Code More Efficient

As a beginner in Scala, I got a problem in SPOJ:
Peter wants to generate some prime numbers for his cryptosystem. Help him! Your task is to generate all prime numbers between two given numbers!
Input
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.
Example
Input:
2
1 10
3 5
Output:
2
3
5
7
3
5
`
Warning: large Input/Output data, be careful with certain languages (though most should be OK if the algorithm is well designed)
Run environment and requirement:
Added by: Adam Dzedzej
Date: 2004-05-01
Time limit: 6s
Source limit: 50000B
Memory limit: 1536MB
Cluster: Cube (Intel Pentium G860 3GHz)
Languages: All except: NODEJS PERL 6 SCM chicken
My code is here:
import math.sqrt
object Pro_2 {
def main(args: Array[String]) {
// judge whether a Long is a prime or not
def isPrime(num: Long): Boolean = {
num match {
case num if (num < 2) => false
case _ => {
2 to (sqrt(num) toInt) forall (num % _ != 0)
}
}
}
// if a Long is a prime print it in console
def printIfIsPrime(num: Long) = {
if (isPrime(num))
println(num)
}
// get range
def getInput(times: Int) = {
for (input <- 0 until times) yield {
val range = readLine().split(" ")
(range(0) toLong, range(1) toLong)
}
}
val ranges = getInput(readInt())
for (time <- 0 until ranges.length) {
(ranges(time)._1 to ranges(time)._2).foreach(printIfIsPrime(_))
if (time != ranges.length - 1)
println()
}
}
}
When I run my code in SPOJ, I got a result: time limit exceeded
I need make my code more efficient, could you please help me?
Any help would be greatly appreciated.
isPrime could be written in a lower level style. Also you can increase the speed of the println method.
def main(args: Array[String]) {
val out = new java.io.PrintWriter(System.out, false)
def isPrime(n: Long): Boolean = {
if(n <= 3) return n > 1
else if(n%2 == 0 || n%3 == 0) return false
else {
var i = 5
while(i*i <= n) {
if(n%i == 0 || n%(i+2) == 0) return false
i += 6
}
return true
}
}
def printIfIsPrime(num: Long) = {
if (isPrime(num)) {
out.println(num)
}
}
...
val ranges = getInput(readInt())
for (time <- 0 until ranges.length) {
(ranges(time)._1 to ranges(time)._2).foreach(printIfIsPrime(_))
if (time != ranges.length - 1)
out.println()
}
out.flush()
}

Scala - can 'for-yield' clause yields nothing for some condition?

In Scala language, I want to write a function that yields odd numbers within a given range. The function prints some log when iterating even numbers. The first version of the function is:
def getOdds(N: Int): Traversable[Int] = {
val list = new mutable.MutableList[Int]
for (n <- 0 until N) {
if (n % 2 == 1) {
list += n
} else {
println("skip even number " + n)
}
}
return list
}
If I omit printing logs, the implementation become very simple:
def getOddsWithoutPrint(N: Int) =
for (n <- 0 until N if (n % 2 == 1)) yield n
However, I don't want to miss the logging part. How do I rewrite the first version more compactly? It would be great if it can be rewritten similar to this:
def IWantToDoSomethingSimilar(N: Int) =
for (n <- 0 until N) if (n % 2 == 1) yield n else println("skip even number " + n)
def IWantToDoSomethingSimilar(N: Int) =
for {
n <- 0 until N
if n % 2 != 0 || { println("skip even number " + n); false }
} yield n
Using filter instead of a for expression would be slightly simpler though.
I you want to keep the sequentiality of your traitement (processing odds and evens in order, not separately), you can use something like that (edited) :
def IWantToDoSomethingSimilar(N: Int) =
(for (n <- (0 until N)) yield {
if (n % 2 == 1) {
Option(n)
} else {
println("skip even number " + n)
None
}
// Flatten transforms the Seq[Option[Int]] into Seq[Int]
}).flatten
EDIT, following the same concept, a shorter solution :
def IWantToDoSomethingSimilar(N: Int) =
(0 until N) map {
case n if n % 2 == 0 => println("skip even number "+ n)
case n => n
} collect {case i:Int => i}
If you will to dig into a functional approach, something like the following is a good point to start.
First some common definitions:
// use scalaz 7
import scalaz._, Scalaz._
// transforms a function returning either E or B into a
// function returning an optional B and optionally writing a log of type E
def logged[A, E, B, F[_]](f: A => E \/ B)(
implicit FM: Monoid[F[E]], FP: Pointed[F]): (A => Writer[F[E], Option[B]]) =
(a: A) => f(a).fold(
e => Writer(FP.point(e), None),
b => Writer(FM.zero, Some(b)))
// helper for fixing the log storage format to List
def listLogged[A, E, B](f: A => E \/ B) = logged[A, E, B, List](f)
// shorthand for a String logger with List storage
type W[+A] = Writer[List[String], A]
Now all you have to do is write your filtering function:
def keepOdd(n: Int): String \/ Int =
if (n % 2 == 1) \/.right(n) else \/.left(n + " was even")
You can try it instantly:
scala> List(5, 6) map(keepOdd)
res0: List[scalaz.\/[String,Int]] = List(\/-(5), -\/(6 was even))
Then you can use the traverse function to apply your function to a list of inputs, and collect both the logs written and the results:
scala> val x = List(5, 6).traverse[W, Option[Int]](listLogged(keepOdd))
x: W[List[Option[Int]]] = scalaz.WriterTFunctions$$anon$26#503d0400
// unwrap the results
scala> x.run
res11: (List[String], List[Option[Int]]) = (List(6 was even),List(Some(5), None))
// we may even drop the None-s from the output
scala> val (logs, results) = x.map(_.flatten).run
logs: List[String] = List(6 was even)
results: List[Int] = List(5)
I don't think this can be done easily with a for comprehension. But you could use partition.
def getOffs(N:Int) = {
val (evens, odds) = 0 until N partition { x => x % 2 == 0 }
evens foreach { x => println("skipping " + x) }
odds
}
EDIT: To avoid printing the log messages after the partitioning is done, you can change the first line of the method like this:
val (evens, odds) = (0 until N).view.partition { x => x % 2 == 0 }