I am new to Scala and functional programming.
I was solving problem where you have to read number, and then that number of integers. After that you should calculate sum of all digits in all the integers.
Here is my code
def sumDigits(line: String) =
line.foldLeft(0)(_ + _.toInt - '0'.toInt)
def main(args: Array[String]) {
val numberOfLines = Console.readInt
val lines = for (i <- 1 to numberOfLines) yield Console.readLine
println(lines.foldLeft(0)( _ + sumDigits(_)))
}
Is there more elegant or efficient way?
sumDigits() can be implemented easier with sum:
def sumDigits(line: String) = line.map(_.asDigit).sum
Second foldLeft() can also be replaced with sum:
lines.map(sumDigits).sum
Which brings us to the final version (notice there is no main, instead with extend App):
object Main extends App {
def sumDigits(line: String) = line.map(_.asDigit).sum
val lines = for (_ <- 1 to Console.readInt) yield Console.readLine
println(lines.map(sumDigits).sum)
}
Or if you really want to squeeze as much as possible in one line, inline sumDigits (not recommended):
lines.map(_.map(_.asDigit).sum).sum
I like compact code, so I might (if I was really going for brevity)
object Reads extends App {
import Console._
println( Seq.fill(readInt){readLine.map(_ - '0').sum}.sum )
}
which sets the number of lines inline and does the processing as you go. No error checking, though. You could throw in a .filter(_.isDigit) right after the readLine to at least discard non-digits. You might also def p[A](a: A) = { println(a); a } and wrap the reads in p so you can see what had been typed (by default on some platforms at least there's no echo to screen).
One-liner Answer:
Iterator.continually(Console.readLine).take(Console.readInt).toList.flatten.map(_.asDigit).sum
To start with, you have to do some kind of parsing on line to break apart the existing decimal integers sub-strings:
val numbers = "5 1 4 9 16 25"
val ints = numbers.split("\\s+").toList.map(_.toInt)
Then you want to pull off the first one as the count and keep the rest to decode and sum:
val count :: numbers = ints
Then use the built-in sum method:
val sum = numbers.sum
Altogether in the REPL:
scala> val numbers = "5 1 4 9 16 25"
numbers: String = 5 1 4 9 16 25
scala> val ints = numbers.split("\\s+").toList.map(_.toInt)
ints: List[Int] = List(5, 1, 4, 9, 16, 25)
scala> val count :: numbers = ints
count: Int = 5
numbers: List[Int] = List(1, 4, 9, 16, 25)
scala> val sum = numbers.sum
sum: Int = 55
If you want to do something with the leading number count, you could verify that it's correct:
scala> assert(count == numbers.length)
Which produces no output, since the assertion passes.
Related
Hi I am new to scala functional programming methodology. I want to input a number to my function and check if it is a good number or not.
A number is a good number if its every digit is larger than the sum of digits which are on the right side of that digit.
For example:
9620 is good as (2 > 0, 6 > 2+0, 9 > 6+2+0)
steps I am using to solve this is
1. converting a number to string and reversing it
2. storing all digits of the reversed number as elements of a list
3. applying for loop from i equals 1 to length of number - 1
4. calculating sum of first i digits as num2
5. extracting ith digit from the list as digit1 which is one digit ahead of the first i numbers for which we calculated sum because list starts from zero.
6. comparing output of 4th and 5th step. if num1 is greater than num2 then we will break the for loop and come out of the loop to print it is not a good number.
please find my code below
val num1 = 9521.toString.reverse
val list1 = num1.map(_.todigit).toList
for (i <- 1 to num1.length - 1) {
val num2 = num1.take(i).map(_.toDigits) sum
val digit1 = list1(i)
if (num2 > digit1) {
print("number is not a good number")
break
}
}
I know this is not the most optimized way to solve this problem. Also I am looking for a way to code this using tail recursion where I pass two numbers and get all the good numbers falling in between those two numbers.
Can this be done in more optimized way?
Thanks in advance!
No String conversions required.
val n = 9620
val isGood = Stream.iterate(n)(_/10)
.takeWhile(_>0)
.map(_%10)
.foldLeft((true,-1)){ case ((bool,sum),digit) =>
(bool && digit > sum, sum+digit)
}._1
Here is a purely numeric version using a recursive function.
def isGood(n: Int): Boolean = {
#tailrec
def loop(n: Int, sum: Int): Boolean =
(n == 0) || (n%10 > sum && loop(n/10, sum + n%10))
loop(n/10, n%10)
}
This should compile into an efficient loop.
Using this function:(This will be the efficient way as the function forall will not traverse the entire list of digits. it stops when it finds the false condition immediately ( ie., when v(i)>v.drop(i+1).sum becomes false) while traversing from left to right of the vector v. )
def isGood(n: Int)= {
val v1 = n.toString.map(_.asDigit)
val v = if(v1.last!=0) v1 else v1.dropRight(1)
(0 to v.size-1).forall(i=>v(i)>v.drop(i+1).sum)
}
If we want to find good numbers in an interval of integers ranging from n1 to n2 we can use this function:
def goodNums(n1:Int,n2:Int) = (n1 to n2).filter(isGood(_))
In Scala REPL:
scala> isGood(9620)
res51: Boolean = true
scala> isGood(9600)
res52: Boolean = false
scala> isGood(9641)
res53: Boolean = false
scala> isGood(9521)
res54: Boolean = true
scala> goodNums(412,534)
res66: scala.collection.immutable.IndexedSeq[Int] = Vector(420, 421, 430, 510, 520, 521, 530, 531)
scala> goodNums(3412,5334)
res67: scala.collection.immutable.IndexedSeq[Int] = Vector(4210, 5210, 5310)
This is a more functional way. pairs is a list of tuples between a digit and the sum of the following digits. It is easy to create these tuples with drop, take and slice (a combination of drop and take) methods.
Finally I can represent my condition in an expressive way with forall method.
val n = 9620
val str = n.toString
val pairs = for { x <- 1 until str.length } yield (str.slice(x - 1, x).toInt, str.drop(x).map(_.asDigit).sum)
pairs.forall { case (a, b) => a > b }
If you want to be functional and expressive avoid to use break. If you need to check a condition for each element is a good idea to move your problem to collections, so you can use forAll.
This is not the case, but if you want performance (if you don't want to create an entire pairs collection because the condition for the first element is false) you can change your for collection from a Range to Stream.
(1 until str.length).toStream
Functional style tends to prefer monadic type things, such as maps and reduces. To make this look functional and clear, I'd do something like:
def isGood(value: Int) =
value.toString.reverse.map(digit=>Some(digit.asDigit)).
reduceLeft[Option[Int]]
{
case(sum, Some(digit)) => sum.collectFirst{case sum if sum < digit => sum+digit}
}.isDefined
Instead of using tail recursion to calculate this for ranges, just generate the range and then filter over it:
def goodInRange(low: Int, high: Int) = (low to high).filter(isGood(_))
I have a simple program written in C++. It generates random numbers, and stop when the sum of those numbers equal or greater than 100. The code looks like:
vector<int> container;
while(container.sum() <100)
{
int new_number = rand()%10 + 1 ;// generate a number in range 1 to 10
container.push_back(new_number); // add new number to the container
}
What is the best way to handle the task in Scala? (without using while loop?)
It seems that FoldLeft or FoldRight function doesn't have ability to break at a condition?
Create an infinite Stream of random numbers (requires very little CPU and memory), take only what you need, then turn the result Stream into the desired collection type.
val randoms = Stream.continually(util.Random.nextInt(10)+1)
val container = randoms.take(randoms.scan(0)(_+_).indexWhere(_>=100)).toVector
Added bonus is that the sums are calculated as you go, i.e. added to the previous sum, not summing from the beginning each time.
Here's one approach to handle a while loop using a tail-recursive function as follows:
#scala.annotation.tailrec
def addToContainer(container: Vector[Int], max: Int): Vector[Int] = {
val newContainer = container ++ Vector(scala.util.Random.nextInt(10) + 1)
if (newContainer.sum >= max) container
else addToContainer(newContainer, max)
}
addToContainer(Vector[Int](), 100)
// res1: Vector[Int] = Vector(9, 9, 5, 9, 3, 5, 2, 5, 10, 7, 6, 4, 5, 5, 9, 3)
res1.sum
// res2: Int = 96
Here's one way to do it:
val randomNumberGenerator = new scala.util.Random
def sumUntil(list: List[Int]): List[Int] = list match {
case exceeds if list.filter(_ > 0).sum > 100 => list
case _ => sumUntil(list :+ (randomNumberGenerator.nextInt(10) + 1))
}
To explain the solution:
Create an instance of scala.util.Random which will help us generate random numbers
sumUntil will pattern match; if the sum of the list exceeds 100, return it.
In the event that the sum does not exceed 100, call sumUntil again, but with another random number generated between 10 and 1 (inclusive). Keep in mind that the _ means, "I don't care about the value, or even the type." _ is anything else but the case where the sum of all the integers in our list is greater than 100.
If you're new to Scala, I understand that it may be a bit rough on the eyes to read. Below is a refined version:
val randomNumberGenerator = new scala.util.Random
def sumUntil(list: List[Int]): List[Int] = list match {
case exceeds if sumList(list) > 100 => list
case _ => sumUntil(appendRandomNumberToList(list))
}
private def sumList(list: List[Int]): Int = {
list.filter(_ > 0).sum
}
private def appendRandomNumberToList(list: List[Int]): List[Int] = {
list :+ randomNumberGenerator.nextInt(10) + 1
}
If your loop just scans through the collection, use fold or reduce.
If it needs some custom terminate condition, recursion is favored.
For example, my input is:
scala> val myList = List("7842", "abf45", "abd", "56")
myList: List[String] = List(7842, abf45, abd, 56)
7842 and 56 can be converted to Int; therefore, my expected output is 2. We can assume that negative integers don't happen, so -67 is not possible.
This is what I have so far:
scala> myList.map(x => Try(x.toInt).getOrElse(-1)).count(_ > -1)
res15: Int = 2
This should work correctly, but I feel like I am missing a more elegant and readable solution, because all I have to do is count number of successes.
I would caution against using exception handling (like Try) in control flow -- it's very slow.
Here's a solution that uses idiomatic Scala collection operations, performs well, and will not count negative numbers:
scala> val myList = List("7842", "abf45", "abd", "56")
myList: List[String] = List(7842, abf45, abd, 56)
scala> myList.count(_.forall(_.isDigit))
res8: Int = 2
EDIT: #immibis pointed out that this won't detect strings of numbers that exceed Integer.MaxValue. If this is a concern, I would recommend one of the following approaches:
import scala.util.Try
myList.count(x => Try(x.toInt).filter(_ >= 0).isSuccess)
or, if you want to keep the performance of my first answer while still handling this edge case:
import scala.util.Try
myList.count(x => x.forall(_.isDigit) && Try(x.toInt).filter(_ >= 0).isSuccess)
This is a bit shorter:
myList.count(x => Try(x.toInt).isSuccess)
Note that this solution will handle any string that can be converted to integer via .toInt, including negative numbers.
You may consider string.matches method with regex as well, to match only positive integers:
val myList = List("7842", "abf45", "abd", "-56")
// myList: List[String] = List(7842, abf45, abd, -56)
myList.count(_.matches("\\d+"))
// res18: Int = 1
If negative integers need to be counted (and take into account possible +/- signs):
myList.count(_.matches("[+-]?\\d+"))
// res17: Int = 2
Starting Scala 2.13 and the introduction of String::toIntOption, we can count items ("34"/"2s3") for which applying toIntOption (Some(34)/None) is defined (true/false):
List("34", "abf45", "2s3", "56").count(_.toIntOption.isDefined) // 2
I want to serialize an into into a Byte array or array buffer.
I realise that I can use 'java.nio.ByteBuffer' but I am experimenting for fun and trying to do it myself.
The following code works for positive Int but goes wrong when I serialize a negative Int.
Can anyone explain why or show me a correction?
import scala.collection.mutable.ArrayBuffer
object b {
val INTBYTES:Int = 4 // int is 4 bytes
def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
val buf = new ArrayBuffer[Byte](INTBYTES)
for(i <- 0 until INTBYTES) {
buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
}
buf
}
}
the following test works as expected:-
int the REPL it prints:-
scala> val test:Int = 0x4f0f0f0f
test: Int = 1326386959
scala> println(test.toBinaryString)
1001111000011110000111100001111
scala> val t1 = b.toArrayBuf(test)
t1: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(79, 15, 15, 15)
scala> t1.foreach( it => printf("%s ",it.toInt.toBinaryString))
1001111 1111 1111 1111
but this with a negative int does something wierd:-
scala> val test2:Int = 0x8f0f0f0f
test2: Int = -1894838513
scala> println(test2.toBinaryString)
10001111000011110000111100001111
scala> val t2 = b.toArrayBuf(test2)
t2: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(-113, 15, 15, 15)
scala> t2.foreach( it => printf("%s ",it.toInt.toBinaryString))
11111111111111111111111110001111 1111 1111 1111
notice that the first byte has been 1 filled for the whole int it shoild be '10001111'
Any ideas?
FYI
Im using :-
scala -version
Scala code runner version 2.10.1 -- Copyright 2002-2013, LAMP/EPFL
java -fullversion
java full version "1.7.0_40-b31"
with OpenJDK
Thanks
Scala's toBinaryString method defers to the Java one on Integer. From those documents:
public static String toBinaryString(int i)
Returns a string representation of the integer argument as an unsigned
integer in base 2. The unsigned integer value is the argument plus
2^32 if the argument is negative; otherwise it is equal to the
argument. This value is converted to a string of ASCII digits in
binary (base 2) with no extra leading 0s.
In other words it's working as specified. Your bit-twiddling seems to be OK, but when you're printing the numbers out, you need to realise that the number of characters is dependent on the length of the data type. (E.g. -1: Int in binary is 11111111111111111111111111111111 while -1: Byte is 11111111.) You get away with it for positive numbers only because the leading zeros are not displayed, as specified above.
Solution: make your own toBinaryString for bytes, or just taking the rightmost 8 digits from the Int version should work (though less efficient) i.e.
it.toInt.toBinaryString.takeRight(8)
Taking Luigi's advice I hacked up a pimp for Byte that provides a toBinaryString that works properly, in case anyone else is struggling with similar problems here is what I did.
object b {
val INTBYTES:Int = 4 // int is 4 bytes
val SIZEBYTE:Short = 8
def toArrayBuf(x:Int): ArrayBuffer[Byte] = {
val buf = new ArrayBuffer[Byte](INTBYTES)
for(i <- 0 until INTBYTES) {
buf += ((x >>> (INTBYTES - i - 1 << 3)) & 0xFF).toByte
}
buf
}
def toBinaryString(x: Byte): String = {
val buf = new StringBuilder(SIZEBYTE)
for(i <- 0 until SIZEBYTE) {
buf.append((x >>> (SIZEBYTE - i - 1)) & 0x01)
}
buf.toString()
}
}
//pimp Byte
implicit def fooBar(byte: Byte) = new {def toBinaryString = b.toBinaryString(byte)}
Now when I run the previous experiment it works properly
scala> val test:Int = 0x4f0f0f0f
test: Int = 1326386959
scala> println(test.toBinaryString)
1001111000011110000111100001111
scala> val t1 = toArrayBuf(test)
t1: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(79, 15, 15, 15)
scala> t1.foreach( it => printf("%s ",it.toBinaryString))
01001111 00001111 00001111 00001111
and
scala> val test2:Int = 0x8f0f0f0f
test2: Int = -1894838513
scala> println(test2.toBinaryString)
10001111000011110000111100001111
scala> val t2 = toArrayBuf(test2)
t2: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(-113, 15, 15, 15)
scala> t2.foreach( it => printf("%s ",it.toBinaryString))
10001111 00001111 00001111 00001111
Thanks Luigi
Suppose I want a Scala data structure that implements a 2-dimensional table of counts that can change over time (i.e., individual cells in the table can be incremented or decremented). What should I be using to do this?
I could use a 2-dimensional array:
val x = Array.fill[Int](1, 2) = 0
x(1)(2) += 1
But Arrays are mutable, and I guess I should slightly prefer immutable data structures.
So I thought about using a 2-dimensional Vector:
val x = Vector.fill[Int](1, 2) = 0
// how do I update this? I want to write something like val newX : Vector[Vector[Int]] = x.add((1, 2), 1)
// but I'm not sure how
But I'm not sure how to get a new vector with only a single element changed.
What's the best approach?
Best depends on what your criteria are. The simplest immutable variant is to use a map from (Int,Int) to your count:
var c = (for (i <- 0 to 99; j <- 0 to 99) yield (i,j) -> 0).toMap
Then you access your values with c(i,j) and set them with c += ((i,j) -> n); c += ((i,j) -> (c(i,j)+1)) is a little bit annoying, but it's not too bad.
Faster is to use nested Vectors--by about a factor of 2 to 3, depending on whether you tend to re-set the same element over and over or not--but it has an ugly update method:
var v = Vector.fill(100,100)(0)
v(82)(49) // Easy enough
v = v.updated(82, v(82).updated(49, v(82)(49)+1) // Ouch!
Faster yet (by about 2x) is to have only one vector which you index into:
var u = Vector.fill(100*100)(0)
u(82*100 + 49) // Um, you think I can always remember to do this right?
u = u.updated(82*100 + 49, u(82*100 + 49)+1) // Well, that's actually better
If you don't need immutability and your table size isn't going to change, just use an array as you've shown. It's ~200x faster than the fastest vector solution if all you're doing is incrementing and decrementing an integer.
If you want to do this in a very general and functional (but not necessarily performant) way, you can use lenses. Here's an example of how you could use Scalaz 7's implementation, for example:
import scalaz._
def at[A](i: Int): Lens[Seq[A], A] = Lens.lensg(a => a.updated(i, _), (_(i)))
def at2d[A](i: Int, j: Int) = at[Seq[A]](i) andThen at(j)
And a little bit of setup:
val table = Vector.tabulate(3, 4)(_ + _)
def show[A](t: Seq[Seq[A]]) = t.map(_ mkString " ") mkString "\n"
Which gives us:
scala> show(table)
res0: String =
0 1 2 3
1 2 3 4
2 3 4 5
We can use our lens like this:
scala> show(at2d(1, 2).set(table, 9))
res1: String =
0 1 2 3
1 2 9 4
2 3 4 5
Or we can just get the value at a given cell:
scala> val v: Int = at2d(2, 3).get(table)
v: Int = 5
Or do a lot of more complex things, like apply a function to a particular cell:
scala> show(at2d(2, 2).mod(((_: Int) * 2), table))
res8: String =
0 1 2 3
1 2 3 4
2 3 8 5
And so on.
There isn't a built-in method for this, perhaps because it would require the Vector to know that it contains Vectors, or Vectors or Vectors etc, whereas most methods are generic, and it would require a separate method for each number of dimensions, because you need to specify a co-ordinate arg for each dimension.
However, you can add these yourself; the following will take you up to 4D, although you could just add the bits for 2D if that's all you need:
object UpdatableVector {
implicit def vectorToUpdatableVector2[T](v: Vector[Vector[T]]) = new UpdatableVector2(v)
implicit def vectorToUpdatableVector3[T](v: Vector[Vector[Vector[T]]]) = new UpdatableVector3(v)
implicit def vectorToUpdatableVector4[T](v: Vector[Vector[Vector[Vector[T]]]]) = new UpdatableVector4(v)
class UpdatableVector2[T](v: Vector[Vector[T]]) {
def updated2(c1: Int, c2: Int)(newVal: T) =
v.updated(c1, v(c1).updated(c2, newVal))
}
class UpdatableVector3[T](v: Vector[Vector[Vector[T]]]) {
def updated3(c1: Int, c2: Int, c3: Int)(newVal: T) =
v.updated(c1, v(c1).updated2(c2, c3)(newVal))
}
class UpdatableVector4[T](v: Vector[Vector[Vector[Vector[T]]]]) {
def updated4(c1: Int, c2: Int, c3: Int, c4: Int)(newVal: T) =
v.updated(c1, v(c1).updated3(c2, c3, c4)(newVal))
}
}
In Scala 2.10 you don't need the implicit defs and can just add the implicit keyword to the class definitions.
Test:
import UpdatableVector._
val v2 = Vector.fill(2,2)(0)
val r2 = v2.updated2(1,1)(42)
println(r2) // Vector(Vector(0, 0), Vector(0, 42))
val v3 = Vector.fill(2,2,2)(0)
val r3 = v3.updated3(1,1,1)(42)
println(r3) // etc
Hope that's useful.