Pattern match for Integer range - scala

The purpose of my function is to add 5 to an integer as long as that integer is greater than 0 and less than or equal to 7. I try:
val add5Partial : PartialFunction[Int, Int] = {
case d if (0 < d <= 7) => d + 5;
}
I get:
<console>:8: error: type mismatch;
found : Int(7)
required: Boolean
case d if (0 < d <= 7) => d + 5;
Any tips?

Scala do not support such syntax out of the box, so you have to write:
val partial : Int => Int = {
case d if (d > 0) && (d <= 7) => d + 5;
}
Alternatively you could do:
val partial : Int => Int = {
case d if 1 to 7 contains d => d + 5;
}

You can't do this in a single comparison. You need to use:
(d > 0) && (d <= 7)
As you have done it, it will evaluate one comparison to a Boolean and then fail to use this as an int in the second comparison.

You can do any of the following:
val f = (n: Int) ⇒ if (n > 0 && n <= 7) n + 5 else n
// or ...
def f(n: Int) = if (n > 0 && n <= 7) n + 5 else n
// or ...
def f(n: Int): Int = n match {
case n if n > 0 && n <= 7 ⇒ n + 5
case _ ⇒ n
}
// or (to speak of ... the comment by #om-nom-nom)
def f(n: Int) = n match {
case n if 0 to 7 contains n ⇒ n + 5
case _ ⇒ n
}

Related

Why did my code get TLE on leetcode since I actually evaluate each slot only once?

I'm trying to solve problem longest palindromic substring in leetcode in a functional way (using LazyList as cache). However, I got TLE result and I don't know why. Can anyone explain why this code is not efficient?
object Solution {
def longestPalindrome(s: String): String = {
val n = s.length
var ans = (0, 0)
var cnt = 1
def logic(i: Int, j: Int): Int = (i, j) match {
case (i, j) if i > j => -1
case (i, j) if i == j => 1
case (i, j) if s(i) != s(j) => 0
case (i, j) if i + 1 == j => 2
case (i, j) =>
if(mem(i + 1)(j - 1) == 0) 0
else j - i + 1
}
lazy val mem: LazyList[LazyList[Int]] = LazyList.tabulate(n, n) {
case (i, j) => {
val n = logic(i, j)
if(n > cnt) {
cnt = n
ans = (i, j)
}
n
}
}
mem.foreach(_.force)
// println(mem)
ans match {
case (i, j) => s.slice(i, j + 1)
}
}
}

scala: sum of squares of every even-positioned digits starting from 2nd position

