Stringbuilder (Scala) - Substituting all instances of one character with another - scala

I'm trying to write a function that takes a region (from the marker pos and cursor pos) and substitutes all instances of character 'X' with character 'Y'.
For example, the user input would be the following:
subChar('g', 'x')
I know how to get the region (I think), it's just the substitution that has confused me. I've looked at similar questions on here, yet I still can't seem to get my head around it.
Also, can I simply apply the function to the region, or do I need to take the region and do something like toString() and THEN apply the rest of the syntax?
Here is what I have so far:
def subChar(s: Char, t: Char) {
var region = (lwr until upr)
region.filterNot('x' == 'y')
}
If anyone has any pointers I'd thoroughly appreciate it!

Well, to test it, I need lwr and upr and a String to operate on.
scala> def subChar (input: String, s: Char, t: Char, lwr: Int, upr: Int): String =
| input.zipWithIndex.map { case (c, i) => if (i >= lwr && i < upr && c == s) t else c}.mkString ("")
subChar: (input: String, s: Char, t: Char, lwr: Int, upr: Int)String
scala> subChar ("dodadodado", 'd', 'l', 1, 5)
res39: String = dolalodado
If that data is given in the outer context - as instance variables or something, you don't need them as parameters.
But notice, that a method, which returns a result, needs a '='.
Another, constant topic is, from where to count indexes and what part of interval is inclusive/exclusive so test it out and adjust it to your needs.

Related

Stringbuilder - Replacing all instances of one character with another**

First time posting on here, let me know if I need to change my format and I will do so.
I need to extract a defined region from the buffer, and apply code that will substitute character 'x' with character 'y', which I have attempted below:
buffer.substring(lwr,upr).replace(s,t)
However that fails all of my JUNIT tests and I can't wrap my head around why.
Does anybody have any pointers? Thank you!
EDIT:
For example, given the following:
a p p r o p r i a t e (Marker position is 2, cursor position is 6)
^ ^
Doing "subChar('p', 'x') should result in this being the output:
a p x r o x r i a t e (Marker position and cursor position DO NOT CHANGE)
^ ^
If you take a string, then substring something, then invoke replace on the result, the resulting string will have nothing to do with the original string, thus your solution obviously cannot work.
The indexing scheme from the linked answer remains the same, the answer is easily generalizable to arbitrary functions that can be applied to characters:
def mapBetween(str: String, start: Int, end: Int)(f: Char => Char) = {
val (a, bc) = str.splitAt(start)
val (b, c) = bc.splitAt(end - start)
a + b.map(f) + c
}
def replaceBetween(str: String, start: Int, end: Int, what: Char, byWhat: Char): String = {
mapBetween(str, start, end){ c =>
if (c == what) byWhat else c
}
}
With the above definitions, this here:
println(replaceBetween("appropriate", 2, 6, 'p', 'x'))
produces:
apxroxriate
I think your problem is your Buffer, I created a ScalaFiddle that demonstrates it for simple String and a simple List implementation:
val str = "appropriate"
println (str.replace('p', 'x')) // axxroxriate
val list = str.toList.map{
case c if c == 'p' => 'x'
case c => c
}
println (list) // List(a, x, x, r, o, x, r, i, a, t, e)
Check your implementation or add your implementation to your question.
Here is the example with a region:
def replaceBetween(str: String, start: Int, end: Int, what: Char, byWhat: Char): String = {
val prefix = str.take(start)
val postfix = str.drop(end)
val toMap = str.drop(start).take(end-start).replace(what, byWhat)
prefix + toMap + postfix
}
println(replaceBetween("appropriate", 2, 6, 'p', 'x'))
Here you can try yourself: ScalaFiddle

How to search efficiently in a nested collection in a functional way

