Scala List to Map with Next and Previous values - performance

What would be the best way to transform:
val arr: List[String]
To:
val mapArr: List[Tuple[Int, String]]
Where:
each Tuple is:
- String value is the an odd index element of the list
- Int the size of the previous value.
Example:
val stringArr = List("a", "aaa", "bb", "abc")
val resultShouldBe = List((1, "aaa"), (2, "abc"))

You can use IterableLike.grouped for that:
val result = stringArr
.grouped(2)
.collect { case List(toIndex, value) => (toIndex.length, value) }
.toList
Which yields:
scala> val stringArr = List("a", "aaa", "bb", "abc")
stringArr: List[String] = List(a, aaa, bb, abc)
scala> stringArr.grouped(2).collect { case List(toIndex, value) => (toIndex.length, value) }.toList
res1: List[(Int, String)] = List((1,aaa), (2,abc))

Related

FOR COMPREHENSIONS for type Rand

Scala Code:
trait RNG {
}
type Rand[+A] = RNG => (A, RNG)
def map[A,B](s: Rand[A])(f: A => B): Rand[B] = rng => {
val (a, rng2) = s(rng)
(f(a), rng2)
}
def flatMap[A,B](f: Rand[A])(g: A => Rand[B]): Rand[B] = rng => {
val (a, r1) = f(rng)
g(a)(r1)
}
def map2_1[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] = flatMap(ra) (a => map(rb)(b => f(a,b)))
def map2_2[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] = for {
a <- ra
b <- rb } yield f(a,b)
Problem: map2_1 - good. map2_2 - not good: Errors: Cannot resolve symbol flatMap, Cannot resolve symbol map
Help please.
map2_2 is not compiled in Scala 2.13
I expected for-comprehensions to work.

Adjacency-List Paths in Scala

