In a function in won't compile but outside it will - list

def combinations(list: List[(Char, Int)]) : List[List[(Char,Int)]]= {
val t = List.range(0, 1)
list match {
case List() => List()
case (c,i) :: xs => val res = for {
o <- List.range(1, i + 1)
} yield List((c, o)) :: combinations(xs)
List()
}
}
I have the following function which won't compile if I try to return res instead of List(). It's a type mismatch of List(List(List[(Char,Int)]]] However this code:
List(('a',10)) :: combinations(List())
compiles perfectly and as expected. Why is it that inside the function it won't compile? Isn't it the exact same thing? How could I tackle this?

Your for-comprehension yields an element of type List[List[(Char,Int)]].
For-comprehensions will generate lists of the elements they're yielding, so in this case that will be a List[List[List[(Char,Int)]]].
I'm not entirely sure what you're trying to achieve, but I think it'll be something like this:
def combinations(list: List[(Char, Int)]) : List[List[(Char,Int)]]= {
val t = List.range(0, 1)
list match {
case Nil => List()
case (c,i) :: xs =>
(for {
o <- List.range(1, i + 1)
} yield (c, o)) :: combinations(xs)
}
}
The for-comprehension generates a List[(Char, Int)] which is added at the head of the list generated by your combinations method.

Related

Optimize solution for the given coding problem

I am a newbie in Scala and I am trying to resolve the following simple coding problem:
Write a listOfLists recursive method that takes a number of strings as varargs and then
creates a list of lists of strings, with one less string in each, so for example:
listOfLists("3","2","1") should give back: List(List("3","2","1"), List("2","1"), List("1"))
The solution I've found is the following:
def listOfLists(strings: String*): List[List[String]] = {
val strLength = strings.length
#tailrec
def recListOfList(result: List[List[String]], accumulator: Int): List[List[String]] = {
accumulator match {
case x if x < strLength =>
recListOfList(result :+ (strings.toList.takeRight(strings.length - accumulator)), accumulator + 1 )
case _ => result
}
}
val res: List[List[String]] = List(strings.toList)
recListOfList(res, 1)
}
The solution works, however I think it could be written much more better.
A problem I can see is that I convert the varargs to a List with the toList method, but a hint that the problem gave me is to use the eta expansion _* but I don't know how to use it in this context.
Then, I tried to find another way to write in a more efficient way the following instruction:
strings.toList.takeRight(strings.length - accumulator))
but this is the only solution that came up in my mind.
Any review is welcome (also say that this solution is a total mess :D (providing the right reasons))
This meets all the specified requirements.
def listOfLists(strings: String*): List[List[String]] =
if (strings.isEmpty) Nil
else strings.toList :: listOfLists(strings.tail:_*)
You can do this:
def listOfLists(strings: String*): List[List[String]] = {
#annotation.tailrec
def loop(remaining: List[String], acc: List[List[String]]): List[List[String]] =
remaining match {
case head :: tail =>
loop(remaining = tail, (head :: tail) :: acc)
case Nil =>
acc.reverse
}
loop(remaining = strings.toList, acc = List.empty)
}
I believe the code is self-explanatory; but, feel free to ask any questions you may have.
You can see the code running here.
Not a recursive method but worth noting that tails in the standard library can do most of this. Then map and filter to convert to correct type and filter out empty list.
def listOfLists(strings: String *): List[List[String]] = strings.tails.map(_.toList).filter(_.nonEmpty).toList
Test:
scala> listOfLists("a","b","c")
val res6: List[List[String]] = List(List(a, b, c), List(b, c), List(c))
Using almost the same idea you can rewrite your solution in cleaner way:
def listOfLists(strings: String*): List[List[String]] = {
#tailrec
def recListOfList(curr: List[String], accumulator: Seq[List[String]]): Seq[List[String]] = {
curr match {
case head :: tail => recListOfList(tail, curr +: accumulator)
case _ => accumulator
}
}
recListOfList(strings.toList, Nil)
.reverse
.toList
}
With the splat(_*) operator, which adapts a sequence (Array, List, Seq, Vector, etc.) to varargs parameter you can create a shorter solution, but it will not be tail-recursive:
def listOfLists(strings: String*): List[List[String]] = {
val curr = strings.toList
curr match {
case Nil => Nil
case x :: tail => curr :: listOfLists(tail:_*)
}
}
From Scala 2.13 you can use List.unfold and Option.when:
def listOfLists(strings: String*): List[List[String]] = {
List.unfold(strings) { s =>
Option.when(s.nonEmpty)(s.toList, s.tail)
}
}
Code run at Scastie.