I'd like to find the indices (coordinates) of the first element whose value is 4, in a nested Vector of Int, in a functional way.
val a = Vector(Vector(1,2,3), Vector(4,5), Vector(3,8,4))
a.map(_.zipWithIndex).zipWithIndex.collect{
case (col, i) =>
col.collectFirst {
case (num, index) if num == 4 =>
(i, index)
}
}.collectFirst {
case Some(x) ⇒ x
}
It returns:
Some((0, 1))
the coordinate of the first 4 occurrence.
This solution is quite simple, but it has a performance penalty, because the nested col.collect is performed for all the elements of the top Vector, when we are only interested in the 1st match.
One possible solution is to write a guard in the pattern matching. But I don't know how to write a guard based in a slow condition, and return something that has already been calculated in the guard.
Can it be done better?
Recursive maybe?
If you insist on using Vectors, something like this will work (for a non-indexed seq, you'd need a different approach):
#tailrec
findit(
what: Int,
lists: IndexedSeq[IndexedSeq[Int]],
i: Int = 0,
j: Int = 0
): Option[(Int, Int)] =
if(i >= lists.length) None
else if(j >= lists(i).length) findit(what, lists, i+1, 0)
else if(lists(i)(j) == what) Some((i,j))
else findit(what, lists, i, j+1)
A simple thing you can to without changing the algorithm is to use Scala streams to be able to exit as soon as you find the match. Streams are lazily evaluated as opposed to sequences.
Just make a change similar to this
a.map(_.zipWithIndex.toStream).zipWithIndex.toStream.collect{ ...
In terms of algorithmic changes, if you can somehow have your data sorted (even before you start to search) then you can use Binary search instead of looking at each element.
import scala.collection.Searching._
val dummy = 123
implicit val anOrdering = new Ordering[(Int, Int, Int)]{
override def compare(x: (Int, Int, Int), y: (Int, Int, Int)): Int = Integer.compare(x._1, y._1)
}
val seqOfIntsWithPosition = a.zipWithIndex.flatMap(vectorWithIndex => vectorWithIndex._1.zipWithIndex.map(intWithIndex => (intWithIndex._1, vectorWithIndex._2, intWithIndex._2)))
val sorted: IndexedSeq[(Int, Int, Int)] = seqOfIntsWithPosition.sortBy(_._1)
val element = sorted.search((4, dummy, dummy))
This code is not very pretty or readable, I just quickly wanted to show an example of how it could be done.

Curried update method

I'm trying to have curried apply and update methods like this:
def apply(i: Int)(j: Int) = matrix(i)(j)
def update(i: Int, j: Int, value: Int) =
new Matrix(n, m, (x, y) => if ((i,j) == (x,y)) value else matrix(x)(y))
Apply method works correctly, but update method complains:
scala> matrix(2)(1) = 1
<console>:16: error: missing arguments for method apply in class Matrix;
follow this method with `_' if you want to treat it as a partially applied function
matrix(2)(1) = 1
Calling directly update(2)(1)(1) works, so it is a conversion to update method that doesn't work properly. Where is my mistake?
The desugaring of assignment syntax into invocations of update maps the concatenation of a single argument list on the LHS of the assignment with the value on the RHS of the assignment to the first parameter block of the update method definition, irrespective of how many other parameter blocks the update method definition has. Whilst this transformation in a sense splits a single parameter block into two (one on the LHS, one on the RHS of the assignment), it will not further split the left parameter block in the way that you want.
I also think you're mistaken about the example of the explicit invocation of update that you show. This doesn't compile with the definition of update that you've given,
scala> class Matrix { def update(i: Int, j: Int, value: Int) = (i, j, value) }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#37176bc4
scala> m.update(1)(2)(3)
<console>:10: error: not enough arguments for method update: (i: Int, j: Int, value: Int)(Int, Int, Int).
Unspecified value parameters j, value.
m.update(1)(2)(3)
^
I suspect that during your experimentation you actually defined update like so,
scala> class Matrix { def update(i: Int)(j: Int)(value: Int) = (i, j, value) }
defined class Matrix
The update desugaring does apply to this definition, but probably not in the way that you expect: as described above, it only applies to the first argument list, which leads to constructs like,
scala> val m = new Matrix
m: Matrix = Matrix#39741f43
scala> (m() = 1)(2)(3)
res0: (Int, Int, Int) = (1,2,3)
Here the initial one-place parameter block is split to an empty parameter block on the LHS of the assignment (ie. the ()) and a one argument parameter block on the RHS (ie. the 1). The remainder of the parameter blocks from the original definition then follow.
If you're surprised by this behaviour you won't be the first.
The syntax you're after is achievable via a slightly different route,
scala> class Matrix {
| class MatrixAux(i : Int) {
| def apply(j : Int) = 23
| def update(j: Int, value: Int) = (i, j, value)
| }
|
| def apply(i: Int) = new MatrixAux(i)
| }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#3af30087
scala> m(1)(2) // invokes MatrixAux.apply
res0: Int = 23
scala> m(1)(2) = 3 // invokes MatrixAux.update
res1: (Int, Int, Int) = (1,2,3)
My guess is, that it is simply not supported. Probably not due to an explicit design decision, because I don't see why it shouldn't work in principle.
The translation concerned with apply, i.e., the one performed when converting m(i)(j) into m.apply(i, j) seems to be able to cope with currying. Run scala -print on your program to see the code resulting from the translation.
The translation concerned with update, on the other hand, doesn't seem to be able to cope with currying. Since the error message is missing arguments for method apply, it even looks as if the currying confuses the translator such that it tries to translate m(i)(j) = v into m.apply, but then screws up the number of required arguments. scala -print unfortunately won't help here, because the type checker terminates the translation too early.
Here is what the language specs (Scala 2.9, "6.15 Assignments") say about assignments. Since currying is not mentioned, I assume that it is not explicitly supported. I couldn't find the corresponding paragraph for apply, but I guess it is purely coincidental that currying works there.
An assignment f(args) = e with a function application to the left of
the ‘=’ operator is interpreted as f.update(args, e), i.e. the
invocation of an update function defined by f.

Union between sets

I am taking a Coursera Functional Programming in Scala class. This is the second week and I hit a wall. In the assignment we are working with Sets, but not the kind of Set we all meet in Java, for example. It is a Set that returns true if the value is in there and false otherwise. They say it's not a container, it's just a function.
To get it clear, I need your help. I don't want you to solve my assignment, it's just an example that I want to get the idea of what I should do.
/**
* We represent a set by its characteristic function, i.e.
* its `contains` predicate.
*/
type Set = Int => Boolean
/**
* Indicates whether a set contains a given element.
*/
def contains(s: Set, elem: Int): Boolean = s(elem)
/**
* Returns the set of the one given element.
*/
def singletonSet(elem: Int): Set = Set(elem)
/**
* Returns the union of the two given sets,
* the sets of all elements that are in either `s` or `t`.
*/
def union(s: Set, t: Set): Set = ???
This is the code. In the singletonSet I guess the way to solve it is to return the Set(elem), right?
If that is good, how am I supposed to make the union between the two? I am not new to programming but I can't see any way to do it. Since I shouldn't return a "set" of numbers.
This is what another student told me about sets: "But all a "Set" is is a function that takes an Int and returns a Boolean (Int => Boolean). Any function that takes an Int and returns a Boolean fits the type 'Set'."
What I tried in the union function is to have something like:
def union(s: Set, t: Set): Set = (s | t) //value | not a member of Int => Boolean
Any help would be appreciated :)
It seems the wall you are hitting is that you are unfamiliar with defining functions in Scala. In this particular case you need to define functions of type Int => Boolean, they take an Int and return a Boolean.
Here are some examples of function literals of type Int => Boolean. Try them in the Scala console or the Scala IDE worksheet:
(x: Int) => true
(x: Int) => false
(x: Int) => x == 2
(x: Int) => x == 10
(x: Int) => x == 2 || x == 10
(x: Int) => x % 2 == 0
Then all you have to do for the assignment is to use the same syntax, starting with (x: Int) => and then translate the meaning of union, intersect, ... into the right hand side of the expression.
Part of learning is giving it a genuine effort. I believe you can resubmit the solution multiple times, so don't hesitate to submit and iterate if you don't get 10/10 on the first try. All you need is compiling code. Good luck!
A possible hint is to look at the types. Look at the Set type. It is actually a type alias to a function from Int into Boolean.
Thus, when you have two sets, you actually have two functions. How can you use them to provide a function that represent the union of these Set? It must be your starting point.

Sort List according to more than only constraint in Scala

I am desperately trying to find a way to sort a List of strings, where the strings are predefined identifiers of following form: a1.1, a1.2,..., a1.100, a2.1, a2.2,....,a2.100,...,b1.1, b1.2,.. and so on, which is alread the correct ordering. So each identifier is first ordered by its first character (descending alphabetic order) and within this ordering descending ordered by consecutive numbers. I have tried sortWith by providing a sorting function specifying the above rule for all two consecutive list members.
scala> List("a1.102", "b2.2", "b2.1", "a1.1").sortWith((a: String, b: String) => a.take(1) < b.take(1) && a.drop(1).toDouble < b.drop(1).toDouble)
res2: List[java.lang.String] = List(a1.102, a1.1, b2.2, b2.1)
This is not the ordering I expected. However, by swapping the ordering of the expressions, as
scala> List("a1.102", "b2.2", "b2.1", "a1.1").sortWith((a: String, b: String) => (a.drop(1).toDouble < b.drop(1).toDouble && a.take(1) < b.take(2)))
res3: List[java.lang.String] = List(a1.1, a1.102, b2.1, b2.2)
this indeed gives me (at least for this example) the desired ordering, which I do not understand neither.
I would be so thankful, if somebody could give me a hint what exactly is going on there and how I can sort lists as I wish (with a more complex boolean expression than only comparing < or >). A further question: The strings I am sorting (in my example) are actually keys from a HashMap m. Will any solution effect sorting m by its keys within
m.toSeq.sortWith((a: (String, String), b: (String, String)) => a._1.drop(1).toDouble < b._1.drop(1).toDouble && a._1.take(1) < b._1.take(1))
Many thanks in advanced!
Update: I misread your example—you want a1.2 to precede a1.102, which the toDouble versions below won't get right. I'd suggest the following instead:
items.sortBy { s =>
val Array(x, y) = s.tail.split('.')
(s.head, x.toInt, y.toInt)
}
Here we use Scala's Ordering instance for Tuple3[Char, Int, Int].
It looks like you have a typo in your second ("correct") version: b.take(2) should doesn't make sense, and should be b.take(1) to match the first. Once you fix that, you get the same (incorrect) ordering.
The real problem is that you only need the second condition in the case where the numbers match. So the following works as desired:
val items = List("a1.102", "b2.2", "b2.1", "a1.1")
items.sortWith((a, b) =>
a.head < b.head || (a.head == b.head && a.tail.toDouble < b.tail.toDouble)
)
I'd actually suggest the following, though:
items.sortBy(s => s.head -> s.tail.toDouble)
Here we take advantage of the fact that Scala provides an appropriate Ordering instance for Tuple2[Char, Double], so we can just provide a transformation function that turns your items into that type.
And to answer your last question: yes, either of these approaches should work just fine with your Map example.
Create a tuple containing the string before the "." and then the integer after the ".". This will use a lexicographic order for the first part and an order on the integer for the second part.
scala> val order = Ordering.by((s:String) => (s.split("\\.")(0),s.split("\\.")(1).toInt))
order: scala.math.Ordering[String] = scala.math.Ordering$$anon$7#384eb259
scala> res2
res8: List[java.lang.String] = List(a1.5, a2.2, b1.11, b1.8, a1.10)
scala> res2.sorted(order)
res7: List[java.lang.String] = List(a1.5, a1.10, a2.2, b1.8, b1.11)
So consider what happens when your sorting function is passed a="a1.1" and b="a1.102".
What you'd like is for the function to return true. However, a.take(1) < b.take(1) returns false, so the function returns false.
Think about your cases a bit more carefully
if the prefix is equal, and the tails are ordered properly, then the arguments are ordered properly
if the prefixes are not equal, then the arguments are ordered properly only if the prefixes are.
So try this instead:
(a: String, b: String) => if (a.take(1) == b.take(1)) a.drop(1).toDouble < b.drop(1).toDouble else a.take(1) < b.take(1)
And that returns the proper ordering:
scala> List("a1.102", "b2.2", "b2.1", "a1.1").sortWith((a: String, b: String) => if (a.take(1) == b.take(1)) a.drop(1).toDouble < b.drop(1).toDouble else a.take(1) < b.take(1))
res8: List[java.lang.String] = List(a1.1, a1.102, b2.1, b2.2)
The reason it worked for you with the reversed ordering was luck. Consider the extra input "c0" to see what was happening:
scala> List("c0", "a1.102", "b2.2", "b2.1", "a1.1").sortWith((a: String, b: String) => (a.drop(1).toDouble < b.drop(1).toDouble && a.take(1) < b.take(2)))
res1: List[java.lang.String] = List(c0, a1.1, a1.102, b2.1, b2.2)
The reversed function sorts on the numeric part of the string first, then on the prefix. It just so happens that your numeric ordering you gave also preserved the prefix ordering, but that won't always be the case.