If I have an adjacency list, represented in Scala like this:
val l = List(
List((1, 1), (2, 3), (4, 10)),
List((2, 1)),
List((3, 1), (4, 5)),
List(4, 1)),
List())
Every "List" contains the costs of the path from one node to another in a directed graph. So the first "List" with three entries represents the successors of the first node (counting from 0). That means Node 0 directs to Node 1 with a cost of 1, to Node 2 with a cost of 3 and to Node 4 with a cost of 10 and so on.
How would it be possible to recursively compute if there are paths with a max cost from a given node to another? I thought of something like this:
def hasMaxCostPath: (List[List[(Int, Int)]], Int, Int, Int) => Int => Boolean = (adj, from, to, max) => len =>
So the function receives the adjacency list "adj", the start node "from", the end node "to", the max cost of the path "max" and the max length of the path "len".
So I think the result should be like the following based on the above given adjacency list:
hasMaxCostPath(l, 0, 2, 2)(1) == false
hasMaxCostPath(l, 0, 2, 3)(1) == true
Furthermore how would it be possible to recursively compute a list of all costs of paths that go from one specified node to another within a given max length? Maybe like this:
def getPaths: (List[List[(Int, Int)]], List[(Int, Int)], Int, Int) => List[Int] =
(adj, vn, dest, len) =>
So this function would get the adjacency list "adj", a list of already visited nodes "vn" with (node, cost), in which we take the given node as the start node, the destination node "dest" and the max length of the path "len". And for this function the results could be like the following:
getPaths(l, List((0, 0)), 2, 1) == List(3) // Node0 -> Node2
getPaths(l, List((0, 0)), 2, 2) == List(2, 3) // Node0 -> Node1 -> Node2 AND Node0 -> Node2
Sorry, I'm very new to Scala
Does this work for you?
package foo
object Foo {
def main(args: Array[String]): Unit = {
val edges = List(
List((1, 1), (2, 3), (4, 10)),
List((2, 1)),
List((3, 1), (4, 5)),
List((4, 1)),
List())
println(hasMaxCostPath(edges,0,1,2))
println(hasMaxCostPath(edges,0,2,2))
}
def hasMaxCostPath(edges: List[List[(Int, Int)]], start: Int, end: Int, maxCost: Int): Boolean = {
maxCost > 0 &&
edges(start).exists(a =>
(a._1 == end && a._2 <= maxCost) ||
hasMaxCostPath(edges, a._1, end, maxCost - a._2)
)
}
}
Edit: ====
The above solution did not take into account the length parameter.
Here is a solution with the length parameter:
package foo
object Foo {
def main(args: Array[String]): Unit = {
val edges = List(
List((1, 1), (2, 3), (4, 10)),
List((2, 1)),
List((3, 1), (4, 5)),
List((4, 1)),
List())
assert(! hasMaxCostPath(edges,0,4,4,3))
assert(hasMaxCostPath(edges,0,4,4,4))
}
def hasMaxCostPath(edges: List[List[(Int, Int)]], start: Int, end: Int, maxCost: Int, maxLength: Int): Boolean = {
maxLength > 0 &&
maxCost >= 0 &&
edges(start).exists(a =>
(a._1 == end && a._2 <= maxCost) ||
hasMaxCostPath(edges, a._1, end, maxCost - a._2, maxLength - 1)
)
}
}
=== Edit:
And here is a solution including your second problem:
package foo
object Foo {
def main(args: Array[String]): Unit = {
val edges = List(
List((1, 1), (2, 3), (4, 10)),
List((2, 1)),
List((3, 1), (4, 5)),
List((4, 1)),
List())
assert(! hasMaxCostPath(edges,0,4,4,3))
assert(hasMaxCostPath(edges,0,4,4,4))
assert(getMaxCostPaths(edges,0,0,5,5) == List())
assert(getMaxCostPaths(edges,0,1,1,1) == List(List(0,1)))
assert(getMaxCostPaths(edges,0,2,2,2) == List(List(0,1,2)))
assert(getMaxCostPaths(edges,0,2,5,5) == List(List(0,2), List(0,1,2)))
}
def hasMaxCostPath(edges: List[List[(Int, Int)]], start: Int, end: Int, maxCost: Int, maxLength: Int): Boolean = {
maxLength > 0 &&
maxCost >= 0 &&
edges(start).exists(a =>
(a._1 == end && a._2 <= maxCost) ||
hasMaxCostPath(edges, a._1, end, maxCost - a._2, maxLength - 1)
)
}
def getMaxCostPaths(
edges: List[List[(Int, Int)]],
from: Int, to: Int,
maxCost: Int,
maxLength: Int): List[List[Int]] = {
getMaxCostPathsRec(edges, from, to, maxCost, maxLength, List(from))
}
def getMaxCostPathsRec(
edges: List[List[(Int, Int)]],
start: Int, end: Int,
maxCost: Int,
maxLength: Int,
path: List[Int]) : List[List[Int]] = {
if (maxLength <= 0 || maxCost < 0) return List()
val direct = edges(start).filter(a => a._1 == end && a._2 <= maxCost).map(edge => path ::: List(edge._1))
val transitive = edges(start).flatMap(a =>
getMaxCostPathsRec(edges, a._1, end, maxCost - a._2, maxLength - 1, path ::: List(a._1))
)
direct ::: transitive
}
}

how to calculate the inversion count using merge sort for a list of Int in Scala?

def mergeSort(xs: List[Int]): List[Int] = {
val n = xs.length / 2
if (n == 0) xs
else {
def merge(xs: List[Int], ys: List[Int]): List[Int] =
(xs, ys) match {
case(Nil, ys) => ys
case(xs, Nil) => xs
case(x :: xs1, y :: ys1) =>
if (x < y) {
x :: merge(xs1, ys)
}
else {
y :: merge(xs, ys1)
}
}
val (left, right) = xs splitAt(n)
merge(mergeSort(left), mergeSort(right))
}
}
Inversion Count for an array indicates – how far (or close) the array is from being sorted. If array is already sorted then inversion count is 0. If array is sorted in reverse order that inversion count is the maximum.
Formally speaking, two elements a[i] and a[j] form an inversion if a[i] > a[j] and i < j
Example:
The sequence 2, 4, 1, 3, 5 has three inversions (2, 1), (4, 1), (4, 3).
So if this list(2, 4, 1, 3, 5)is passed to the function, the inversion count should be 3.
How do I add a variable to get the number?
May be something like will help
def mergeSort(xs: List[Int], cnt: Int): (List[Int], Int) = {
val n = xs.length / 2
if (n == 0) (xs, cnt)
else {
def merge(xs: List[Int], ys: List[Int], cnt: Int): (List[Int], Int) =
(xs, ys) match {
case(Nil, ys) => (ys, cnt)
case(xs, Nil) => (xs, cnt)
case(x :: xs1, y :: ys1) =>
if (x <= y) {
val t = merge(xs1, ys, cnt)
(x :: t._1, t._2)
}
else {
val t = merge(xs, ys1, cnt + xs.size)
(y :: t._1, t._2)
}
}
val (left, right) = xs splitAt(n)
val leftMergeSort = mergeSort(left, cnt)
val rightMergeSort = mergeSort(right, cnt)
merge(leftMergeSort._1, rightMergeSort._1, leftMergeSort._2 + rightMergeSort._2)
}
}
I am passing a tuple along all the function calls that's it.
I increment the value of the cnt when we find that first element of one list is less than the first element of second list. In this scenario we add list.length to the cnt. Look at the code, to get a more clear view.
Hope this helps!

