Scala, collections, variable access scope - scala

Sorry, I got even no idea how to name a title, as I believe this is a dead simple thing.
I have function which is taking Int as an argument and returning List of Ints (after adding values to int trough loop, and couple if statements. Signature is a must)
My problem:
def a(i:Int) = { var l2 = List(1,2); l2.+:(1); l2; }
println(a(3)) // outputs List(1, 2)
Why function a is returning List(1,2) instead of List(3,1,2) ??
And what would be a correct solution in this situation?
I really appreciate your time to help me.

The method +: that you are calling on a List returns a new list with the element prepended. The original list is not modified.
In the statement l2.+:(1) you are ignoring the return value (the new list with the element prepended). Then you return l2, which still refers to the original List which contains the two elements 1 and 2.

You are missing an assignment (and you probably meant i instead of 1): l2 +:= i.
But in scala it is preferable to avoid using var:
def a(i: Int) = { i :: List(1, 2) }
(I guess your method is much more complex, but it's almost always possible to rewrite it that way)

Related

Removing duplicates (ints) in an array and replacing them with chars

So i'm trying to make a basic hitori solver, but i am not sure where i should start. I'm still new to Scala.
My first issue is that i'm trying to have an array of some ints (1,2,3,4,2)
and making the program output them like this: (1,2,3,4,B)
notice that the duplicate has become a char B.
Where do i start? Here is what i already did, but didn't do what i excatly need.
val s = lines.split(" ").toSet;
var jetSet = s
for(i<-jetSet){
print(i);
}
One way is to fold over the numbers, left to right, building the Set[Int], for the uniqueness test, and the list of output, as you go along.
val arr = Array(1,2,3,4,2)
arr.foldLeft((Set[Int](),List[String]())){case ((s,l),n) =>
if (s(n)) (s,"B" :: l)
else (s + n, n.toString :: l)
}._2.reverse // res0: List[String] = List(1, 2, 3, 4, B)
From here you can use mkString() to format the output as desired.
What I'd suggest is to break your program into a number of steps and try to solve those.
As a first step you could transform the list into tuples of the numbers and the number of times they have appeared so far ...
(1,2,3,4,2) becomes ((1,1),(2,1),(3,1),(4,1),(2,2)
Next step it's easy to map over this list returning the number if the count is 1 or the letter if it is greater.
That first step is a little bit tricky because as you walk through the list you need to keep track of how many you've seen so far of each letter.
When want to process a sequence and maintain some changing state as you do, you should use a fold. If you're not familiar with fold it has the following signature:
def foldLeft[B](z: B)(op: (B, A) => B): B
Note that the type of z (the initial value) has to match the type of the return value from the fold (B).
So one way to do this would be for type B to be a tuple of (outputList, seensofarCounts)
outputList would accumulate in each step by taking the next number and updating the map of how many of each numbers you've seen so far. "seensofarCounts" would be a map of the numbers and the current count.
So what you get out of the foldLeft is a tuple of (((1,1),(2,1),(3,1),(4,1),(2,2), Map(1 -> 1, 2, 2 ETC ... ))
Now you can map over that first element of the tuple as described above.
Once it's working you could avoid the last step by updating the numbers to letters as you work through the fold.
Usually this technique of breaking things into steps makes it simple to reason about, then when it's working you may see that some steps trivially collapse into each other.
Hope this helps.

Scala type mismatch when adding an element to an array

I have the following array:
var as = Array.empty[Tuple2[Int, Int]]
I am adding an element to it like this:
var nElem = Tuple2(current, current)
as += nElem
current is a var of type Int
However, I am getting this error:
Solution.scala:51: error: type mismatch;
found : (Int, Int)
required: String
as += nElem
I don't understand why this is appearing. I haven't declared a String anywhere.
+= is the string concatenation operator.
You are looking for :+ to append to an array. Note, that Array length is immutable, so :+=, will return a new array, with the nElem appended, and assign it to the as variable, the original array will stay unchanged (take this as a hint, that you are likely doing something in a suboptimal way).
Note, that if you find yourself using var, that is almost always a sign of a bad design in your code. Mutable objects and variables are considered really bad taste in functional programming. Sometimes, you can't get away without using them, but those are rare corner cases. Most of the time, you should not need mutability.
Also, do not use Tuple2. Just do Array.empty[(Int, Int)], nElem = (current, current) etc.
Use a :+= to modify the variable in place. However, remember this: Using both var and a mutable data structure at the same time (like Array) is a sign of really bad programming. Either is sometimes fine, though.
However, note that this operation is O(n), therefore pushing n elements like that is going to be slow, O(n²). Arrays are not meant to have elements pushed to back like that. You can alternatively use a var Vector instead and call .toArray() on it at the end or use a mutable val ArrayBuffer. However, prefer functional style of programming, unless it produces less readable code.
Also, avoid typing Tuple2 explicitly. Use Array.empty[(Int, Int)] and var nElem = (current, current).
The semantics of + are weird because of the automatic conversion to String in certain cases. To append to an array, use the :+ method:
as :+= nElem

How does foo(a)(b) += x work in Scala?

I have been counting occurences with a mutable map:
var bar = collection.mutable.Map[Int, Int]().withDefaultValue(0)
Now bar(a) += b works just fine, no matter if the key a is present in bar already or not (in which case it will then be added).
I tried the same thing with a mutable map of mutable maps:
var foo = collection.mutable.Map[Int, collection.mutable.Map[Int, Int]]().
withDefaultValue(collection.mutable.Map().withDefaultValue(0))
How does foo(a)(b) += x look without syntactic sugar?
Using What are all the instances of syntactic sugar in Scala? I would assume it expands to:
foo.apply(a).put(b, foo.apply(a).apply(b) + x)
But why does this not update foo itself accordingly like in the introductory example (i.e. foo will not have a dedicated value for key a if it wasn't present before)?
Edit: As Perseids pointed out, foo(a)(b) += x will change the mutable default value. Is this a desired feature?
Using getOrElseUpdate as suggested by DaoWen seems to be the best way to overcome both problems. But while that works well for functions of type Int => Int => Int it becomes really cumbersome for functions of type Int => Int => Int => Int => Int. So I'm still happy for any suggestions!
This is actually an issue with withDefaultValue, not the += operator. Your first withDefaultValue for foo returns a new mutable map if the given key does not exist. When you do the lookup foo(a)(b), if foo(a) doesn't exist, then it returns a new map, which we'll call tmp. foo(a)(b) += x then essentially expands to this:
val tmp = foo(a)
tmp(b) += x
The problem is that only tmp is being updated by +=, not foo. So your update is happening on tmp, but tmp gets thrown away after the call because it's never stored anywhere.
If you want your parent map to get updated, you might want to look into using getOrElseUpdate instead of relying on withDefaultValue.
Note: As Perseids points out in the comments below, withDefaultValue takes a by-value parameter. This means that every time you get an unset key from your map, it's going to return the same mutable map instance! This is yet another reason you should think about using getOrElseUpdate (which uses a by-name parameter), or at least withDefault, which takes a function. (That's all assuming that you actually want different map instances for each slot in your map...)
How does foo(a)(b) += x look without syntactic sugar?
It depends on whether or not the object returned by foo(a)(b) has a method named += or not. If it does, then it's equivalent to:
foo.apply(a).apply(b).+=(x)
If it doesn't, then it's equivalent to:
foo.apply(a).update(b, foo.apply(a).apply(b).+(x))
Except without the duplicate evaluation of foo.apply(a) (I think.)

Infinite streams in Scala

Say I have a function, for example the old favourite
def factorial(n:Int) = (BigInt(1) /: (1 to n)) (_*_)
Now I want to find the biggest value of n for which factorial(n) fits in a Long. I could do
(1 to 100) takeWhile (factorial(_) <= Long.MaxValue) last
This works, but the 100 is an arbitrary large number; what I really want on the left hand side is an infinite stream that keeps generating higher numbers until the takeWhile condition is met.
I've come up with
val s = Stream.continually(1).zipWithIndex.map(p => p._1 + p._2)
but is there a better way?
(I'm also aware I could get a solution recursively but that's not what I'm looking for.)
Stream.from(1)
creates a stream starting from 1 and incrementing by 1. It's all in the API docs.
A Solution Using Iterators
You can also use an Iterator instead of a Stream. The Stream keeps references of all computed values. So if you plan to visit each value only once, an iterator is a more efficient approach. The downside of the iterator is its mutability, though.
There are some nice convenience methods for creating Iterators defined on its companion object.
Edit
Unfortunately there's no short (library supported) way I know of to achieve something like
Stream.from(1) takeWhile (factorial(_) <= Long.MaxValue) last
The approach I take to advance an Iterator for a certain number of elements is drop(n: Int) or dropWhile:
Iterator.from(1).dropWhile( factorial(_) <= Long.MaxValue).next - 1
The - 1 works for this special purpose but is not a general solution. But it should be no problem to implement a last method on an Iterator using pimp my library. The problem is taking the last element of an infinite Iterator could be problematic. So it should be implemented as method like lastWith integrating the takeWhile.
An ugly workaround can be done using sliding, which is implemented for Iterator:
scala> Iterator.from(1).sliding(2).dropWhile(_.tail.head < 10).next.head
res12: Int = 9
as #ziggystar pointed out, Streams keeps the list of previously computed values in memory, so using Iterator is a great improvment.
to further improve the answer, I would argue that "infinite streams", are usually computed (or can be computed) based on pre-computed values. if this is the case (and in your factorial stream it definately is), I would suggest using Iterator.iterate instead.
would look roughly like this:
scala> val it = Iterator.iterate((1,BigInt(1))){case (i,f) => (i+1,f*(i+1))}
it: Iterator[(Int, scala.math.BigInt)] = non-empty iterator
then, you could do something like:
scala> it.find(_._2 >= Long.MaxValue).map(_._1).get - 1
res0: Int = 22
or use #ziggystar sliding solution...
another easy example that comes to mind, would be fibonacci numbers:
scala> val it = Iterator.iterate((1,1)){case (a,b) => (b,a+b)}.map(_._1)
it: Iterator[Int] = non-empty iterator
in these cases, your'e not computing your new element from scratch every time, but rather do an O(1) work for every new element, which would improve your running time even more.
The original "factorial" function is not optimal, since factorials are computed from scratch every time. The simplest/immutable implementation using memoization is like this:
val f : Stream[BigInt] = 1 #:: (Stream.from(1) zip f).map { case (x,y) => x * y }
And now, the answer can be computed like this:
println( "count: " + (f takeWhile (_<Long.MaxValue)).length )
The following variant does not test the current, but the next integer, in order to find and return the last valid number:
Iterator.from(1).find(i => factorial(i+1) > Long.MaxValue).get
Using .get here is acceptable, since find on an infinite sequence will never return None.

How do I insert something at a specific position of a mutable LinkedList?

Again, this seems like something that should be obvious.
I would like to insert an element into a linked list at a specific position.
In one case, this is where a field in the element is less than a certain value, so I can do it this way:
def Add(act:Elem):Unit = {
val (before, after) = myList.partition(elem.n >= _.n)
myList = (before :+ act) ++ after
}
... but this is really an immutable approach disguised as a mutable one. I don't think I can get at the LinkedList node that corresponds to the insertion point, so I can't mess with the "next" attribute.
It shouldn't be this difficult. Half the point of linked lists is so you insert things in the middle.
I'm still messing with a compiler generator (as in this question). Replacing lists with copies is just not the way to do this, as there are many recursive calls during which the lists are quite deliberately modified, so you may find that some of the recursive calls are still using the lists you just replaced.
I really want mutable lists, and straightforward mutable operations. I guess I can write my own collection classes, but I don't think the need is that unusual. Anyone implemented "proper" multable linked lists already?
EDIT
Some more detail
I should have perhaps chosen a different example. Typically, I've got a reference to the element by some other route, and I want to insert an new element in one of the linked lists this element is on (I'd be happy with the element being in one linked list as a start)
In the naive Java implementation I'm starting with, the element itself contains a next field (which I can then manipulate).
In the Scala LinkedList case, the linked list node contains a reference to the element, and so, given the element, I cannot easily find the LinkedList node and so the next field.
I can traverse the list again, but it might be very long.
It might help to assume a DoublyLinkedList and deleting the element as the operation I want to do, as it's clearer then that traversal isn't needed and so should be avoided. So in that case, assume I have found the element by some other means than traversing the linked list. I now want to delete the element. In the Java/naive case, the back and forward pointers are part of the element. In the Scala collections case, there's a DoublyLinkedList node somewhere that contains a reference to my element. But I can't go from element to that node without traversing the list again.
Random thoughts follow: I'm getting somewhere by mixing in a Trait that defines a next field (for my singly linked case). This trait might support iterating over the objects in the list, for example. But that would help me only for elements that are on one list at a time and I have objects that are on three (with, currently, three different "next" pointers called things like "nezt", "across" and "down").
I don't want a List of Nodes pointing to Elements, I wanta List of Elements that are Nodes (ie. have a next field).
Unfortunately, LinkedList is does not implement Buffer, so there isn't AFAIK a good way to do this out of the box. You actually do have access to the next field, however, so you can write your own. Something like this (warning, untested!; warning, low level code!):
def Add(act: Elem) {
var last = myList
while (last.next ne null && last.next.n >= act.n) last = last.next
var ins = LinkedList(act)
ins.next = last.next
last.next = ins
}
(You might want to add a special case for myList being empty, and for insertion before the first element. But you get the idea
Edit after clarification: Don't keep copies of the elements; keep copies of the list starting at that element. (That's what last is.) Then write an implicit conversion from a list of your thingy of choice to the head thingy itself. Unless you duplicate the collections methods in your element, you get all the power of the collections library and all the syntactic convenience of having an element with a next pointer, with only an extra object allocation as drawback.
Of course, you can always implement any low-level data structure you want, if you want to reinvent the wheel so that it fits your car better (so to speak).
Why are people going to such trouble?
scala> LinkedList(1, 2, 3)
res21: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3)
scala> val ll = LinkedList(1, 2, 3)
ll: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 3)
scala> ll.next.insert(LinkedList(0))
scala> ll
res23: scala.collection.mutable.LinkedList[Int] = LinkedList(1, 2, 0, 3)
scala> ll.insert(LinkedList(-1, -2))
scala> ll
res25: scala.collection.mutable.LinkedList[Int] = LinkedList(1, -1, -2, 2, 0, 3)
Of course, this doesn't answer the question after clarification, but I think Rex Kerr's idea of implicit conversions might be the way to go here. That, or just add a .elem before any method using the value. In fact, here's the implicit:
implicit def linkedListToA[A](ll: LinkedList[A]): A = ll.elem
Unpolished version: Inserts other into l the first time that the predicate p is true.
import scala.collection.mutable.LinkedList
import scala.annotation.tailrec
val list = LinkedList(1, 2, 3, 10, 11, 12)
def insertAfter[T](l: LinkedList[T], other: LinkedList[T], p: (T) => Boolean) {
#tailrec
def loop(x: LinkedList[T]) {
if (p(x.head)) {
other.next = x.next
x.next = other
return
}
if (x.next.isEmpty) {}
else loop(x.next)
}
loop(l)
}
insertAfter(list, LinkedList(100), (_:Int) >= 10)