Related
In Scala, define the function slice(from, until, xs) that selects an interval of elements from the (string) list xs such that for each element x in the interval the following invariant holds: from <= indexOf(x) < until.
from: the lowest index to include from this list.
until: the highest index to exclude from this list.
returns: a list containing the elements greater than or equal to index from extending up to (but not including) index until of this list.
example:
def test {
expect (Cons("b", Cons("c", Nil()))) {
slice(1, 3, Cons("a", Cons("b", Cons("c", Cons("d", Cons("e", Nil()))))))
}
}
another example:
def test {
expect (Cons("d", Cons("e", Nil()))) {
slice(3, 7, Cons("a", Cons("b", Cons("c", Cons("d", Cons("e", Nil()))))))
}
}
and this is what I have, but its not that correct. Can someone help me with it?
abstract class StringList
case class Nil() extends StringList
case class Cons(h: String, t: StringList) extends StringList
object Solution {
// define function slice
def slice(from : Int, until : Int, xs : StringList) : StringList = (from, until, xs) match {
case (_,_,Nil()) => Nil()
case (n, m, _) if(n == m) => Nil()
case (n, m, _) if(n > m) => Nil()
case (n, m, _) if(n < 0) => Nil()
case (n, m, xs) if(n == 0)=> Cons(head(xs), slice(n+1,m,tail(xs)))
case (n, m, xs) => {
//Cons(head(xs), slice(n+1,m,tail(xs)))
if(n == from) {
print("\n")
print("n == m " + Cons(head(xs), slice(n+1,m,tail(xs))))
print("\n")
Cons(head(xs), slice(n+1,m,tail(xs)))
}
else slice(n+1,m,tail(xs))
}
}
def head(t : StringList) : String = t match {
case Nil() => throw new NoSuchElementException
case Cons(h, t) => h
}
def tail(t : StringList) : StringList = t match {
case Nil() => Nil()
case Cons(h, t) => t
}
/* def drop(n : Int, t : StringList) : StringList = (n, t) match {
case (0, t) => t
case (_, Nil()) => Nil()
case (n, t) => drop(n-1 , tail(t))
}*/
}//
This works add a method to find the element at given index :
trait StringList
case class Nil() extends StringList
case class Cons(h: String, t: StringList) extends StringList
object Solution {
def numberOfElements(str: StringList, count: Int = 0): Int = {
if (str == Nil()) count else numberOfElements(tail(str), count + 1)
}
def elemAtIndex(n: Int, str: StringList, count: Int = 0): String = {
if (str == Nil() || n == count) head(str) else elemAtIndex(n, tail(str), count + 1)
}
def head(str: StringList): String = str match {
case Nil() => throw new NoSuchElementException
case Cons(h, t) => h
}
def tail(str: StringList): StringList = str match {
case Nil() => Nil()
case Cons(h, t) => t
}
// define function slice
def slice(from: Int, until: Int, xs: StringList): StringList = (from, until, xs) match {
case (n, m: Int, _) if n == m || n > m || n < 0 => Nil()
case (n, m: Int, xs: StringList) =>
if (m > numberOfElements(xs)) {
slice(n, numberOfElements(xs), xs)
} else {
Cons(elemAtIndex(n, xs), slice(n + 1, m, xs))
}
}
}
scala> Solution.slice(1, 3, Cons("a", Cons("b", Cons("c", Cons("d", Cons("e", Nil()))))))
res0: StringList = Cons(b,Cons(c,Nil()))
scala> Solution.slice(3, 7, Cons("a", Cons("b", Cons("c", Cons("d", Cons("e", Nil()))))))
res0: StringList = Cons(d,Cons(e,Nil()))
Newbie to scala.
I am trying to make this code to work for a few hours now . It is intended to update the List[Int](list of integers) with absolute values of the integers.
Took a long time to figure out that List is immutable, so found that ListBuffer can be the saviour, but eventually in returning it back into the List form is seeing some issue i guess.
def f (arr:List[Int]) : List[Int] =
{
val list = new scala.collection.mutable.ListBuffer[Int]();
val len = arr.length;
for ( i <- 0 to len)
{
if(arr(i) < 0)
{
list.append((-1)*arr(i)) ;
}
else
{
list.append(arr(i));
}
}
return list.toList;
}
which is giving this error:
java.lang.IndexOutOfBoundsException: 12
at scala.collection.LinearSeqOptimized$class.apply(LinearSeqOptimized.scala:52)
at scala.collection.immutable.List.apply(List.scala:84)
at Solution$.f(Solution.scala:7)
at Solution$delayedInit$body.apply(Solution.scala:23)
at scala.Function0$class.apply$mcV$sp(Function0.scala:40)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:71)
at scala.App$$anonfun$main$1.apply(App.scala:7...
Not getting what's wrong here.
The best way is to use Scala functions like #senia suggested in comments. For example:
val res = list map math.abs
But if you want to fix your code just replace to with until. You are getting off by one error:
def f (arr:List[Int]) : List[Int] =
{
val list = new scala.collection.mutable.ListBuffer[Int]();
val len = arr.length;
for ( i <- 0 until len)
{
if(arr(i) < 0)
{
list.append((-1)*arr(i)) ;
}
else
{
list.append(arr(i));
}
}
return list.toList;
}
Here is the difference between until and to:
1 to 3
// Range(1, 2, 3)
1 until 3
// Range(1, 2)
You can also remove return, ; and even braces { used with if/else.
Yet another version using a for comprehension that avoids indexing,
def f (arr:List[Int]) : List[Int] =
{
val list = new scala.collection.mutable.ListBuffer[Int]();
for {
a <- arr
sign = if (a < 0) -1 else 1
} list.append(sign * a)
return list.toList;
}
As mentioned above, the return may be omitted.
You can try using case statements for more neat syntax :
def f(arr:List[Int]):List[Int] = {
val list = scala.collection.mutable.ListBuffer[Int]()
arr.foreach{
x =>
x match {
case _ if (x <0) => list+= (x*(-1))
case _ => list +=x
}
}
list.toList
}
Looks like you were trying to solve the challenge from here. Probably you may want to use more functional approach with recursion and immutable List.
def f(arr: List[Int]): List[Int] = arr match {
case Nil => Nil
case x :: rest => java.lang.Math.abs(x) :: f(rest)
}
Beginner friendly: this is how I wrote it
def f(arr: List[Int]) : List[Int] = {
var list = new scala.collection.mutable.ArrayBuffer[Int]();
// var len = arr.length;
for(i <-0 until arr.length) {
list.append( math.abs(arr(i)));
}
return list.toList; }
I haven't done any time complexity analysis but it's the most straightforward for beginners to understand. Also, it passes all the tests on hackerrank
def f (arr: List[Int]) : List[Int] = {
arr.map {
case i if 0 > i => i * -1
case i => i
}
}
I am trying to define a function, that would take a list and split it down n without using take, drop or grouped
def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
if (n <= 0) (Nil, xs)
else
if (n >= xs.size) (xs, Nil)
else
if (n < xs.tail.size) (xs.head :: mySplit(n, xs.tail), Nil)
else (Nil, xs.head :: mySplit(n, xs.tail))
}
Here is what I am thinking. If n < xs.tail.size we can build up tuple 1 (representing part 1), else we can work on tuple 2 (second part of the list).
The above does not work. It seems that it does not like the :: when I am constructing part of a tuple.
Am I approaching this the right way?
Example: mySplit(3, (1 to 5).toList) should return (List(1,2,3), List(4,5))
Here is my take, rewritten from scratch:
def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
xs match {
case Nil => (Nil, Nil)
case head :: tail =>
if(n == 0)
(Nil, xs)
else
mySplit(n - 1, tail) match {
case (before, after) =>
(head :: before, after)
}
}
}
Or alternatively and shorter:
def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
n match {
case 0 => (Nil, xs)
case s =>
mySplit(s - 1, xs.tail) match {
case (before, after) =>
(xs.head :: before, after)
}
}
}
If you still want to split large lists, here is a tail recursive variant. Its also faster:
import scala.annotation.tailrec
def mySplit[X](n: Int, xs: List[X]): (List[X], List[X]) = {
require(n >= 0)
if (n > 0) {
var result: (List[X], List[X]) = null
#tailrec
def mySplit0(n: Int, l: List[X], r: List[X]): Unit = r match {
case h :: t if (n > 0) => mySplit0(n - 1, h :: l, t)
case _ => result = (l.reverse, r)
}
mySplit0(n, Nil, xs)
result
} else (Nil, xs)
}
I would like to know how I can split a string using more than one delimiter with Scala.
For instance if I have a list of delimiters :
List("Car", "Red", "Boo", "Foo")
And a string to harvest :
Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed
I would like to be able to output something like :
List( ("Car", " foerjfpoekrfopekf "),
("Red", " ezokdpzkdpoedkzopke dekpzodk "),
("Foo", " azdkpodkzed")
)
You can use the list to create a regular expression and use its split method:
val regex = List("Car", "Red", "Boo", "Foo").mkString("|").r
regex.split("Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed")
That however doesn't tell you which delimiter was used where. If you need that, I suggest you try Scala's parser library.
EDIT:
Or you can use regular expressions to extract one pair at a time like this:
def split(s:String, l:List[String]):List[(String,String)] = {
val delimRegex = l.mkString("|")
val r = "("+delimRegex+")(.*?)(("+delimRegex+").*)?"
val R = r.r
s match {
case R(delim, text, rest, _) => (delim, text) :: split(rest, l)
case _ => Nil
}
}
a bit verbose, but it works:
DEPRECATED VERSION: (it has a bug, left it here because you already accepted the answer)
def f(s: String, l: List[String], g: (String, List[String]) => Int) = {
for {
t <- l
if (s.contains(t))
w = s.drop(s.indexOf(t) + t.length)
} yield (t, w.dropRight(w.length - g(w, l)))
}
def h(s: String, x: String) = if (s.contains(x)) s.indexOf(x) else s.length
def g(s: String, l: List[String]): Int = l match {
case Nil => s.length
case x :: xs => math.min(h(s, x), g(s, xs))
}
val l = List("Car", "Red", "Boo", "Foo")
val s = "Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed"
output:
f(s, l, g).foreach(println)
> (Car, foerjfpoekrfopekf )
> (Red, ezokdpzkdpoedkzopke dekpzodk )
> (Foo, azdkpodkzed)
it returns Array[String] instead of list. but you can just as well do: f(s, l, g).toList
EDIT:
just noticed this code is good if the delimiters only appear once in the string. if had defined s as follows:
val s = "Car foerjfpoekrfopekf Red ezokdpzkdpoedkzopke dekpzodk Foo azdkpodkzed Car more..."
I'd still get the same result, instead of another pair ("Car"," more...")
EDIT#2: BUGLESS VERSION here's the fixed snippet:
def h(s: String, x: String) = if (s.contains(x)) s.indexOf(x) else s.length
def multiSplit(str: String, delimiters: List[String]): List[(String, String)] = {
val del = nextDelimiter(str, delimiters)
del._1 match {
case None => Nil
case Some(x) => {
val tmp = str.drop(x.length)
val current = tmp.dropRight(tmp.length - nextDelIndex(tmp,delimiters))
(x, current) :: multiSplit(str.drop(x.length + current.length), delimiters)
}
}
}
def nextDelIndex(s: String, l: List[String]): Int = l match {
case Nil => s.length
case x :: xs => math.min(h(s, x), nextDelIndex(s, xs))
}
def nextDelimiter(str: String, delimiters: List[String]): (Option[String], Int) = delimiters match {
case Nil => (None, -1)
case x :: xs => {
val next = nextDelimiter(str, xs)
if (str.contains(x)) {
val i = str.indexOf(x)
next._1 match {
case None => (Some(x), i)
case _ => if (next._2 < i) next else (Some(x), i)
}
} else next
}
}
output:
multiSplit(s, l).foreach(println)
> (Car, foerjfpoekrfopekf )
> (Red, ezokdpzkdpoedkzopke dekpzodk )
> (Foo, azdkpodkzed)
> (Car, more...)
and now it works :)
I search the best and the most elegant way to make GA crossover operator in Scala functional (No "for" loop, with only immutable type if possible), for example, with this list:
val A = IndexedSeq (5,4,8)
val B = IndexedSeq (3,2,6)
I want to make random bitcoin permutation (with rng.nextBoolean for example) between each element in my IndexedSeq, and finally I get the two lists A' and B' after permutation of their elements.
Example of execution:
rng.nextBoolean <- (true,false,true)
A' = 3,4,6
B' = 5,2,8
Thanks.
def crossover[T](a: Seq[T], b: Seq[T], rs: Seq[Boolean]) =
(a, b, rs).zipped.map((x, y, z) => if (z) Seq(x, y) else Seq(y, x)).transpose
Use with Booleans as third argument:
scala> val Seq(a1, b1) = crossover(A, B, List(true, false, true))
a1: Seq[Int] = Vector(5, 2, 8)
b1: Seq[Int] = Vector(3, 4, 6)
If you want it with a default sequence of Booleans, you could provide a default argument like this:
def crossover[T](a: Seq[T], b: Seq[T], rs: Seq[Boolean] = {
val rng = new util.Random
Stream.continually(rng.nextBoolean) }) =
(a, b, rs).zipped.map((x, y, z) => if (z) Seq(x, y) else Seq(y, x)).transpose
Wow, where's all this code coming from? Here:
val (a1, b1) = A zip B map (t => if (util.Random.nextBoolean) t.swap else t) unzip
There, that's all.
If you already have a list of random booleans, you can do this:
val (a1, b1) = A zip B zip C map { case (t, flag) => if (flag) t.swap else t } unzip
import scala.util.Random
val A = IndexedSeq(5,4,8)
val B = IndexedSeq(3,2,6)
def crossover[T](rng: Random)(a: Seq[T], b: Seq[T]): (Seq[T],Seq[T]) = {
if (a.isEmpty && b.isEmpty) return (Nil,Nil)
val (aTailCrossover,bTailCrossover) = crossover(rng)(a.tail,b.tail)
if (rng.nextBoolean) (b.head +: aTailCrossover, a.head +: bTailCrossover)
else (a.head +: aTailCrossover, b.head +: bTailCrossover)
}
println(crossover(new Random)(A,B))
def rndCombi [T] (a: Seq[T], b: Seq[T]): Seq[T] = {
if (a.size != b.size) sys.error ("sizes don't match: a:" + a.size + " != b: " + b.size)
val rnd = util.Random
val max = (math.pow (2, a.size)).toInt
val r = rnd.nextInt (max)
def pick (a: Seq[T], b: Seq[T], r: Int) : List[T] = {
if (a.size == 0) Nil else
if (r % 2 == 0) a.head :: pick (a.tail , b.tail, r/2) else
b.head :: pick (a.tail , b.tail, r/2)
}
// print all combinations for testing:
// (0 until max).map (i => println (pick (a, b, i).mkString ("-")))
pick (a, b, r).toSeq
}
// I choosed different values for easy testing:
val a = IndexedSeq (7, 8, 9)
val b = IndexedSeq (1, 2, 3)
println (rndCombi (a, b).mkString (" "))
println (rndCombi (a, b.tail).mkString (" "))
Initializing util.Random each time is of course not very clever, if done frequently. So for production code you would rearrange the code.
If you don't restrict the input to 2 sequences, it get's more interesting. Here we go:
def rndCombi [T] (s: Seq[Seq[T]]): Seq[T] = {
val outer = s.size
val inner = s(0).size
val rnd = util.Random
val max = (math.pow (outer, inner)).toInt
val r = rnd.nextInt (max)
def pick (s: Seq[Seq[T]], r: Int, pos: Int = 0) : List[T] =
if (pos == inner) Nil
else s(r % inner)(pos) :: pick (s, r/inner, pos + 1)
// print all combinations for testing:
(0 until max).map (i => println (pick (s, i).mkString ("-")))
println ()
pick (s, r).toSeq
}
val a = IndexedSeq (1, 2, 3)
val b = IndexedSeq (4, 5, 6)
val c = IndexedSeq (7, 8, 9)
println (rndCombi (Seq (a, b, c)).mkString (" "))
The second solution can, of course, be used for 2 sequences as well.