The below code is written in scala,
val Array(f, t) = readLine().trim().split(" +").map(_.toInt)
I am not able to comprehend val Array(f, t).
To me, Array is class. Due to that, We can only create the object and with that object, we can access the function of the class. Or else We can access the static methods of the Array class without creating an object for it.
-- scala
def main(args: Array[String]): Unit = {
val n = readInt
val m = readInt
val f = Array.ofDim[Int](100000)
Arrays.fill(f, -1)
for (e <- 1 to m) {
val Array(f, t) = readLine().trim().split(" +").map(_.toInt)
// Code continues
}
}
That is called pattern matching (for example you can check this at Extractors). The code you mentioned means that please assign the first (index 0) value in the array resulting to f, assign the second (index 1) element to t and there should not be more or less values in the array. Both f and t are fresh variables.
You also mentioned the confusion with the val Array(...) syntax. It translates to the following method: scala.Array.unapplySeq[T](x:Array[T])
Related
Problem Statement
I will try to elaborate the case by means of a scenario. Lets take this question for instance.
Link to question: https://leetcode.com/problems/remove-element/
Given an array nums and a value target, remove all instances of
that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example: Given nums = [0,1,2,2,3,0,4,2], target = 2; the output =
5 (number of elements not equal to target) and modify the array to
[0,1,3,0,4]
The order of elements can be changed. It doesn't matter what you leave
beyond the new length.
My Approach
Step-1: Identify all the elements which are equal to the given target and move them to right hand side of the array while maintaining a counter.
Step-2: Drop all the elements from right.
Step-3: return (n - counter), where n is the array length and counter is the number of elements equal to target.
Below is the implementation of the same:
object RemoveElement {
// Link to question: https://leetcode.com/problems/remove-element/
def main(args: Array[String]): Unit = {
var nums = Array(3,2,2,3)
val target = 3
val result = removeElement(nums, target)
// nums = nums.dropRight(_.equals(target)) // POINT 1
println(s"Result: ${result}, Modified Array: [${nums.mkString(", ")}]")
}
def removeElement(nums: Array[Int], target: Int): Int = {
val n = nums.length
var left, counter = 0
var right = n - 1
while(left < right){
if(nums(left) != target){
left += 1
}
else {
// Find position of the elements which is not equal to target
if(nums(right) == target){
counter += 1
right -= 1
}
else{
// Swap the elements
counter += 1
val temp = nums(left)
nums(left) = nums(right)
nums(right) = temp
left += 1
right -= 1
}
}
}
// nums.dropWhile(_.equals(target)) // POINT 2
// nums = nums.dropRight(_.equals(target)) // POINT 3
return (n - counter)
}
}
POINT - 1: Makes absolute sense as the array nums is in the scope of main method, therefore, the statement would work as charm.
POINT - 2: These lines has no impact to the array nums.
POINT - 3: Gives error. I understand that the input argument (array nums) is of type val (i.e. passed by reference, and hence immutable within the scope of the method removeElement).
If I had an option of creating a new array, there wouldn't be any issue. But if I am required to return the modified array by adding/removing the elements (like in this question) to the calling method, how do I achieve that in Scala?
To make the case more generic, what is the way by which we can modify the input collections (passed as arguments) in Scala methods?
P.S.: If I do not remove elements from the input array itself, LeetCode fails my submission with below message:
How do I modify an input array passed to a method by reference?
Scala does not support pass-by-reference. The default is pass-by-value (or more precisely, a special case of pass-by-value which is sometimes known as call-by-object, call-by-sharing, or call-by-object-sharing). Scala also supports call-by-name.
So, you simply cannot pass an array to a method by reference in Scala. You will have to use another language which supports pass-by-reference such as C# (with the ref keyword) or C++. (Note that Java also doesn't support pass-by-reference.)
Something like this
object Solution {
def removeElement(nums: Array[Int], `val`: Int): Int = {
var p: Int = 0
nums.foreach(v => {
if (v != `val`) {
nums(p) = v
p += 1
}
})
p
}
}
I would like to use length of provided array inside parameters list. I tried
def find(xs: Array[Double], m:Int = xs.length*2) = ???
,but xs is not accessible for m parameter.
Is it possible to do that? How?
When defining default values of arguments, you can refer only to variables in the previous argument lists. Therefore, you need two argument lists:
def find(xs: Array[Double])(m: Int = xs.size * 2) = ???
Then you can call it as follows:
find(Array(1, 2, 3))(6)
and
find(Array(1, 2, 3))()
In this case an ugly alternative is to use an invalid length as the default:
def find(xs: Array[Double], _m: Int = -1) = {
val m = if (_m >= 0) _m else xs.length
I tried below code but it ultimately prints 5 zeros after giving the user defined values to array .
the below code takes array of size 5 and gives user defined values
object printarray {
def main(args:Array[String]) {
val arr = new Array[Int](5)
println("the values of array is ")
for(i<-0 to 4) {
val arr = scala.io.StdIn.readInt()
}
arr.foreach(println)
}
}
There are a couple of things that need improvement in the code.
You allocate an array of 5 elements named arr in the scope of the main method, but you also declare an additional value with the same name, arr, inside the for comprehension scope and read an Int into it, which you discard once you exit the for scope. Then, you print the array in the outer scope, which hasn't changed at all.
The first thing you need to make this work, is index into the array instead of creating a new value named arr in the inner scope:
object printarray {
def main(args:Array[String]) {
val arr = new Array[Int](5)
println("the values of array is ")
for (i <- 0 to 4) {
arr(i) = scala.io.StdIn.readInt()
}
arr.foreach(println)
}
}
To improve things further, you use the yield Scala synax to make this more concise:
val arr = for (i <- 0 to 4) yield StdIn.readInt()
This will not return an Array[Int], but an IndexedSeq[Int] with an underlying type of Vector[Int]. If you still want an Array[Int], you'll have to explicitly call toArray:
val arr: Array[Int] = (for (i <- 0 to 4) yield scala.io.StdIn.readInt()).toArray
In your for-loop you are reassigning the variable in every iteration. You can change it to:
for(i <- 0 to 4) {
arr(i) = scala.io.StdIn.readInt()
}
As a side-note, instead of declaring the arr before the loop you can simply do:
val arr = for(i <- 0 to 4) yield scala.io.StdIn.readInt()
What is the suitable way to compute hashCode of an Array that depends on its content?
Array.hashCode is for the array instance:
val h = a.hashCode
println(h == Array(1,2).hashCode) // false
a(0) = 42
println(h == a.hashCode) // true
Note: It'd be better to avoid copying the whole array, to a List for example, prior to computing the hashCode
Why I ask: I use an Array in a class (as a private field) because lookup time is critical, and its content is relevant to compute the hashCode of the class
from https://issues.scala-lang.org/browse/SI-1607, it says that the hashCode of Array is the hashCode from java, as scala Array are java Array. And scala could not changed it.
But it also says that scala has a suitable hashCode method in WrappedArray.
Thus:
val a = Array(1,2)
val h = a.toSeq.hashCode // wrapped it in a WrappedArray - no copy
println(h == Array(1,2).toSeq.hashCode) // true
a(0) = 42
println(h == a.toSeq.hashCode) // false
You can also use java.util.Arrays.hashCode(a), it's likely to be faster than a.toSeq.hashCode (since WrappedArray seems to inherit a non-array-specific implementation).
You can use the MurmurHash3 algorithm directly.
import scala.util.hashing.MurmurHash3
MurmurHash3.orderedHash(Array(1,2)))
I'm attempting to represent the basic strategy of a blackjack game as a map with integer keys whose values are a fixed length array of strings.
The keys represent the value of the player's hand, the array index represents the value of the dealers up card (hence the fixed length array of size 10 corresponding to card values 2-11). The string value in the array at the position corresponding to the dealer's up card contains the ideal play (stay, hit, split, double).
IE) player hand value is a hard 8, dealer up card is a 2. Basic strategy says the player should hit. To determine this using my map, I would get the array whose key is 8(player hand value = 8) and then looking at the string in array index 0 (Dealer up card = 2).
I've attempted to define it this way:
val hardHandBasicStrategy = collection.mutable.Map[Int,Array[String](10)]
but Scala doesn't seem to like this...
Please help me understand what I've done wrong, and/or suggest a way to make it work.
Scala doesn't have a type that represents arrays of a fixed size. You can either simply use arrays of size ten--this is what is normally done--or, if you want stronger guarantees that it really is size ten, you can construct a ten-long-array-class yourself:
class ArrayTen[T: ClassManifest](zero: T) {
protected val data = Array.fill(10)(zero)
def apply(i: Int) = data(i)
def update(i: Int, t: T) { data(i) = t }
protected def set(ts: Array[T]) { for (i <- data.indices) data(i) = ts(i) }
def map[U: ClassManifest](f: T => U) = {
val at = new ArrayTen(null.asInstanceOf[U])
at.set(data.map(f))
at
}
def foreach(f: T => Unit) { data.map(f) }
override def toString = data.mkString("#10[",",","]")
override def hashCode = scala.util.MurmurHash.arrayHash(data)
override def equals(a: Any) = a match {
case a: ArrayTen[_] => (data,a.data).zipped.forall(_ == _)
case _ => false
}
// Add other methods here if you really need them
}
Example:
scala> new ArrayTen("(nothing)")
res1: ArrayTen[java.lang.String] =
#10[(nothing),(nothing),(nothing),(nothing),(nothing),
(nothing),(nothing),(nothing),(nothing),(nothing)]
scala> res1(3) = "something!!!"
scala> res1
res3: ArrayTen[java.lang.String] =
#10[(nothing),(nothing),(nothing),something!!!,(nothing),
(nothing),(nothing),(nothing),(nothing),(nothing)]
If you need the the fixed-length array to take a parameter that determines the length, then you should
trait Size { size: Int }
class ArraySize[S <: Size, T: ClassManifest](zero: T, s: Size) {
protected val data = Array.fill(s.size)(zero)
...
}
You won't have all the collections goodies unless you reimplement them, but then again you don't want most of the goodies, since most of them can change the length of the array.