Type mismatch when dealing with list comprehensions

def combinations(list: List[(Char,Int)]): List[List[(Char,Int)]] = {
list match {
case List() => List()
case x::xs => for(o <- List.range(0,x._2 + 1)) yield List((x._1,o)) :: combinations(xs)
}
}
This function won't compile properly as the comprehension will convert my result to a list resulting in a
List(List(List((Char,Int))))
The function is meant to find all the sub lists of a List(Char,Int) taking in consideration that ('a',2) is a sub list of ('a',5)
My question is can I somehow stop the comprehension making the end result a list? Am I missing the whole point of comprehension? Is this function even logically correct?
for comprehension has a generator of type List so it yields aList. you are putting that yielded List into another list.
Following compiles
def combinations(list: List[(Char, Int)]) : List[List[(Char, Int)]]= {
val t = List.range(0, 1)
list match {
case List() => List()
case (c,i) :: xs => val res = for {
o <- List.range(0, i + 1)
} yield (c, o)
res:: combinations(xs)
}
}

Recursive call to find the sub lists of a list returns empty

def find(list: List[(Char,Int)]): List[(Char,Int)] = {
list match {
case List() => List()
case (z,y):: xs => ((for(i <- 1 to y) yield (z,i)).toList ::: find(xs).toList)
}
find(List(('a',5),('b',3))) // will return nothing at all
I simply cannot understand why such a function will return empty for the given arguments. It does not have arguments which are empty so what could be the problem here?
This might be a very easy question but I really need a fresh pair of eyes to help me debug this as I simply am not able to spot the silly mistake I made
Your function appears to work properly for me as it returns this:
List((a,1), (a,2), (a,3), (a,4), (a,5), (b,1), (b,2), (b,3))
I did notice in the code you provided you're missing a closing bracket on your find function, it should look like this:
def find(list: List[(Char, Int)]): List[(Char, Int)] = {
list match {
case List() => List()
case (z, y) :: xs => (for (i <- 1 to y) yield (z, i)).toList ::: find(xs)
}
}

How to find the largest element in a list of integers recursively?

I'm trying to write a function which will recursively find the largest element in a list of integers. I know how to do this in Java, but can't understand how to do this at Scala.
Here is what I have so far, but without recursion:
def max(xs: List[Int]): Int = {
if (xs.isEmpty) throw new java.util.NoSuchElementException();
else xs.max;
}
How can we find it recursively with Scala semantic.
This is the most minimal recursive implementation of max I've ever been able to think up:
def max(xs: List[Int]): Option[Int] = xs match {
case Nil => None
case List(x: Int) => Some(x)
case x :: y :: rest => max( (if (x > y) x else y) :: rest )
}
It works by comparing the first two elements on the list, discarding the smaller (or the first, if both are equal) and then calling itself on the remaining list. Eventually, this will reduce the list to one element which must be the largest.
I return an Option to deal with the case of being given an empty list without throwing an exception - which forces the calling code to recognise the possibility and deal with it (up to the caller if they want to throw an exception).
If you want it to be more generic, it should be written like this:
def max[A <% Ordered[A]](xs: List[A]): Option[A] = xs match {
case Nil => None
case x :: Nil => Some(x)
case x :: y :: rest => max( (if (x > y) x else y) :: rest )
}
Which will work with any type which either extends the Ordered trait or for which there is an implicit conversion from A to Ordered[A] in scope. So by default it works for Int, BigInt, Char, String and so on, because scala.Predef defines conversions for them.
We can become yet more generic like this:
def max[A <% Ordered[A]](xs: Seq[A]): Option[A] = xs match {
case s if s.isEmpty || !s.hasDefiniteSize => None
case s if s.size == 1 => Some(s(0))
case s if s(0) <= s(1) => max(s drop 1)
case s => max((s drop 1).updated(0, s(0)))
}
Which will work not just with lists but vectors and any other collection which extends the Seq trait. Note that I had to add a check to see if the sequence actually has a definite size - it might be an infinite stream, so we back away if that might be the case. If you are sure your stream will have a definite size, you can always force it before calling this function - it's going to work through the whole stream anyway. See notes at the end for why I really would not want to return None for an indefinite stream, though. I'm doing it here purely for simplicity.
But this doesn't work for sets and maps. What to do? The next common supertype is Iterable, but that doesn't support updated or anything equivalent. Anything we construct might be very poorly performing for the actual type. So my clean no-helper-function recursion breaks down. We could change to using a helper function but there are plenty of examples in the other answers and I'm going to stick with a one-simple-function approach. So at this point, we can to switch to reduceLeft (and while we are at it, let's go for `Traversable' and cater for all collections):
def max[A <% Ordered[A]](xs: Traversable[A]): Option[A] = {
if (xs.hasDefiniteSize)
xs reduceLeftOption({(b, a) => if (a >= b) a else b})
else None
}
but if you don't consider reduceLeft recursive, we can do this:
def max[A <% Ordered[A]](xs: Traversable[A]): Option[A] = xs match {
case i if i.isEmpty => None
case i if i.size == 1 => Some(i.head)
case i if (i collect { case x if x > i.head => x }).isEmpty => Some(i.head)
case _ => max(xs collect { case x if x > xs.head => x })
}
It uses the collect combinator to avoid some clumsy method of bodging a new Iterator out of xs.head and xs drop 2.
Either of these will work safely with almost any collection of anything which has an order. Examples:
scala> max(Map(1 -> "two", 3 -> "Nine", 8 -> "carrot"))
res1: Option[(Int, String)] = Some((8,carrot))
scala> max("Supercalifragilisticexpialidocious")
res2: Option[Char] = Some(x)
I don't usually give these others as examples, because it requires more expert knowledge of Scala.
Also, do remember that the basic Traversable trait provides a max method, so this is all just for practice ;)
Note: I hope that all my examples show how careful choice of the sequence of your case expressions can make each individual case expression as simple as possible.
More Important Note: Oh, also, while I am intensely comfortable returning None for an input of Nil, in practice I'd be strongly inclined to throw an exception for hasDefiniteSize == false. Firstly, a finite stream could have a definite or non-definite size dependent purely on the sequence of evaluation and this function would effectively randomly return Option in those cases - which could take a long time to track down. Secondly, I would want people to be able to differentiate between having passed Nil and having passed truly risk input (that is, an infinite stream). I only returned Option in these demonstrations to keep the code as simple as possible.
The easiest approach would be to use max function of TraversableOnce trait, as follows,
val list = (1 to 10).toList
list.max
to guard against the emptiness you can do something like this,
if(list.empty) None else Some(list.max)
Above will give you an Option[Int]
My second approach would be using foldLeft
(list foldLeft None)((o, i) => o.fold(Some(i))(j => Some(Math.max(i, j))))
or if you know a default value to be returned in case of empty list, this will become more simpler.
val default = 0
(list foldLeft default)(Math.max)
Anyway since your requirement is to do it in recursive manner, I propose following,
def recur(list:List[Int], i:Option[Int] = None):Option[Int] = list match {
case Nil => i
case x :: xs => recur(xs, i.fold(Some(x))(j => Some(Math.max(j, x))))
}
or as default case,
val default = 0
def recur(list:List[Int], i:Int = default):Int = list match {
case Nil => i
case x :: xs => recur(xs, i.fold(x)(j => Math.max(j, x)))
}
Note that, this is tail recursive. Therefore stack is also saved.
If you want functional approach to this problem then use reduceLeft:
def max(xs: List[Int]) = {
if (xs.isEmpty) throw new NoSuchElementException
xs.reduceLeft((x, y) => if (x > y) x else y)
}
This function specific for list of ints, if you need more general approach then use Ordering typeclass:
def max[A](xs: List[A])(implicit cmp: Ordering[A]): A = {
if (xs.isEmpty) throw new NoSuchElementException
xs.reduceLeft((x, y) => if (cmp.gteq(x, y)) x else y)
}
reduceLeft is a higher-order function, which takes a function of type (A, A) => A, it this case it takes two ints, compares them and returns the bigger one.
You could use pattern matching like that
def max(xs: List[Int]): Int = xs match {
case Nil => throw new NoSuchElementException("The list is empty")
case x :: Nil => x
case x :: tail => x.max(max(tail)) //x.max is Integer's class method
}
Scala is a functional language whereby one is encourage to think recursively. My solution as below. I recur it base on your given method.
def max(xs: List[Int]): Int = {
if(xs.isEmpty == true) 0
else{
val maxVal= max(xs.tail)
if(maxVal >= xs.head) maxVal
else xs.head
}
}
Updated my solution to tail recursive thanks to suggestions.
def max(xs: List[Int]): Int = {
def _max(xs: List[Int], maxNum: Int): Int = {
if (xs.isEmpty) maxNum
else {
val max = {
if (maxNum >= xs.head) maxNum
else xs.head
}
_max(xs.tail, max)
}
}
_max(xs.tail, xs.head)
}
I used just head() and tail()
def max(xs: List[Int]): Int = {
if (xs.isEmpty) throw new NoSuchElementException
else maxRecursive(xs.tail, xs.head)
}
def maxRecursive(xs: List[Int], largest: Int): Int = {
if (!xs.isEmpty) {
if (xs.head > largest) maxRecursive(xs.tail, xs.head)
else maxRecursive(xs.tail, largest)
} else {
largest
}
}
Here is tests for this logic:
test("max of a few numbers") {
assert(max(List(3, 7, 2, 1, 10)) === 10)
assert(max(List(3, -7, 2, -1, -10)) === 3)
assert(max(List(-3, -7, -2, -5, -10)) === -2)
}
Folding can help:
if(xs.isEmpty)
throw new NoSuchElementException
else
(Int.MinValue /: xs)((max, value) => math.max(max, value))
List and pattern matching (updated, thanks to #x3ro)
def max(xs:List[Int], defaultValue: =>Int):Int = {
#tailrec
def max0(xs:List[Int], maxSoFar:Int):Int = xs match {
case Nil => maxSoFar
case head::tail => max0(tail, math.max(maxSoFar, head))
}
if(xs.isEmpty)
defaultValue
else
max0(xs, Int.MinValue)
}
(This solution does not create Option instance every time. Also it is tail-recursive and will be as fast as an imperative solution.)
Looks like you're just starting out with scala so I try to give you the simplest answer to your answer, how do it recursively:
def max(xs: List[Int]): Int = {
def maxrec(currentMax : Int, l: List[Int]): Int = l match {
case Nil => currentMax
case head::tail => maxrec(head.max(currentMax), tail) //get max of head and curretn max
}
maxrec(xs.head, xs)
}
This method defines an own inner method (maxrec) to take care of the recursiveness. It will fail ( exception) it you give it an empty list ( there's no maximum on an empty List)
Here is my code (I am a newbie in functional programming) and I'm assuming whoever lands up under this question will be folks like me. The top answer, while great, is bit too much for newbies to take! So, here is my simple answer. Note that I was asked (as part of a Course) to do this using only head and tail.
/**
* This method returns the largest element in a list of integers. If the
* list `xs` is empty it throws a `java.util.NoSuchElementException`.
*
* #param xs A list of natural numbers
* #return The largest element in `xs`
* #throws java.util.NoSuchElementException if `xs` is an empty list
*/
#throws(classOf[java.util.NoSuchElementException])
def max(xs: List[Int]): Int = find_max(xs.head, xs.tail)
def find_max(max: Int, xs: List[Int]): Int = if (xs.isEmpty) max else if (max >= xs.head) find_max(max, xs.tail) else find_max(xs.head, xs.tail)
Some tests:
test("max of a few numbers") {
assert(max(List(3, 7, 2)) === 7)
intercept[NoSuchElementException] {
max(List())
}
assert(max(List(31,2,3,-31,1,2,-1,0,24,1,21,22)) === 31)
assert(max(List(2,31,3,-31,1,2,-1,0,24,1,21,22)) === 31)
assert(max(List(2,3,-31,1,2,-1,0,24,1,21,22,31)) === 31)
assert(max(List(Int.MaxValue,2,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,222,3,-31,1,2,-1,0,24,1,21,22)) === Int.MaxValue)
}
list.sortWith(_ > ).head & list.sortWith( > _).reverse.head for greatest and smallest number
If you are required to write a recursive max function on a list using isEmpty, head and tail and throw exception for empty list:
def max(xs: List[Int]): Int =
if (xs.isEmpty) throw new NoSuchElementException("max of empty list")
else if (xs.tail.isEmpty) xs.head
else if (xs.head > xs.tail.head) max(xs.head :: xs.tail.tail)
else max(xs.tail)
if you were to use max function on list it is simply (you don't need to write your own recursive function):
val maxInt = List(1, 2, 3, 4).max
def max(xs: List[Int]): Int = {
def _max(xs: List[Int], maxAcc:Int): Int = {
if ( xs.isEmpty )
maxAcc
else
_max( xs.tail, Math.max( maxAcc, xs.head ) ) // tail call recursive
}
if ( xs.isEmpty )
throw new NoSuchElementException()
else
_max( xs, Int.MinValue );
}
With tail-recursion
#tailrec
def findMax(x: List[Int]):Int = x match {
case a :: Nil => a
case a :: b :: c => findMax( (if (a > b) a else b) ::c)
}
With pattern matching to find max and return zero in case empty
def findMax(list: List[Int]) = {
def max(list: List[Int], n: Int) : Int = list match {
case h :: t => max(t, if(h > n) h else n)
case _ => n
}
max(list,0)
}
I presume this is for the progfun-example
This is the simplest recursive solution I could come up with
def max(xs: List[Int]): Int = {
if (xs.isEmpty) throw new NoSuchElementException("The list is empty")
val tail = xs.tail
if (!tail.isEmpty) maxOfTwo(xs.head, max(xs.tail))
else xs.head
}
def maxOfTwo(x: Int, y: Int): Int = {
if (x >= y) x
else y
}
def max(xs: List[Int]): Int = xs match {
case Nil => throw new NoSuchElementException("empty list!")
case x :: Nil => x
case x :: tail => if (x > max(tail)) x else max(tail)
}

Scala: extracting a repeated value from a list

I have often the need to check if many values are equal and in case extract the common value. That is, I need a function that will work like follows:
extract(List()) // None
extract(List(1,2,3)) // None
extract(List(2,2,2)) // Some(2)
Assuming one has a pimp that will add tailOption to seqs (it is trivial to write one or there is one in scalaz), one implementation looks like
def extract[A](l: Seq[A]): Option[A] = {
def combine(s: A)(r: Seq[A]): Option[A] =
r.foldLeft(Some(s): Option[A]) { (acc, n) => acc flatMap { v =>
if (v == n) Some(v) else None
} }
for {
h <- l.headOption
t <- l.tailOption
res <- combine(h)(t)
} yield res
}
Is there something like that - possibly more general - already in Scalaz, or some simpler way to write it?
This seems like a really complicated way to write
def extract[A](l:Seq[A]):Option[A] = l.headOption.flatMap(h =>
if (l.tail.forall(h==)) Some(h) else None)
You don't need tailOption, since the anonymous function that gets passed as an argument to flatMap is only executed if l is not empty.
If you only want to delete duplicates toSet is enough:
def equalValue[A](xs: Seq[A]): Option[A] = {
val set = xs.toSet
if (set.size == 1) Some(set.head) else None
}
scala> equalValue(List())
res8: Option[Nothing] = None
scala> equalValue(List(1,2,3))
res9: Option[Int] = None
scala> equalValue(List(2,2,2))
res10: Option[Int] = Some(2)
This is a fluent solution
yourSeq.groupBy(x => x) match {case m if m.size==1 => m.head._1; case _ => None}
You could use a map to count the number of occurrences of each element in the list and then return only those that occur more than once:
def extract[T](ts: Iterable[T]): Iterable[T] = {
var counter: Map[T, Int] = Map()
ts.foreach{t =>
val cnt = counter.get(t).getOrElse(0) + 1
counter = counter.updated(t, cnt)
}
counter.filter(_._2 > 1).map(_._1)
}
println(extract(List())) // List()
println(extract(List(1,2,3))) // List()
println(extract(List(2,2,2))) // List(2)
println(extract(List(2,3,2,0,2,3))) // List(2,3)
You can also use a foldLeft instead of foreach and use the empty map as the initial accumulator of foldLeft.