I'm trying to write a function in scala that finds the Sum of any (passed) function from a to b. Additionally , I'm trying to do it in a tail-wise recursive manner. I managed a tailwise recursive factorial function , so now i want to pass it to the "Summation" function and have it find the sum of all factorials from lower-bound a to upper-bound b . Here's what i have so far
object Sum {
def Summation( f : Double => Double , a: Double , b: Double):Double = {
def tailwiseSummation(accumulator:Double , count:Double):Double = {
if(count > b) accumulator
else tailwiseSummation(accumulator + f, a+1) // i dont know what to do here
}
}
def Factorial(num: Double): Double = { // i want to pass this function to `Summation`
def tailwise(accumulator: Double, deprecator: Double): Double = {
if (deprecator == 0) accumulator
else tailwise(accumulator * deprecator, deprecator - 1) // deprecator deprecating 1 unit at a time
}
tailwise(1, num)
}
}
can someone please help ?
You almost have it. Call f with count and add 1 to count in the recursive call tailwiseSummation. Also, you need the initialization function tailwiseSummation(f(a), a + 1) just like Factorial.
object Sum {
def Summation( f : Double => Double , a: Double , b: Double):Double = {
def tailwiseSummation(accumulator:Double , count:Double):Double = {
if(count > b) accumulator
else tailwiseSummation(accumulator + f(count), count+1)
}
// accumulator starts with f(a) , so count starts from a+1 to remove off-by-one error
tailwiseSummation(f(a), a + 1)
}
def Factorial(num: Double): Double = {
def tailwise(accumulator: Double, deprecator: Double): Double = {
if (deprecator == 0) accumulator
else tailwise(accumulator * deprecator, deprecator - 1) // deprecator deprecating 1 unit at a time
}
tailwise(1, num)
}
}
Run it:
scala> Sum.Summation(Sum.Factorial(_), 1, 5)
res0: Double = 153.0
Generic recursion over the range could be something like that :
def makeSum(f: Double => Double, a:Double, b:Double, step:Double = 1.0):Double = {
def makeSumAcc(f:Double =>Double, a:Double, b:Double, acc:Double) = {
if (a>=b) acc
else makeSumAcc(f, a+step, b, acc+f(a))
}
makeSum(f, a, b, 0)
}
Related
New to Scala and functional programming in general. Have the following code snippet which means to calculate the sum over a closed interval of Ints. Have implemented both tail-recursive method (sum1) and non-tail-recursive method (sum2).
package test
import scala.annotation.tailrec
object Currying extends App{
def sum1(f:Int=>Int)(a:Int, b:Int): (Int, Int) => Int = {
require(a <= b, "Received a=" + a + " and b=" + b)
#tailrec
def sum(a:Int, acc:Int) : Int = {
if(a > b) acc
else sum(a+1, acc + f(a))
}
sum
}
println("sum1(x=>x*x)(1, 4)=" + sum1(x=>x*x)(1, 4))
println("sum1(x=>x*x*x)(1, 4)=" + sum1(x=>x*x*x)(1, 4))
def sum2(f:Int=>Int)(a:Int, b:Int): Int => Int = {
def sum(a:Int) : Int = {
if(a > b) 0
else f(a) + sum(a+1)
}
sum
}
println("sum2(x=>x*x)(1, 4)=" + sum2(x=>x*x)(1, 4))
println("sum2(x=>x*x*x)(1, 4)=" + sum2(x=>x*x*x)(1, 4))
}
The print-outs, however, do not return actual Ints, but what appears to be a function itself:
sum(x=>x*x)(1, 4)=week2.Currying$$$Lambda$12/1468177767#3d24753a
sum(x=>x*x*x)(1, 4)=week2.Currying$$$Lambda$12/1468177767#67b64c45
sum2(x=>x*x)(1, 4)=week2.Currying$$$Lambda$15/1626877848#2f7a2457
sum2(x=>x*x*x)(1, 4)=week2.Currying$$$Lambda$15/1626877848#6108b2d7
Process finished with exit code 0
Clearly I'm doing something dumb in the currying, but I can't for the life of me figure it out.
I want to write a totient-function with scala (recursive).
Euler's totient function counts the positive integers up to a given integer n that are relatively prime to n
I came up with:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
private def isDividable(divisor: Int) = number % divisor == 0
}
}
For readability I created a small function isDividable.
This function I want to use in my recursive helper-method.
Unfortunately I get the following error:
Error:(12, 22) value isDividable is not a member of Int
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
Question: Can someone explain to me, what I did wrong and how I can fix it?
Edit:
for completeness I will add the valid implementation of the totient function:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 0) accumulator
else {
if (number.isCoprimeTo(currentN)) helper(currentN - 1, accumulator + 1)
else helper(currentN - 1, accumulator)
}
helper(number, 0)
}
private[Totient] def isCoprimeTo(otherNumber: Int): Boolean = {
gcd(number, otherNumber) == 1
}
private def gcd(firstNumber: Int, secondNumber: Int): Int =
if (secondNumber == 0) firstNumber else gcd(secondNumber, firstNumber % secondNumber)
}
}
private without extra information mean here "accessible only by other methods of Improvements but for the same instance of Improvements".
That means you can call isDividable to get the result for the same number for which you call totient/helper, but it doesn't becomes an extension method (because it is not visible outside of Improvements).
To fix that you can change the scope of the method, e.g. to make it visible to all methods defined within Totient:
object Totient {
implicit class Improvements(val number: Int) {
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (number.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
// notice [Totient] after private
private[Totient] def isDividable(divisor: Int) = number % divisor == 0
}
}
This compiles in my ammonite and works:
# import Totient._
import Totient._
# 12.totient
res2: Int = 6
Another option is to call isDividable/isCoprimeTo from this instead of number. This way, the compiler doesn't have to perform an implicit resolution at all to get the method. With your original code:
def totient: Int = {
#tailrec
def helper(currentN: Int, accumulator: Int): Int =
if (currentN == 1) accumulator
else {
if (this.isDividable(currentN)) helper(currentN - 1, accumulator)
else helper(currentN - 1, accumulator + 1)
}
helper(number, 0)
}
(You can even leave out the call to this entirely and simply have isDividable(currentN), but that makes the code less clear.)
I'm trying to understand how to leverage monads in scala to solve simple problems as way of building up my familiarity. One simple problem is estimating PI using a functional random number generator. I'm including the code below for a simple stream based approach.
I'm looking for help in translating this to a monadic approach. For example, is there an idiomatic way convert this code to using the state (and other monads) in a stack safe way?
trait RNG {
def nextInt: (Int, RNG)
def nextDouble: (Double, RNG)
}
case class Point(x: Double, y: Double) {
val isInCircle = (x * x + y * y) < 1.0
}
object RNG {
def nonNegativeInt(rng: RNG): (Int, RNG) = {
val (ni, rng2) = rng.nextInt
if (ni > 0) (ni, rng2)
else if (ni == Int.MinValue) (0, rng2)
else (ni + Int.MaxValue, rng2)
}
def double(rng: RNG): (Double, RNG) = {
val (ni, rng2) = nonNegativeInt(rng)
(ni.toDouble / Int.MaxValue, rng2)
}
case class Simple(seed: Long) extends RNG {
def nextInt: (Int, RNG) = {
val newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
val nextRNG = Simple(newSeed)
val n = (newSeed >>> 16).toInt
(n, nextRNG)
}
def nextDouble: (Double, RNG) = {
val (n, nextRNG) = nextInt
double(nextRNG)
}
}
}
object PI {
import RNG._
def doubleStream(rng: Simple):Stream[Double] = rng.nextDouble match {
case (d:Double, next:Simple) => d #:: doubleStream(next)
}
def estimate(rng: Simple, iter: Int): Double = {
val doubles = doubleStream(rng).take(iter)
val inside = (doubles zip doubles.drop(3))
.map { case (a, b) => Point(a, b) }
.filter(p => p.isInCircle)
.size * 1.0
(inside / iter) * 4.0
}
}
// > PI.estimate(RNG.Simple(10), 100000)
// res1: Double = 3.14944
I suspect I'm looking for something like replicateM from the Applicative monad in cats but I'm not sure how to line up the types or how to do it in a way that doesn't accumulate intermediate results in memory. Or, is there a way to do it with a for comprehension that can iteratively build up Points?
Id you want to iterate using monad in a stack safe way, then there is a tailRecM method implemented in Monad type class:
// assuming random generated [-1.0,1.0]
def calculatePi[F[_]](iterations: Int)
(random: => F[Double])
(implicit F: Monad[F]): F[Double] = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations): F[Either[Iterations, Double]] = for {
x <- random
y <- random
isInCircle = (x * x + y * y) < 1.0
newTotal = data.total + 1
newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
// iterates until Right value is returned
F.tailRecM(Iterations(0, 0))(step)
}
calculatePi(10000)(Future { Random.nextDouble }).onComplete(println)
It uses by-name param because you could try to pass there something like Future (even though the Future is not lawful), which are eager, so you would end up with evaluating the same thing time and time again. With by name param at least you have the chance of passing there a recipe for side-effecting random. Of course, if we use Option, List as a monad holding our "random" number, we should also expect funny results.
The correct solution would be using something that ensures that this F[A] is lazily evaluated, and any side effect inside is evaluated each time you need a value from inside. For that you basically have to use some of Effects type classes, like e.g. Sync from Cats Effects.
def calculatePi[F[_]](iterations: Int)
(random: F[Double])
(implicit F: Sync[F]): F[Double] = {
...
}
calculatePi(10000)(Coeval( Random.nextDouble )).value
calculatePi(10000)(Task( Random.nextDouble )).runAsync
Alternatively, if you don't care about purity that much, you could pass side effecting function or object instead of F[Int] for generating random numbers.
// simplified, hardcoded F=Coeval
def calculatePi(iterations: Int)
(random: () => Double): Double = {
case class Iterations(total: Int, inCircle: Int)
def step(data: Iterations) = Coeval {
val x = random()
val y = random()
val isInCircle = (x * x + y * y) < 1.0
val newTotal = data.total + 1
val newInCircle = data.inCircle + (if (isInCircle) 1 else 0)
if (newTotal >= iterations) Right(newInCircle.toDouble / newTotal.toDouble * 4.0)
else Left(Iterations(newTotal, newInCircle))
}
Monad[Coeval].tailRecM(Iterations(0, 0))(step).value
}
Here is another approach that my friend Charles Miller came up with. It's a bit more direct since it uses RNG directly but it follows the same approach provided by #Mateusz Kubuszok above that leverages Monad.
The key difference is that it leverages the State monad so we can thread the RNG state through the computation and generate the random numbers using the "pure" random number generator.
import cats._
import cats.data._
import cats.implicits._
object PICharles {
type RNG[A] = State[Long, A]
object RNG {
def nextLong: RNG[Long] =
State.modify[Long](
seed ⇒ (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL
) >> State.get
def nextInt: RNG[Int] = nextLong.map(l ⇒ (l >>> 16).toInt)
def nextNatural: RNG[Int] = nextInt.map { i ⇒
if (i > 0) i
else if (i == Int.MinValue) 0
else i + Int.MaxValue
}
def nextDouble: RNG[Double] = nextNatural.map(_.toDouble / Int.MaxValue)
def runRng[A](seed: Long)(rng: RNG[A]): A = rng.runA(seed).value
def unsafeRunRng[A]: RNG[A] ⇒ A = runRng(System.currentTimeMillis)
}
object PI {
case class Step(count: Int, inCircle: Int)
def calculatePi(iterations: Int): RNG[Double] = {
def step(s: Step): RNG[Either[Step, Double]] =
for {
x ← RNG.nextDouble
y ← RNG.nextDouble
isInCircle = (x * x + y * y) < 1.0
newInCircle = s.inCircle + (if (isInCircle) 1 else 0)
} yield {
if (s.count >= iterations)
Right(s.inCircle.toDouble / s.count.toDouble * 4.0)
else
Left(Step(s.count + 1, newInCircle))
}
Monad[RNG].tailRecM(Step(0, 0))(step(_))
}
def unsafeCalculatePi(iterations: Int) =
RNG.unsafeRunRng(calculatePi(iterations))
}
}
Thanks Charles & Mateusz for your help!
I am new to scala.
Lately I have tried to write some math functions, but I don't understand what I am doing wrong.
import scala.annotation.tailrec
import scala.math.{pow, sqrt}
object HikeStatProcessor {
def mean(list: List[Double]): Double = {
sum(list, value => value) / list.size
}
def std(list: List[Double]): Double = {
val means: Double = mean(list)
sqrt(pow(sum(list, (head: Double) => head - means), 2) / list.size)
}
private def sum(list: List[Double],
operation: Double => Double): Double = {
#tailrec
def innerCalc(xs: List[Double], accu: Double): Double = {
if (xs.isEmpty) return accu
println(accu + operation(xs.head))
innerCalc(xs.tail, accu + operation(xs.head))
}
innerCalc(list, 0)
}
}
val a = HikeStatProcessor.std(List(1, 2, 3))
Could you please provide a fix for the above code and a brief explanation of what I was doing wrong?
Consider this statement: sum(list, (head: Double) => head - means). Let's break it down into smaller steps.
sum(list , (head: Double) => head - means)
sum(List(1,2,3), x => x - 2)
sum(List(1-2, 2-2, 3-2))
-1 + 0 + 1 = 0
If you subtract the average from each element, the sum is always going to be zero (or close to it). What was your intention?
Thanks all for the answers.
I solved the issue by changing the def std to:
def std(list: List[Double]): Double = {
val means: Double = mean(list)
sqrt( sum(list, (head: Double) => pow(head - means, 2)) / (list.size - 1) )
}
The issue was caused by the fact that I did not evaluate the pow 2 within my anonymous function.
I have the following code
object TailRec
{
def func1(n:Int) : Int =
{
if (n < 10)
func2(n)
else
func1(n/10) + func2(n % 10)
}
def func2(n: Int) : Int =
{
#tailrec def _func2(n: Int, result: Int): Int =
{
if (n <= 1)
result
else
_func2(n-1,n*result)
}
_func2(n,1)
}
def test(n: Int) : Boolean =
{
if (n > 2)
n == func1(n)
else
false
}
}
I managed to rewrite func2 but I am not quite sure how to convert the bool function. I thought about match and case but I still need to call func1 to get the result for comparison. The other problem is how to break up the double function call in func1 itself. Any hints?
You have already converted func2 into tail-recursive form.
Similarly, using an additional accumulator, you can convert func1 into a tail-recursive form (I have modified the interface of func1, but you could also create another inner helper function). Since test isn't recursive, nothing has to be done here.
import scala.annotation.tailrec
object TailRec {
#tailrec def func1(n:Int, acc: Int): Int = {
if (n < 10) func2(n)
else func1(n / 10, acc + func2(n % 10))
}
def func2(n: Int): Int = {
#tailrec def _func2(n: Int, result: Int): Int = {
if (n <= 1) result
else _func2(n-1,n*result)
}
_func2(n,1)
}
def test(n: Int): Boolean = (n > 2) && (n == func1(n, 0))
}