Generate a List with values generated by function in Scala - list

I must generate some random numbers and sum them. Something like
result = generateList(range(0, max), generatorFunctionReturningInt()).foreach(sum _)
If generateList generates a List with size = max and values generated by generatorFunctionReturningInt
Or may be something like
result = range(0, max).map(generatorFunctionReturningInt).foreach(sum _)

How about this?
Stream.continually(generatorFunctionReturningInt()).take(max).sum

The companion objects for various collection types have some handy factory methods. Try:
Seq.fill(max)(generate)

Simply
(0 to max).map(_ => (new util.Random).nextInt(max)).sum
where max defines both number of numbers and random range.
foreach method intended to be used with side-effect functions (like println) which returns nothing (Unit).

foreach is not for returning results, use map instead:
val result = Range (0, max).map (generatorFunctionReturningInt).map (sum _)
specifically, sum is already predefined, isn't it?
val result = Range (0, max).map (generatorFunctionReturningInt).sum
working code (we all like working code)
val result = Range (0, 15).map (3 + _).sum
result: Int = 150
For this trivial case it is the same as Range (3, 18).sum.

Related

SML adding indices to a list

Given a generic list, return a list containing the same objects in a tuple with their index in the list.
For example:
f ["a", "b"];
- val it = [(0,"a") , (1,"b")] : (int * string) list
The function should be a one-liner, meaning no pattern matching, recursion, if/else, helper functions and let/local. So far i could only make a list of indices given the input list:
fun f lst = List.take((foldl (fn (x,list) => [(hd(list)-1)]#list) [length(lst)] (lst)),length(lst));
f [#"a",#"b"];
- val it = [0, 1]: int List.list;
I should add the list items to these indices in a tuple but i'm not sure how to do that.
Here is a hint for one way to solve it:
1) Using List.sub, create an anonymous function which sends an index i to the pair consisting of i and the lst element at index i.
2) Map this over the result obtained by calling List.tabulate on length lst and the function which sends x to x.
I was able to get this to work (on one line), but the result is ugly compared to a straightforward pattern-matching approach. Other than as a puzzle, I don't see the motivation for disallowing that which makes SML an elegant language.
It appears that i forgot the #i operator to access the i'th element of a tuple. The answer is the following:
fun f xs = List.take((foldr (fn (x,list) => [(#1(hd(list))-1,x)]#list) [(length(xs),hd(xs))] (xs)),length(xs));
f (explode "Hello");
- val it = [(0, #"H"), (1, #"e"), (2, #"l"), (3, #"l"), (4, #"o")]: (int * char) List.list;

Prolog- Convert a matrix to a list with indices

I have a Matrix like this:
[[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]]
and I need a list that saves the index when a row is not [0,0,0].
So the result in my example should be:
[2,3,4,5,7,8]
I have problems to program recursive in Prolog because i haven`t really figured out how it works.
Would it maybe help to first convert the matrix into a vector? It doesn't matter if its [1,0,0] or [0,1,0]. The only thing that is important is that it's not [0,0,0].
Since you want to describe a list, you could opt to use DCGs. They usually yield quite easily readable code:
matrix_indices(M,I) :-
phrase(indices(M,0),I). % the list I is described by the DCG indices//2
indices([],_) --> % if M is empty
[]. % I is empty too
indices([[0,0,0]|Ls],I0) --> % if the head of M is [0,0,0]
{I1 is I0+1}, % the current index is calculated but is not in I
indices(Ls,I1). % the same holds for the tail
indices([L|Ls],I0) --> % if the head of the list
{dif(L,[0,0,0])}, % differs from [0,0,0]
{I1 is I0+1}, % the current index is calculated
[I1], % and is in the list I
indices(Ls,I1). % the same holds for the tail
Note that the goals enclosed in braces are normal Prolog-goals. If you query this predicate with your given example you get the desired solution:
?- matrix_indices([[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]],I).
I = [2,3,4,5,7,8] ? ;
no
You can also use the predicate in the other direction but you have to ask for a concrete length or prefix a goal length(M,_)to prevent the predicate from looping. For example the query...
?- length(M,_), matrix_indices(M,[2,3,4,5,7,8]).
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? ;
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F,[0,0,0]],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ? ;
M = [[0,0,0],_A,_B,_C,_D,[0,0,0],_E,_F,[0,0,0],[0,0,0]],
dif(_A,[0,0,0]),
dif(_B,[0,0,0]),
dif(_C,[0,0,0]),
dif(_D,[0,0,0]),
dif(_E,[0,0,0]),
dif(_F,[0,0,0]) ?
.
.
.
... yields infinitely many answers as expected.
How I would solve using findall/3 and nth1/3:
?- M = [[0,0,0],[1,0,0],[0,0,1],[1,0,0],[0,1,0],[0,0,0],[0,1,0],[0,1,0],[0,0,0]],
findall(I, (nth1(I,M,E), E\=[0,0,0]), L).
L = [2, 3, 4, 5, 7, 8]

Scala partition into more than two lists

I have a list in Scala that I'm trying to partition into multiple lists based on a predicate that involves multiple elements of the list. For example, if I have
a: List[String] = List("a", "ab", "b", "abc", "c")
I want to get b: List[List[String]] which is a List of List[String] such that the sum of the lengths of the inner List[String] == 3. i.e List(List("a", "b", "c"), List("abc"), List("ab", "a"), ...)
[Edit] Needs to take a reasonable time for lists of length 50 or less.
It is not possible to build an efficient algorithm that is cheaper than O(2^n * O(p)) for any arbitrary predicate, p. This is because every subset must be evaluated. You will never achieve something that works for n == 50.
Build all possible sublists and filter:
def filter[A](list: List[A])(predicate: (List[A] => Boolean)): List[List[A]] = {
(for {i <- 1 to list.length
subList <- list.combinations(i)
if predicate(subList)
} yield subList).toList
}
val a = List("a", "ab", "b", "abc", "c")
val result = filter(a)(_.foldLeft(0)(_ + _.length) == 3)
I think Sergey is on a good track here, but we can optimize his code a little bit. First of all, we can notice that if the sum of string lengths is N then for sure we don't need to check combinations composed of more than N strings, as the shortest string is at least one character long. And, additionally, we can get away without for synctatic sugar and use the sum method instead of a much more generic (and thus, probably, not so quick) foldLeft.
For clarity's sake, let's first define a small helper function which will compute the sum of strings lengths:
def sumOfStr(list: List[String]) = list.map(_.length).sum
And now the main method:
def split(list: List[String], sum: Int) =
(1 to sum).map(list.combinations(_).filter(sumOfStr(_) == sum)).flatten.toList
EDIT: With our powers combined, we give you a still very inefficient, but hey-that's-the-best-we-can-do-in-reasonable-time version:
def sumOfStr(lst: List[String]) = {
var sum = 0
lst.foreach{ sum += _.length }
sum
}
def split(lst: List[String], sum: Int) =
(1 to sum).par
.map(lst.combinations(_).filter(sumOfStr(_) == sum))
.flatten.toList

Scala conditional sum of elements in a filtered tuples list

I'm new to Scala and need a little help about how to combine
filters and sum on a list of tuples.
What I need is the sum of integers of a filtered tuples list which
essentially the answer to the question:
What is the sum of all set weights?
The result should be 20 for the sample list below
The list is pretty simple:
val ln = List( ("durationWeight" , true, 10),
("seasonWeight" , true, 10),
("regionWeight" , false, 5),
("otherWeight" , false, 5)
Filtering the list according to the Boolean flag is a simple:
val filtered = ln.filter { case(name, check, value) => check == true }
which returns me the wanted tuples. Getting the sum of all them seems to work
with a map followed by sum:
val b = filtered.map{case((name, check, value) ) => value}.sum
Which returns me the wanted sum of all set weights.
However, how do I do all that in one step combining filter, map and sum,
ideally in an elegant one liner?
Thanks for your help.
ln.collect{ case (_, true, value) => value }.sum
Another approach for the heck of it:
(0 /: ln)((sum,x) => if (x._2) sum + x._3 else sum)

How to stay true to functional style in Scala for expressions

I've struggled to find a way to stay true to functional style in for expressions when I need to collect multiple parameters of an object into a List.
As an example, say I have a Notification object, which has both a fromId (the user id the notification is from) and an objectOwnerId (the id of the user who created the original object). These can differ in facebook style notifications ("X also commented on Y's post").
I can collect the userIds with a for expression like so
val userIds = for { notification <- notifications } yield notification.fromId
however say I want to collect both the fromIds and the objectOwnerIds into a single list, is there any way to do this in a single for expression without the user of vars?
I've done something like this in the past:
var ids = List()
for {
notification <- notifications
ids = ids ++ List(notification.fromId, notification.objectOwnerId)
}
ids = ids.distinct
but it feels like there must be a better way. The use of a var, and the need to call distinct after I complete the collection are both ugly. I could avoid the distinct with some conditionals, but I'm trying to learn the proper functional methods to do things.
Thanks in advance for any help!
For such cases, there is foldLeft:
(notifications foldLeft Set.empty[Id]) { (set, notification) =>
set ++ Seq(notification.fromId, notification.ownerId)
}
or in short form:
(Set.empty[Id] /: notifications) { (set, notification) =>
set ++ Seq(notification.fromId, notification.ownerId)
}
A set doesn't hold duplicates. After the fold you can convert the set to another collection if you want.
val userIds = for {
notification <- notifications
id <- List(notification.fromId, notification.objectOwnerId)
} yield id
Apply distinct afterwards if required. If the id can only be duplicated on a single notification, you can apply distinct on the second generator instead.
Sure, instead of just yielding the fromId, yield a tuple
val idPairs:List[(String, String)] = for(notification <- notifications) yield(notification.fromId, notification.objectOwnerId)
Well, here is my answer to the following:
How to map from [Y(x1, x2), Y(x3, x4)] to [x1,x2,x3,x4]?
Use flatMap (see Collection.Traversable, but note it's actually first defined higher up).
case class Y(a: Int, b: Int)
var in = List(Y(1,2), Y(3,4))
var out = in.flatMap(x => List(x.a, x.b))
> defined class Y
> in: List[Y] = List(Y(1,2), Y(3,4))
> out: List[Int] = List(1, 2, 3, 4)
Also, since for..yield is filter, map and flatMap in one (but also see "sugar for flatMap?" that points out that this isn't as efficient as it could be: there is an extra map):
var out = for { i <- in; x <- Seq(i.a, i.b) } yield x
I would likely pick one of the other answers, however, as this does not directly address the final problem being solved.
Happy coding.
You can also use Stream to transform the pairs into a stream of individual items:
def toStream(xs: Iterable[Y]): Stream[Int] = {
xs match {
case Y(a, b) :: t => a #:: b #:: toStream(t)
case _ => Stream.empty
}
}
But like pst said, this doesn't solve your final problem of getting the distinct values, but once you have the stream it's trivial:
val result = toStream(ys).toList.removeDuplicates
Or a slight modification to the earlier suggestions to use flatten - add a function that turns a Y into a List:
def yToList(y: Y) = List(y.a, y.b)
Then you can do:
val ys = List(Y(1, 2), Y(3, 4))
(ys map yToList flatten).removeDuplicates
I agree with Dave's solution but another approach is to fold over the list, producing your map of id to User object as you go. The function to apply In the fold will query the db for both users and add them to the map being accumulated.
What about simple map? AFAIK for yield gets converted to series of flatMap and map anyway. Your problem could be solved simply as follows:
notifications.map(n => (n.fromId, n.objectOwnerId)).distinct