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
Related
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.
So I have a generic compose combinator.
Recall that the composition of two functions—f and g-- is h(x) = f(g(x))
def inc(x: Double) = x + 1
def double(x: Double) = 2 * x
def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x))
//TEST
println(compose(double, inc, 2.0))
//OUTPUT
// 6.0
But now I want to implement the self-composition iterator combinator, recursively, using my compose function where:
def selfIter[T](f: T=>T, n: Int) = f composed with itself n times.
I tried doing this:
def selfIter[T](f: T, n: Int): T = {
if(n == 0) f
else f + selfIter(f, n-1)
}
//TEST
println(selfIter(compose(double, inc, 2.0), 2))
I get an error, I know I'm doing something fundamentally wrong, but I cant figure out what I need to do.
In this case, the output should be 14.0 because first call will be 2(2+1) = 6.0, and then second call will be 2(6.0 + 1) = 14.0
Question: How should I refactor my code so that selfIter will compose f with itself n times until we have n == 0, and returns the final value
The easiest way to solve this kind of problems is to use the combinators provided by Scala. Also you should first compose the function you want to use and then apply the input
def compose[A,B,C](f: B => C, g: A => B): A => C = g.andThen(f)
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f))
println(selfIter(compose(double, inc), 2)(2.0))
If compose signature could not be changed then
def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x))
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f))
println(selfIter[Double](compose(double, inc, _), 2)(2.0))
But it makes much more sense the first solution
There are a few things going wrong here.
This f + selfIter(f, n-1) says that f (type T) must have a + method that takes another T as an argument. But you don't want to add these things, you want to compose them.
Here's a simpler way to get the result you're after.
Stream.iterate(2.0)(compose(double, inc, _))(2) // res0: Double = 14.0
If you're intent on a recursive method, this appears to achieve your goal.
def selfIter[T](start:T, n:Int)(f:T=>T): T = {
if (n < 2) f(start)
else f(selfIter(start, n-1)(f))
}
selfIter(2.0, 2)(compose(double, inc, _)) // res0: Double = 14.0
I'd like to pad a vector of strings with a given value on all sides (i.e., top, bottom, right, left). For example, the following vector of strings:
1122
1122
3344
3344
should look like this:
000000
011220
011220
033440
033440
000000
Of course, this representation is purely for visual purposes and it is actually a Vector of strings.
I found I can accomplish this with the following code.
val v = Vector("1122", "1122", "3344", "3344")
Vector("000000") ++ (for { r <- v } yield "0" + r + "0") ++ Vector("000000")
However, I am fairly new to Scala and I feel I might be missing a better way to accomplish this. Is there a better way to pad a Vector of Strings in Scala with a given value?
Using jwvh's map approach with the * operator on String:
def repeat(len: Int, c: Char) = c.toString * len
def padLeftRight(s: String, len: Int, c: Char) = {
repeat(len - 1 - s.size, c) + s + c
}
def padSeq[S <: Seq[String]](xs: S, c: Char) = {
val len = xs.map(_.size).max + 2
val padded = repeat(len, c)
padded +: xs.map(padLeftRight(_, len, c)) :+ padded
}
Using padSeq with your example:
val v = Vector("1122", "1122", "3344", "3344")
val result = padSeq(v, '0')
gives:
Vector("000000", "011220", "011220", "033440", "033440", "000000")
I have this function to compute the distance between two n-dimensional points using Pythagoras' theorem.
def computeDistance(neighbour: Point) = math.sqrt(coordinates.zip(neighbour.coordinates).map {
case (c1: Int, c2: Int) => math.pow(c1 - c2, 2)
}.sum)
The Point class (simplified) looks like:
class Point(val coordinates: List[Int])
I'm struggling to refactor the method so it's a little easier to read, can anybody help please?
Here's another way that makes the following three assumptions:
The length of the list is the number of dimensions for the point
Each List is correctly ordered, i.e. List(x, y) or List(x, y, z). We do not know how to handle List(x, z, y)
All lists are of equal length
def computeDistance(other: Point): Double = sqrt(
coordinates.zip(other.coordinates)
.flatMap(i => List(pow(i._2 - i._1, 2)))
.fold(0.0)(_ + _)
)
The obvious disadvantage here is that we don't have any safety around list length. The quick fix for this is to simply have the function return an Option[Double] like so:
def computeDistance(other: Point): Option[Double] = {
if(other.coordinates.length != coordinates.length) {
return None
}
return Some(sqrt(coordinates.zip(other.coordinates)
.flatMap(i => List(pow(i._2 - i._1, 2)))
.fold(0.0)(_ + _)
))
I'd be curious if there is a type safe way to ensure equal list length.
EDIT
It was politely pointed out to me that flatMap(x => List(foo(x))) is equivalent to map(foo) , which I forgot to refactor when I was originally playing w/ this. Slightly cleaner version w/ Map instead of flatMap :
def computeDistance(other: Point): Double = sqrt(
coordinates.zip(other.coordinates)
.map(i => pow(i._2 - i._1, 2))
.fold(0.0)(_ + _)
)
Most of your problem is that you're trying to do math with really long variable names. It's almost always painful. There's a reason why mathematicians use single letters. And assign temporary variables.
Try this:
class Point(val coordinates: List[Int]) { def c = coordinates }
import math._
def d(p: Point) = {
val delta = for ((a,b) <- (c zip p.c)) yield pow(a-b, dims)
sqrt(delta.sum)
}
Consider type aliases and case classes, like this,
type Coord = List[Int]
case class Point(val c: Coord) {
def distTo(p: Point) = {
val z = (c zip p.c).par
val pw = z.aggregate(0.0) ( (a,v) => a + math.pow( v._1-v._2, 2 ), _ + _ )
math.sqrt(pw)
}
}
so that for any two points, for instance,
val p = Point( (1 to 5).toList )
val q = Point( (2 to 6).toList )
we have that
p distTo q
res: Double = 2.23606797749979
Note method distTo uses aggregate on a parallelised collection of tuples, and combines the partial results by the last argument (summation). For high dimensional points this may prove more efficient than the sequential counterpart.
For simplicity of use, consider also implicit classes, as suggested in a comment above,
implicit class RichPoint(val c: Coord) extends AnyVal {
def distTo(d: Coord) = Point(c) distTo Point(d)
}
Hence
List(1,2,3,4,5) distTo List(2,3,4,5,6)
res: Double = 2.23606797749979
So this might not be the best way to tackle it but my initial thought was a for expression.
Say I have a List like
List(List('a','b','c'),List('d','e','f'),List('h','i','j'))
I would like to find the row and column for a character, say 'e'.
def findChar(letter: Char, list: List[List[Char]]): (Int, Int) =
for {
r <- (0 until list.length)
c <- (0 until list(r).length)
if list(r)(c) == letter
} yield (r, c)
If there is a more elegant way I'm all ears but I would also like to understand what's wrong with this. Specifically the error the compiler gives me here is
type mismatch; found : scala.collection.immutable.IndexedSeq[(Int, Int)] required: (Int, Int)
on the line assigning to r. It seems to be complaining that my iterator doesn't match the return type but I don't quite understand why this is or what to do about it ...
In the signature of findChar you are telling the compiler that it returns (Int, Int). However, the result of your for expression (as inferred by Scala) is IndexedSeq[(Int, Int)] as the error message indicates. The reason is that (r, c) after yield is produced for every "iteration" in the for expression (i.e., you are generating a sequence of results, not just a single result).
EDIT: As for findChar, you could do:
def findChar(letter: Char, list: List[List[Char]]) = {
val r = list.indexWhere(_ contains letter)
val c = list(r).indexOf(letter)
(r, c)
}
It is not the most efficient solution, but relatively short.
EDIT: Or reuse your original idea:
def findAll(letter: Char, list: List[List[Char]]) =
for {
r <- 0 until list.length
c <- 0 until list(r).length
if list(r)(c) == letter
} yield (r, c)
def findChar(c: Char, xs: List[List[Char]]) = findAll(c, xs).head
In both cases, be aware that an exception occurs if the searched letter is not contained in the input list.
EDIT: Or you write a recursive function yourself, like:
def findPos[A](c: A, list: List[List[A]]) = {
def aux(i: Int, xss: List[List[A]]) : Option[(Int, Int)] = xss match {
case Nil => None
case xs :: xss =>
val j = xs indexOf c
if (j < 0) aux(i + 1, xss)
else Some((i, j))
}
aux(0, list)
}
where aux is a (locally defined) auxiliary function that does the actual recursion (and remembers in which sublist we are, the index i). In this implementation a result of None indicates that the searched element was not there, whereas a successful result might return something like Some((1, 1)).
For your other ear, the question duplicates
How to capture inner matched value in indexWhere vector expression?
scala> List(List('a','b','c'),List('d','e','f'),List('h','i','j'))
res0: List[List[Char]] = List(List(a, b, c), List(d, e, f), List(h, i, j))
scala> .map(_ indexOf 'e').zipWithIndex.find(_._1 > -1)
res1: Option[(Int, Int)] = Some((1,1))