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.
Related
I'm trying to make a function that calculates how many combinations of elements with repetition there are given an array of values and a exact sum value.
But I'm getting an error:
Error:(23, 38) type arguments [Int] do not conform to method empty's type parameter bounds [T <: AnyRef]
r(maxValue,WrappedArray.empty[Int],Set[WrappedArray[Int]]()).size
It seems there is a type problem in the empty set I'm trying to pass to the function.
I choosed WrappedArrays following this [question]: Scala: lightweight way to put Arrays in a Set or Map in order to be able to have a set of arrays without duplicates.
import scala.collection.mutable.WrappedArray
def Combinations(maxValue: Int): Int = {
val values= Array(1,2,5,10)
def r (a:Int,can:WrappedArray[Int],sol:Set[WrappedArray[Int]]): Set[WrappedArray[Int]] ={
values.map(x=> if (a-x > 0) r(a-x,can:+x,sol) else if (a-x == 0) sol + (can:+x).sorted else sol).reduce((x, y)=>x union y)
}
r(maxValue,WrappedArray.empty[Int],Set[WrappedArray[Int]]()).size
}
Combinations(4)
Thanks
WrappedArray.empy is bounded by AnyRef, as Int inherits from AnyVal you cannot declare your wrappedArray this way.
However you can declare your empty array this way new WrappedArray.ofInt(Array())
Here is a little fiddle for you
https://scalafiddle.io/sf/PioRREd/0
I've never seen anyone ever importing WrappedArray for anything. It's a rather obscure implementation detail for providing collection methods on ordinary arrays, it has no place in the solution of combinatoric problems. Another general remark: methodNames are written in camel-case, starting with a lowercase letter.
Here is a more idiomatic (and also much simpler) solution:
def numCombinations(
sum: Int,
coins: List[Int] = List(1, 2, 5, 10)
): Long = {
coins match {
case Nil => if (sum == 0) 1L else 0L
case h :: t => {
(0 to sum / h)
.map { i => numCombinations(sum - i * h, t) }
.sum
}
}
}
println(numCombinations(4))
Example: for n = 4, it will find the combinations
1 + 1 + 1 + 1
1 + 1 + 2
2 + 2
and output 3.
Consider 2+7 == 3+6 (mod 5). Can you some how use scala syntactic sugar to achieve the same in scala code?
Keep in mind that 2+7 and 3+6 are regular scala Int so overriding the + or == to be mod 5 doesn't work. I'm actually interested in more complex congruences on algebras A. I could do A.congruent(a,b), and write that with some nice symbols like A.~(a,b), but I am interested in a == b (A) or a ==(A) b or perhaps A(a == b). Something where the congruence appears inbetween the terms a and b.
The bottom line of my struggles is that the congruence is defined for type A, and a,b are some elements passed to A but not actually of type A. E.g. A might be a group of matrices and the congruence is if individual matrices a and b differ by a scalar i.e. a*b^-1=sI_n. In particular, a, b will live inside of many groups and the congruence will change based on that. So I it isn't possible to simply add a reference within a and b back to A.
Some how the right solution seems to be the mathematical one, label the equivalence with A not the variables a and b. Yet scala syntactic sugar may not have such a sweetness in mind. Any suggestions appreciated.
Try this:
implicit class ModEquals(a: Int) {
def %%(n: Int) = new { def ===(b: Int) = (a - b) % n == 0 }
}
Usage:
7 %% 3 === 10
This solution enriches Ints with a %% method that takes the congruence. In this example, it's just modulu, but this can easily be extended to anything. The returned object is a class that has an === method defined to implements the equality check.
import scala.languageFeature.implicitConversions
import scala.languageFeature.reflectiveCalls
case class ModuloArg(list: List[Int]) {
assert(list.size > 1)
def ==%%?(m: Int) = {
val hm = list.head % m
list.tail.filter(i => (i % m) != hm).isEmpty
}
def ::%%(n: Int) = ModuloArg(n :: list)
}
implicit class ModuloArgOps(i: Int) {
def ::%%(n: Int) = ModuloArg(n :: i :: Nil)
}
Now, you can use these to check modulo equality,
// 4 == 10 (mod 3)
scala> val mod3Equal4And10 = 4 ::%% 10 ==%%? 3
// mod3Equal4And10: Boolean = true
// 4 == 11 (mod 3)
scala> val mod3Equal4And11 = 4 ::%% 11 ==%%? 3
//mod3Equal4And11: Boolean = false
// 4 == 10 == 13 == 16 (mod 3)
scala> val mod3Equal4And10And13And16 = 4 ::%% 10 ::%% 13 ::%% 16 ==%%? 3
// mod3Equal4And10And13And16: Boolean = true
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.
I have a graph, with each vertex connected to 6 neighbors.
While constructing the graph and making declarations of the connections, I would like to use a syntax like this:
1. val vertex1, vertex2 = new Vertex
2. val index = 3 // a number between 0 and 5
3. vertex1 + index = vertex2
The result should be that vertex2 be declared assigned as index-th neighbor of vertex1, equivalent to:
4. vertex1.neighbors(index) = vertex2
While frobbing with the implementation of Vertex.+, I came up with the following:
5. def +(idx: Int) = neighbors(idx)
which, very surprisingly indeed, did not cause line 3 to be underlined red by my IDE (IntelliJIdea, BTW).
However, compilation of line 3 offsprang the following message:
error: missing arguments for method + in class Vertex;
follow this method with `_' if you want to treat it as a partially applied function
Next, I tried with an extractor, but actually, that doesn't seem to fit the case very well.
Does anybody have any clue if what I'm trying to achieve is anywhat feasible?
Thank you
You probably can achieve what you want by using := instead of =. Take a look at this illustrating repl session:
scala> class X { def +(x:X) = x; def :=(x:X) = x }
defined class X
scala> val a = new X;
a: X = X#7d283b68
scala> val b = new X;
b: X = X#44a06d88
scala> val c = new X;
c: X = X#fb88599
scala> a + b := c
res8: X = X#fb88599
As one of the comments stated, the custom = requires two parameter, for example vertex1(i)=vertex2 is dessugared to vertext.update(i,vertex2) thus forbidding the exact syntax you proposed. On the other hand := is a regular custom operator and a:=b will dessugar to a.:=(b).
Now we still have one consideration to do. Is the precedence going to work as you intent? The answer is yes, according to the Language Specification section 6.12.3. + has higher precedence than :=, so it ends up working as (a+b):=c.
Not exactly what you want, just playing with right-associativity:
scala> class Vertex {
| val neighbors = new Array[Vertex](6)
| def :=< (n: Int) = (this, n)
| def >=: (conn: (Vertex, Int)) {
| val (that, n) = conn
| that.neighbors(n) = this
| this.neighbors((n+3)%6) = that
| }
| }
defined class Vertex
scala> val a, b, c, d = new Vertex
a: Vertex = Vertex#c42aea
b: Vertex = Vertex#dd9f68
c: Vertex = Vertex#ca0c9
d: Vertex = Vertex#10fed2c
scala> a :=<0>=: b ; a :=<1>=: c ; d :=<5>=: a
scala> a.neighbors
res25: Array[Vertex] = Array(Vertex#dd9f68, Vertex#ca0c9, Vertex#10fed2c, null, null, null)
I am new to Scala, and ran across a small hiccup that has been annoying me.
Initializing two vars in parallel works great: var (x,y) = (1,2)
However I can't find a way to assign new values in parallel: (x,y) = (x+y,y-x) //invalid syntax
I end up writing something like this: val xtmp = x+y; y = x-y; x = xtmp
I realize writing functional code is one way of avoiding this, but there are certain situations where vars just make more sense.
I have two questions:
1) Is there a better way of doing this? Am I missing something?
2) What is the reason for not allowing true parallel assignment?
Unfortunately, you cannot do multiple assignments in Scala. But you may use tuples, if they fit your problem:
scala> var xy = (1,2)
xy: (Int, Int) = (1,2)
scala> xy = (xy._1 + xy._2, xy._2 - xy._1)
xy: (Int, Int) = (3,1)
This way, xy is one tuple with two values. The first value can be accessed using xy._1, the second one using xy._2.
Scala has 2 types of variables: vals and vars. Vals are similar to Java's final variables, so as far as I understand from what you're asking, the only way to assign new values in parallel to vals is by:
scala> val (x, y) = (1, 2);
or
scala> val s = (3, 4);
s: (Int, Int) = (3,4)
scala> s._1
res1: Int = 3
scala> s._2
res2: Int = 4