Break out of loop in scala while iterating on list

I am trying to solve a problem.
Problem :
You are given a sequence of N balls in 4 colors: red, green, yellow and blue. The sequence is full of colors if and only if all of the following conditions are true:
There are as many red balls as green balls.
There are as many yellow balls as blue balls.
Difference between the number of red balls and green balls in every prefix of the sequence is at most 1.
Difference between the number of yellow balls and blue balls in every prefix of the sequence is at most 1.
Your task is to write a program, which for a given sequence prints True if it is full of colors, otherwise it prints False.
My solution : for each string, i am generating all possible prefixes and suffixes to validate the condition number 3 and 4. But it is taking more time.
instead of generating prefix and validating conditions every time, we can iterate over the string and validate the condition. I want to break out of loop when condition is not met. I am not able to get that in functional style. Can someone help me how to achieve it.
My solution :
object Test {
def main(args: Array[String]) {
def isValidSequence(str: String) = {
def isValidCondition(ch1:Char, ch2:Char, m:Map[Char, Int]):Boolean = m.getOrElse(ch1, 0) - m.getOrElse(ch2, 0) > 1
def groupByChars(s:String) = s.groupBy(ch => ch).map(x => (x._1, x._2.length))
def isValidPrefix(s:String):Boolean = (1 to s.length).exists(x => isValidCondition('R', 'G', groupByChars(s.take(x))))
val x = groupByChars(str)
lazy val cond1 = x.get('R') == x.get('G')
lazy val cond2 = x.get('B') == x.get('Y')
lazy val cond3 = isValidPrefix(str)
lazy val cond4 = isValidPrefix(str.reverse)
cond1 && cond2 && !cond3 && !cond4
}
def printBoolValue(b:Boolean) = if(b) println("True") else println("False")
val in = io.Source.stdin.getLines()
val inSize = in.take(1).next().toInt
val strs = in.take(inSize)
strs.map(isValidSequence(_)).foreach(printBoolValue)
}
}
As another answer, here's a more straightforward solution, that does short-circuit the differences check.
val valid = List("RGYBRGYB")
val invalid = List("RGYBR", "RGYBY", "RGYBY", "RGYYB")
def checkBalls(s:String) = {
def differences(s:String, a:Char, b:Char) = {
def differenceHelp(s:String, a:Char, b:Char, current:Int):Boolean = {
if (current < -1 || current > 1) false
else if (s.length == 0) true
else differenceHelp(s.tail, a, b,
if (s.head == a) current + 1 else if (s.head == b) current - 1 else current)
}
differenceHelp(s, a, b, 0)
}
lazy val cond1 = s.count('R'==) == s.count('G'==)
lazy val cond2 = s.count('Y'==) == s.count('B'==)
lazy val cond3 = differences(s, 'R', 'G')
lazy val cond4 = differences(s, 'Y', 'B')
cond1 && cond2 && cond3 && cond4
}
valid.forall(checkBalls(_)) //> res0: Boolean = true
invalid.forall(!checkBalls(_)) //> res1: Boolean = true
EDIT: as an optimisation, we can do cond1 as part of cond3 (and cond2 as part of cond4). There are equal numbers of each if and only if the count is 0 at the end of the string. We can check that in differences and return true only if that's the case. So that gives
def checkBalls(s:String) = {
def differences(s:String, a:Char, b:Char) = {
def differenceHelp(s:String, a:Char, b:Char, current:Int):Boolean = {
if (current < -1 || current > 1) false
else if (s.length == 0) (count == 0) // <- this line changed
else differenceHelp(s.tail, a, b,
if (s.head == a) current + 1 else if (s.head == b) current - 1 else current)
}
differenceHelp(s, a, b, 0)
}
lazy val cond3 = differences(s, 'R', 'G')
lazy val cond4 = differences(s, 'Y', 'B')
cond3 && cond4
}
which passes the tests just like the previous version. It could be made slightly faster by doing the R/G and Y/B checks in one call to differences, but that's looking a bit overspecialised.
Here is a solution using streams if you need.
code :-
object RGYB extends App {
val validPattern = List(
"RG","RYBG","RYGB","RBGY",
"GR","GYBR","GYRB","GBRY",
"YB","YRGB","YRBG","YGRB",
"BY","BRGY","BRYG","BGYR"
)
val pattern ="RGRG"
pattern.sliding(4).foreach { x1 =>
val count = validPattern.filter { p1 => {
x1.equalsIgnoreCase(p1)
}
}.size
if(count<1)
{
x1.sliding(2).foreach {
x2=>
val counter = validPattern.filter { p2 => {
x2.equalsIgnoreCase(p2)
}
}.size
if(counter<1)
{
println("false !! not valid due to "+x2);
System.exit(0)
}
}
println("false !! not valid due to "+x1);
System.exit(0)
}
}
println("True !!"+pattern+" Is a valid string pattern")
}
So, the trick is to check the longest prefix first. If that fails, we're done. Otherwise, we take the next longest prefix and recurse. If we get to the empty string, it passed for all prefixes, and therefore it's valid.
def isValidPrefix(s: String): Boolean =
if (s.length == 0)
true
else if (!isValidCondition('R', 'G', groupByChars(s)))
false
else isValidPrefix(s.init)