I can use the following code to sum up squares of every digits. how could it be changed to only do it for even-positioned digits starting from 2nd position ?
var sum:Int = num.toString.map{ _.asDigit }.map(x => x*x).sum
If you want every even-positioned value, one way of doing that is with grouped and head.
To start at the second digit, take the tail of the list before grouping.
val sum = num.toString.map{ _.asDigit }.tail.grouped(2).map(_.head).map(x => x*x).sum
See it working here.
A possible solution to keep only even-positioned is to use zipWithIndex:
// Your initial code
def squareDigitsSummation(n: Int): Int =
n.toString.map{ _.asDigit }.map(x => x*x).sum
def squareEvenPositionedDigitsSummation(n: Int): Int =
n.toString.view.
tail.
map(_.asDigit).
zipWithIndex.
collect { case (n, i) if i % 2 != 0 => n * n }.
sum
assert(squareDigitsSummation(1234) == 30)
assert(squareEvenPositionedDigitsSummation(1234) == 9)
Please note that zipWithIndex is 1-based, so I had to somewhat counter-intuitively negate the filter predicate to keep odd-indexed pairs (I assumed you wanted to have 0-based indexes, given you explicitly mentioned you didn't want the 0th element to be kept).
Sum of squares of even digits from the right - tail recursion
def sumOfEvenDigitsTailRecursion(num: Int): Int = {
#tailrec def impl(num: Int, idx: Int, acc: Int): Int = {
if (num == 0) acc
else if (idx % 2 == 0) impl(num / 10, idx + 1, acc + ((num % 10) * (num % 10)))
else impl(num / 10, idx + 1, acc)
}
impl(num, 1, 0)
}
assert(sumOfEvenDigitsTailRecursion(123456) == 5*5 + 3*3 +1*1)
Sum of squares of even digits from the left - tail recursion
def sumOfEvenDigitsTailRecursion(num: Int): Int = {
#tailrec def impl(num: Int, idx: Int, acc: Int, length: Int = -1): Int = {
if (length % 2 == 0) {
impl(num / 10, idx, acc + ((num % 10) * (num % 10)))
} else {
if (num == 0) acc
else if (idx % 2 == 0) impl(num / 10, idx + 1, acc + ((num % 10) * (num % 10)))
else impl(num / 10, idx + 1, acc)
}
}
impl(num, 1, 0, (Math.log10(num) + 1).toInt)
}
assert(sumOfEvenDigitsTailRecursion(123456) == 2*2 + 4*4 + 6*6)
Sum of squares of even digits from the left - iterators
def sumOfEvenDigitsIterators(num: Int): Int =
num
.toString
.iterator
.map(_.asDigit)
.grouped(2)
.collect{ case ArraySeq(_, b) => b }
.map(x => x * x)
.sum
Benchmark: sbt "jmh:run -i 10 -wi 10 -f 2 -t 1 bench.So59627557"
#State(Scope.Benchmark)
#BenchmarkMode(Array(Mode.Throughput))
class So59627557 {
def _sumOfEvenDigitsIterators(num: Int): Int =
num
.toString
.iterator
.map(_.asDigit)
.grouped(2)
.collect{ case ArraySeq(_, b) => b }
.map(x => x * x)
.sum
def _sumOfEvenDigitsTailRecursion(num: Int): Int = {
#tailrec def impl(num: Int, idx: Int, acc: Int, length: Int = -1): Int = {
if (length % 2 == 0) {
impl(num / 10, idx, acc + ((num % 10) * (num % 10)))
} else {
if (num == 0) acc
else if (idx % 2 == 0) impl(num / 10, idx + 1, acc + ((num % 10) * (num % 10)))
else impl(num / 10, idx + 1, acc)
}
}
impl(num, 1, 0, (Math.log10(num) + 1).toInt)
}
val num: Int = (math.random * 100000000).toInt
#Benchmark def sumOfEvenDigitsIterators: Int = _sumOfEvenDigitsIterators(num)
#Benchmark def sumOfEvenDigitsTailRecursion: Int = _sumOfEvenDigitsTailRecursion(num)
}
results
[info] Benchmark Mode Cnt Score Error Units
[info] So59627557.sumOfEvenDigitsIterators thrpt 20 2033487.342 ± 187156.764 ops/s
[info] So59627557.sumOfEvenDigitsTailRecursion thrpt 20 27431255.610 ± 835429.506 ops/s
Tail-recursive solution seems to have more than 10x throughput than iterators-based solution.
Why not use regex?
val num = 24874
var sum: Int = "\\d{2}".r
.findAllIn(num.toString)
.map(_.last.asDigit)
.map(v => v * v)
.sum

scala how to reduce while n > 0

