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.
Related
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!
Update list with negative elements.
For example init:
List(1,-2,-3)
final:
List(1,2,3)
Scala solution:
def fpUpdateList(el: List[Int]): List[Int] = el.map(e => if (e < 0) e - e * 2; else e)
Not sure if this is a question or what, but here's a more concise way:
def fpUpdateList(el: List[Int]) = el.map(Math.abs)
I need to count the number of inversions using Merge Sort:
object Example {
def msort(xs: List[Int]): List[Int] = {
def merge(left: List[Int], right: List[Int]): Stream[Int] = (left, right) match {
case (x :: xs, y :: ys) if x < y => Stream.cons(x, merge(xs, right))
case (x :: xs, y :: ys) => Stream.cons(y, merge(left, ys))
case _ => if (left.isEmpty) right.toStream else left.toStream
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(ys), msort(zs)).toList
}
}
msort(List(8, 15, 3))
}
I guess I have to count it in the line (where y < y, the second line in match)
case (x :: xs, y :: ys) => Stream.cons(y, merge(left, ys))
However, when I tried I failed.
How do I do that?
UPDATE:
a version with an accumulator:
def msort(xs: List[Int]): List[Int] = {
def merge(left: List[Int], right: List[Int], inversionAcc: Int = 0): Stream[Int] = (left, right) match {
case (x :: xs, y :: ys) if x < y => Stream.cons(x, merge(xs, right, inversionAcc))
case (x :: xs, y :: ys) => Stream.cons(y, merge(left, ys, inversionAcc + 1))
case _ => if (left.isEmpty) right.toStream else left.toStream
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(ys), msort(zs)).toList
}
}
How do I easily return inversionAcc? I guess, I can return it a part of tuple only like this:
def merge(left: List[Int], right: List[Int], invariantAcc: Int = 0): (Stream[Int], Int)
It doesn't look good, though.
UPDATE2:
and it actually doesn't count properly, I can't find where the error is.
This is the Scala port of my Frege solution.
object CountInversions {
def inversionCount(xs: List[Int], size: Int): (Int, List[Int]) =
xs match {
case _::_::_ => { //If the list has more than one element
val mid = size / 2
val lsize = mid
val rsize = size - mid
val (left, right) = xs.splitAt(mid)
val (lcount, lsorted) = inversionCount(left, lsize)
val (rcount, rsorted) = inversionCount(right, rsize)
val (mergecount, sorted) = inversionMergeCount(lsorted, lsize, rsorted,
rsize, 0, Nil)
val count = lcount + rcount + mergecount
(count, sorted)
}
case xs => (0, xs)
}
def inversionMergeCount(xs: List[Int], m: Int, ys: List[Int], n: Int,
acc: Int, sorted: List[Int]): (Int, List[Int]) =
(xs, ys) match {
case (xs, Nil) => (acc, sorted.reverse ++ xs)
case (Nil, ys) => (acc, sorted.reverse ++ ys)
case (x :: restx, y :: resty) =>
if (x < y) inversionMergeCount(restx, m - 1, ys, n, acc, x :: sorted)
else if (x > y) inversionMergeCount(xs, m, resty, n - 1, acc + m, y :: sorted)
else inversionMergeCount(restx, m - 1, resty, n - 1, acc, x :: y :: sorted)
}
}
If the solution doesn't have to be strictly functional then you can just add a simplistic counter:
object Example {
var inversions = 0
def msort(xs: List[Int]): List[Int] = {
def merge(left: List[Int], right: List[Int]): Stream[Int] = (left, right) match {
case (x :: xs, y :: ys) if x < y => Stream.cons(x, merge(xs, right))
case (x :: xs, y :: ys) =>
inversions = inversions + 1
Stream.cons(y, merge(left, ys))
case _ => if (left.isEmpty) right.toStream else left.toStream
}
val n = xs.length / 2
if (n == 0) xs
else {
val (ys, zs) = xs splitAt n
merge(msort(ys), msort(zs)).toList
}
}
}
Example.msort(List(8, 15, 3))
println(Example.inversions)
If it has to remain functional then you'll need to create an accumulator and thread it through all of the method calls and return a Pair from each function where the accumulator value is included in the return result, then sum the accumulator values for each merge convergence. (My functional-fu is not very good, I've already tried solving this functionally before trying the simple var approach.)
Just wondering if there's a syntax shortcut for taking two procs and joining them so that output of one is passed to the other, equivalent to:
a = ->(x) { x + 1 }
b = ->(x) { x * 10 }
c = ->(x) { b.( a.( x ) ) }
This would come in handy when working with things like method(:abc).to_proc and :xyz.to_proc
More sugar, not really recommended in production code
class Proc
def *(other)
->(*args) { self[*other[*args]] }
end
end
a = ->(x){x+1}
b = ->(x){x*10}
c = b*a
c.call(1) #=> 20
a = Proc.new { |x| x + 1 }
b = Proc.new { |x| x * 10 }
c = Proc.new { |x| b.call(a.call(x)) }
you could create a union operation like so
class Proc
def union p
proc {p.call(self.call)}
end
end
def bind v
proc { v}
end
then you can use it like this
a = -> (x) { x + 1 }
b = -> (x) { x * 10 }
c = -> (x) {bind(x).union(a).union(b).call}
An updated answer. Proc composition is already available in Ruby 2.6. There are two methods << and >>, differing in the order of the composition. So now you can do
##ruby2.6
a = ->(x) { x + 1 }
b = ->(x) { x * 10 }
c = a >> b
c.call(1) #=> 20
How to write this LINQ expression in another .SelectMany() form ?
var result =
from a in numbersA
where a < 3
from b in numbersB
where b < 5
select new { a, b };
?
var result = numbersA.Where(x => x < 3).Select.. ?
This is a rough translation of what the compiler would do:
var result = numbersA.Where(a => a < 3)
.SelectMany(a => numbersB, (a, b) => new { a, b })
.Where(z => z.b < 5)
.Select(z => new { z.a, z.b });
Now you can write this more efficiently as:
var result = numbersA.Where(a => a < 3)
.SelectMany(a => numbersB.Where(b => b < 5),
(a, b) => new { a, b });
... but that's not what the compiler would do. It's not clear whether your aim is to see what the compiler does, or to just write a query.
Something like
var result = numbersA.Where(a => a < 3).SelectMany(a =>
numbersB.Where(b => b < 5).Select(b => new { a, b }));
Note that it maybe be more efficient to filter numbersB once only:
var filteredB = numbersB.Where(b => b < 5).ToArray();
var result = numbersA.Where(a => a < 3).SelectMany(a =>
filteredB.Select(b => new { a, b }));