Linq intersect with sum

I have two collections that I want to intersect, and perform a sum operation on matching elements.
For example the collections are (in pseudo code):
col1 = { {"A", 5}, {"B", 3}, {"C", 2} }
col2 = { {"B", 1}, {"C", 8}, {"D", 6} }
and the desired result is:
intersection = { {"B", 4}, {"C", 10} }
I know how to use an IEqualityComparer to match the elements on their name, but how to sum the values while doing the intersection?
EDIT:
The starting collections haven't two items with the same name.
Let's say your input data looks like this:
IEnumerable<Tuple<string, int>> firstSequence = ..., secondSequence = ...;
If the strings are unique in each sequence (i.e there can be no more than a single {"A", XXX} in either sequence) you can join like this:
var query = from tuple1 in firstSequence
join tuple2 in secondSequence on tuple1.Item1 equals tuple2.Item1
select Tuple.Create(tuple1.Item1, tuple1.Item2 + tuple2.Item2);
You might also want to consider using a group by, which would be more appropriate if this uniqueness doesn't hold:
var query = from tuple in firstSequence.Concat(secondSequence)
group tuple.Item2 by tuple.Item1 into g
select Tuple.Create(g.Key, g.Sum());
If neither is what you want, please clarify your requirements more precisely.
EDIT: After your clarification that these are dictionaries - your existing solution is perfectly fine. Here's another alternative with join:
var joined = from kvp1 in dict1
join kvp2 in dict2 on kvp1.Key equals kvp2.Key
select new { kvp1.Key, Value = kvp1.Value + kvp2.Value };
var result = joined.ToDictionary(t => t.Key, t => t.Value);
or in fluent syntax:
var result = dict1.Join(dict2,
kvp => kvp.Key,
kvp => kvp.Key,
(kvp1, kvp2) => new { kvp1.Key, Value = kvp1.Value + kvp2.Value })
.ToDictionary(a => a.Key, a => a.Value);
This will give the result, but there are some caveats. It does an union of the two collections and then it groups them by letter. So if, for example, col1 contained two A elements, it would sum them together and, because now they are 2 A, it would return them.
var col1 = new[] { new { L = "A", N = 5 }, new { L = "B", N = 3 }, new { L = "C", N = 2 } };
var col2 = new[] { new { L = "B", N = 1 }, new { L = "C", N = 8 }, new { L = "D", N = 6 } };
var res = col1.Concat(col2)
.GroupBy(p => p.L)
.Where(p => p.Count() > 1)
.Select(p => new { L = p.Key, N = p.Sum(q => q.N) })
.ToArray();
The best I came up with until now is (my collections are actually Dictionary<string, int> instances):
var intersectingKeys = col1.Keys.Intersect(col2.Keys);
var intersection = intersectingKeys
.ToDictionary(key => key, key => col1[key] + col2[key]);
I'm not sure if it will perform well, at least is it readable.
If your intersection algorithm will result in anonymous type, i.e. ...Select(new { Key = key, Value = value}) then you can easily sum it
result.Sum(e => e.Value);
If you want to sum the "while" doing the intersection, add the value to the accumulator value when adding to the result set.

Resources