I am wondering if there's a way to deal with a while (n > 0) loop in a more functional way, I have a small Scala app that counts the number of digits equal to K from a range from 1 to N:
for example 30 and 3 would return 4 [3, 13, 23, 30]
object NumKCount {
def main(args: Array[String]): Unit = {
println(countK(30,3))
}
def countKDigit(n:Int, k:Int):Int = {
var num = n
var count = 0
while (num > 10) {
val digit = num % 10
if (digit == k) {count += 1}
num = num / 10
}
if (num == k) {count += 1}
count
}
def countK(n:Int, k:Int):Int = {
1.to(n).foldLeft(0)((acc, x) => acc + countKDigit(x, k))
}
}
I'm looking for a way to define the function countKDigit using a purely functional approach
First expand number n into a sequence of digits
def digits(n: Int): Seq[Int] = {
if (n < 10) Seq(n)
else digits(n / 10) :+ n % 10
}
Then reduce the sequence by counting occurrences of k
def countKDigit(n:Int, k:Int):Int = {
digits(n).count(_ == k)
}
Or you can avoid countKDigit entirely by using flatMap
def countK(n:Int, k:Int):Int = {
1.to(n).flatMap(digits).count(_ == k)
}
Assuming that K is always 1 digit, you can convert n to String and use collect or filter, like below (there's not much functional stuff you can do with Integer):
def countKDigit(n: Int, k: Int): Int = {
n.toString.collect({ case c if c.asDigit == k => true }).size
}
or
def countKDigit(n: Int, k: Int): Int = {
n.toString.filter(c => c.asDigit == 3).length
}
E.g.
scala> 343.toString.collect({ case c if c.asDigit == 3 => true }).size
res18: Int = 2
scala> 343.toString.filter(c => c.asDigit == 3).length
res22: Int = 2
What about the following approach:
scala> val myInt = 346763
myInt: Int = 346763
scala> val target = 3
target: Int = 3
scala> val temp = List.tabulate(math.log10(myInt).toInt + 1)(x => math.pow(10, x).toInt)
temp: List[Int] = List(1, 10, 100, 1000, 10000, 100000)
scala> temp.map(x => myInt / x % 10)
res17: List[Int] = List(3, 6, 7, 6, 4, 3)
scala> temp.count(x => myInt / x % 10 == target)
res18: Int = 2
Counting the occurrences of a single digit in a number sequence.
def countK(n:Int, k:Int):Int = {
assert(k >= 0 && k <= 9)
1.to(n).mkString.count(_ == '0' + k)
}
If you really only want to modify countKDigit() to a more functional design, there's always recursion.
def countKDigit(n:Int, k:Int, acc: Int = 0):Int =
if (n == 0) acc
else countKDigit(n/10, k, if (n%10 == k) acc+1 else acc)

What's missing from this ScalaTest/ScalaCheck example?

I'm trying out ScalaCheck and haven't been able to figure out how to build the first example on the ScalaTest user's manual. I'm pretty sure that the following needs to be preceded by some imports and wrapped inside a class that extends from some library class. The page in the user's manual says to "mix in" PropertyChecks, but it doesn't give an example of an appropriate class to mix it into:
forAll { (n: Int, d: Int) =>
whenever (d != 0 && d != Integer.MIN_VALUE
&& n != Integer.MIN_VALUE) {
val f = new Fraction(n, d)
if (n < 0 && d < 0 || n > 0 && d > 0)
f.numer should be > 0
else if (n != 0)
f.numer should be < 0
else
f.numer should be === 0
f.denom should be > 0
}
}
I've been trying various combinations, but the best result I've gotten so far is compilation errors like this:
[info] Compiling 1 Scala source to .../target/scala-2.11/test-classes...
[error] .../src/test/scala/TestFraction.scala:14: value should is not a member of Int
[error] f.numer should be > 0
[error] ^
What would be a complete source file for the test, imports and all?
If you check the github repository of scala test here you can find some extra code here
github source scalatest
For your source this are the imports and the structure
import org.scalatest.{Matchers, FlatSpec}
import org.scalatest.prop.PropertyChecks
class Fraction(n: Int, d: Int) {
require(d != 0)
require(d != Integer.MIN_VALUE)
require(n != Integer.MIN_VALUE)
val numer = if (d < 0) -1 * n else n
val denom = d.abs
override def toString = numer + " / " + denom
}
class PropertySpec extends FlatSpec with PropertyChecks with Matchers {
forAll { (n: Int, d: Int) =>
whenever(d != 0 && d != Integer.MIN_VALUE
&& n != Integer.MIN_VALUE) {
val f = new Fraction(n, d)
if (n < 0 && d < 0 || n > 0 && d > 0)
f.numer should be > 0
else if (n != 0)
f.numer should be < 0
else
f.numer should be === 0
f.denom should be > 0
}
}
val invalidCombos =
Table(
("n", "d"),
(Integer.MIN_VALUE, Integer.MIN_VALUE),
(1, Integer.MIN_VALUE),
(Integer.MIN_VALUE, 1),
(Integer.MIN_VALUE, 0),
(1, 0)
)
forAll(invalidCombos) { (n: Int, d: Int) =>
evaluating {
new Fraction(n, d)
} should produce[IllegalArgumentException]
}
}
Recent versions of scalatest do not implementevaluating and mark === as obsolete.
So, I'd rewrite example as:
import org.scalatest._
import org.scalatest.prop.PropertyChecks
protected class Fraction(n: Int, d: Int) {
require(d != 0 && d != Integer.MIN_VALUE && n != Integer.MIN_VALUE)
val numer = if (d < 0) -1 * n else n
val denom = d.abs
override def toString = numer + " / " + denom
}
class SscceProps extends FlatSpec with PropertyChecks with Matchers {
it should "valid combos" in { forAll { (n: Int, d: Int) =>
whenever(d != 0 && d != Integer.MIN_VALUE && n != Integer.MIN_VALUE) {
val f = new Fraction(n, d)
if (n < 0 && d < 0 || n > 0 && d > 0) f.numer should be > 0
else if (n != 0) f.numer should be < 0
else f.numer shouldBe 0
f.denom should be > 0
}
}}
it should "invalid combos" in {
forAll(Table(
("n", "d"),
(Integer.MIN_VALUE, Integer.MIN_VALUE),
(1, Integer.MIN_VALUE),
(Integer.MIN_VALUE, 1),
(Integer.MIN_VALUE, 0),
(1, 0)
)) { (n: Int, d: Int) =>
an[IllegalArgumentException] should be thrownBy {new Fraction(n, d)}}
}
}

Idiomatic way to convert A => Seq[B]

I'd like to convert a single value into a collection of multiple "characteristics", without using a mutable data structure to collect the values. I'd like something like this fantasy construct which uses pattern matching, but does not stop after first match:
scala> 2 multimatch {
case i if i > 0 => "Positive"
case i if i < 0 => "Negative"
case i if (i % 2 == 0) => "Even"
//yadda yadda
}
res0: Seq[java.lang.String] = List(Positive, Even)
Using the pimp pattern, partial functions and repeated parameters, this is how close I can get:
class MultiMatcher[A](a: A) {
def multiMatch[B](pfs: PartialFunction[A, B]*): Seq[B] = {
pfs.map(_.lift(a)).collect{ case Some(v) => v }
}
}
implicit def toMultiMatcher[A](a:A): MultiMatcher[A] = new MultiMatcher(a)
2 multiMatch (
{ case i if i > 0 => "Positive" },
{ case i if i < 0 => "Negative" },
{ case i if i % 2 == 0 => "Even" }
)
// returns Seq[java.lang.String] = ArrayBuffer(Positive, Even)
First you define your characteristics as functions from Int to Option[String]
val pos = (i:Int) => if (i > 0) Some("Positive") else None
val neg = (i:Int) => if (i < 0) Some("Negative") else None
val even = (i:Int) => if (i % 2 == 0) Some("Even") else None
Then you make a list of characteristics.
val characteristics = pos::neg::even::Nil
And then you use flatmap to get a list of those characteristics that apply to a certain object.
scala> characteristics.flatMap(f=>f(2))
res6: List[java.lang.String] = List(Positive, Even)
First, define a multimatch function as follows:
scala> def multimatch[A,B]( value : A,ps: ( A => Boolean, B)*) =
| for ( p <- ps
| if (p._1(value))) yield p._2
multimatch: [A,B](value: A,ps: ((A) => Boolean, B)*)Seq[B]
Then, here we go:
scala> multimatch(2,
| ( ((x :Int) => x > 0) -> "POSITIVE"),
| ( ((x :Int) => x < 0) -> "NEGATIVE"),
| ( ((x :Int) => x % 2 == 0) -> "EVEN")
| )
res4: Seq[java.lang.String] = ArrayBuffer(POSITIVE, EVEN)
Or, less cluttered:
scala> multimatch(2,
| ( (x :Int) => x > 0 , "POSITIVE"),
| ( (x :Int) => x < 0, "NEGATIVE"),
| ( (x :Int) => x % 2 == 0, "EVEN")
| )
res5: Seq[java.lang.String] = ArrayBuffer(POSITIVE, EVEN)