I am starting the Scala programming course on Coursera, coming from 2 years experience with Java/Python/C#.
I am working through a problem where you must check to see if a list of characters has balanced paranthesis.
/**
* Exercise 2
*/
def balance(chars: List[Char]): Boolean = {
def recursiveBalance(chars: List[Char]): Boolean = {
if (!chars.contains('(') && !chars.contains(')')) true
else {
val openIndex = chars.indexOf('(')
if (openIndex == -1) false
else {
val chars2 = dropFirstMatch(chars, '(')
val closeIndex = chars2.indexOf(')')
if(closeIndex == -1 || openIndex > closeIndex) false
else recursiveBalance(dropFirstMatch(chars2, ')'))
}
}
}
def remove(index: Int, list: List[Char]): List[Char] = {
list.take(index) ++ list.drop(index)
}
def dropFirstMatch[A](ls: List[A], value: A): List[A] = {
val index = ls.indexOf(value) //index is -1 if there is no match
if (index < 0) {
ls
} else if (index == 0) {
ls.tail
} else {
// splitAt keeps the matching element in the second group
val (a, b) = ls.splitAt(index)
a ++ b.tail
}
}
recursiveBalance(chars)
}
So this solution is working (if a little ugly). As part of the solution I attempted to remove an object from a list at a specific index. I've learned that in Scala Lists are immutable.
My attempt at doing this was to provide the index, the list, and use this example, which is the remove function. This works in the REPL, I made a list, ran the function and a new list was returned without the specified index.
But this did not work in my balance solution. Everytime the list was returned it was unchanged, causing infinite recursion. Eventually I stumbled on this article and borrowed their dropFirstMatch function, and upon substituting it, bam, working solution.
I am very new to Scala, and I must be overlooking something - can someone point out what it might be?
take(n) selects the first n elements in your list, where drop(n) selects all elements of the list except the first n ones.
To illustrate:
scala> val xs = List(0,1,2,3,4,5)
xs: List[Int] = List(0, 1, 2, 3, 4, 5)
scala> xs.take(2)
res0: List[Int] = List(0, 1)
scala> xs.drop(2)
res1: List[Int] = List(2, 3, 4, 5)
scala> xs.take(2) ++ xs.drop(2)
res2: List[Int] = List(0, 1, 2, 3, 4, 5)
In other words, your remove function simply returns the same list because it takes the first n elements of the original list, then adds that to the elements of the original list except the first n ones (drop). In order to remove the element at the given index in your list, you merely need to increment the index by one in your call to drop:
def remove(index: Int, list: List[Char]): List[Char] = {
list.take(index) ++ list.drop(index+1)
}
Checking for balanced parenthesis is way easier than what you are doing:
def balanced(list: Seq[Char]): Boolean = list.foldLeft(0) {
case (n, _) if (n < 0) => return false
case (n, '(') => n + 1
case (n, ')') => n - 1
case (n, _) => n
} == 0
Or, if you are a purist, like some commenters, and insist on recursion:
#tailrec
def balanced(chars: Seq[Char], n: Int = 0): Boolean = (n, chars) match {
case (-1, _) => false
case (n, Nil) => n == 0
case ('(' :: tail, n) => balanced(tail, n+1)
case (')' :: tail, n) => balanced(tail, n-1)
case (_ :: tail, n) => balanced(tail, n)
}
Related
I am having a hard time understanding m.get and m+(x._1 -> x._2) in below code ,can anyone let me know what does it do
object Solution {
def twoSum(nums: Array[Int], target: Int): Array[Int] = {
nums.zipWithIndex.foldLeft(Map.empty[Int,Int])((m,x)=>
{
if(m.get(target - x._1)==None)
m+(x._1 -> x._2)
else
return Array(m.getOrElse(target-x._1, -1), x._2)
})
null
}
}
This code returns indices of the two numbers such that they add up to a specific target.
Here are a few different (better?) ways to get the same result (essentially the same).
If you want all index pairs whose values sum to the target.
def twoSum(nums :Array[Int], target :Int) :Iterator[Seq[Int]] =
nums.indices
.combinations(2)
.filter{case Seq(a,b) => nums(a) + nums(b) == target}
twoSum(Array(3,5,11,2,13,9), 41) //returns empty Iterator
twoSum(Array(3,5,11,2,13,9), 14) //returns Iterator(Seq(0, 2), Seq(1, 5))
If you want just the first pair that sum to the target (with early termination).
def twoSum(nums :Array[Int], target :Int) :Option[Seq[Int]] =
nums.indices
.combinations(2)
.find{case Seq(a,b) => nums(a) + nums(b) == target}
twoSum(Array(3,5,11,2,13,9), 41) //returns None
twoSum(Array(3,5,11,2,13,9), 14) //returns Some(Seq(0, 2))
If you want to avoid the Option and just return an empty collection if no 2 values sum to the target.
def twoSum(nums :Array[Int], target :Int) :Seq[Int] =
nums.indices
.combinations(2)
.find{case Seq(a,b) => nums(a) + nums(b) == target}
.getOrElse(Seq())
twoSum(Array(3,5,11,2,13,9), 41) //returns Seq()
twoSum(Array(3,5,11,2,13,9), 14) //returns Seq(0, 2)
Here is a more efficient and idiomatic way to solve that problem.
def twoSum(nums: ArraySeq[Int], target: Int): Option[(Int, Int)] = {
val allIndexes = for {
i <- Iterator.range(start = 0, end = nums.length)
j <- Iterator.range(start = i + 1, end = nums.length)
} yield i -> j
allIndexes.find {
case (i, j) => (nums(i) + nums(j)) == target
}
}
(Note: ArraySeq is like any normal array, but it is immutable, it was introduced in 2.13 if you are in an older version, just use a regular Array).
Here is my own take, the function loops through all pairs of numbers until an answer is found. It makes use of scala's optimised recursion capability. Also it uses simple concepts only, useful for beginners: functions, Arrays, Ints and if-else statements.
def twoSum(nums :Array[Int], target : Int): Array[Int] = {
def iter(a:Int, b: Int): Array[Int] = {
if(nums(a) + nums(b) == target) Array(a,b)
else if(b < nums.length-1) iter(a,b+1)
else iter(a+1,a+2)
}
iter(0,1)
}
jwvh: true. with empty array on failure:
def twoSum(nums: Array[Int], target: Int): Array[Int] = {
def iter(a: Int,b: Int): Array[Int] = {
if(nums(a) + nums(b) == target) Array(a,b)
else if(b < nums.length-1) iter(a,b+1)
else if(a < nums.length-2) iter(a+1,a+2)
else Array()
}
iter(0,1)
}
I have a requirement where I have to search a character in vector of vectors. I have written a method which is very crude. What is a better way to search an element in vector of vectors.
Here is my code:
def search( xs: Vector[Vector[Char]], char: Char, rowIndex: Int): Pos = xs.headOption match {
case None => Pos(-1, -1)
case Some(row) => {
val tuple = searchHelper(row, char, 0)
if(tuple._1)
Pos(rowIndex, tuple._2)
else
search(xs.tail, char, rowIndex +1)
}
}
def searchHelper(xs: Vector[Char], char: Char, colIndex: Int): (Boolean, Int) = xs.headOption match {
case None => (false, colIndex)
case Some(col) =>
if(col == char)
(true, colIndex)
else
searchHelper(xs.tail, char, colIndex +1)
}
search(vector, c, 0)
Here is the input:
val input =
"""ooo-------
|oSoooo----
|ooooooooo-
|-ooooooooo
|-----ooToo
|------ooo-""".stripMargin
val vector =
Vector(input.split("\n").map(str => Vector(str: _*)): _*)
val c = 'S'
Something like this, perhaps?
xs
.iterator
.zipWithIndex
.map { case (chars, idx) => (idx, chars.indexOf(c)) }
.collectFirst {
case (outer, inner) if(inner >= 0) => Pos(outer, inner)
}.getOrElse(Pos(-1, 1))
To address a concern from the comments: this is not iterating through the entire list multiple times (not even once completely, as long as it finds a match earlier). Scala iterators are wonderful that way: you can write a chain of calls, that conceptually looks like a bunch of sequential transformations to the entire list, but is really executed lazily, element by element: the first element is is extracted from list, converted to a tuple (chars, 0), fed to the map, then the result of that is sent to collectFirst, if the condition matches there, it stops and returns right away, otherwise, next element is taken from list, made into a tuple (chars, 1), fed to the .map, etc ...
If, with better, you mean more concise, you could try leveraging the methods on Scalas collections:
def search( xs: Vector[Vector[Char]], c: Char ): (Int, Int) = {
var innerIndex = -1
val outerIndex = xs.indexWhere { inner =>
innerIndex = inner.indexOf(c)
innerIndex > -1
}
(outerIndex, innerIndex)
}
This assumes that you only need the first occurence of that character.
indexWhere terminates as soon as the innerIndex is larger than -1.
Maybe another possibility, which goes more in your recursive direction (and without a mutable var), but also with minimal iterations:
#tailrec
def search(xs: Vector[Vector[Char]], c: Char, n: Int = 0): (Int, Int) = {
if (n > xs.size - 1) (-1, -1)
else
xs(n).indexOf(c) match {
case -1 => search(xs, c, n + 1)
case i => (n, i)
}
}
Simplest way of doing it :
def findChar(c: Char, levelVector: Vector[Vector[Char]]): Pos =
val x = levelVector.indexWhere(_.contains(c))
val y = levelVector(x).indexWhere(_ == c)
Pos(x,y)
Indeed you have to assume there is only one correct answer.
Main idea :
First search for the row that have the character c
Then find the column in this row that has this character c
I would like to know whether is there any isSorted() function exist or not in scala.
Question: check whether List[Int] is sorted or not, If not remove smallest number and do again till List[Int] become sorted?
I want only 1 or 2 line program.
You can compare each pair in the input sequence for lists containing more than 1 item:
def isSorted[T](s: Seq[T])(implicit ord: Ordering[T]): Boolean = s match {
case Seq() => true
case Seq(_) => true
case _ => s.sliding(2).forall { case Seq(x, y) => ord.lteq(x, y) }
}
It's not the best solution but you can use sorted method on list and then compare it with original one;
def sorted(l: List[Int]): Boolean = l == l.sorted
With some lazyness:
def isSorted(l:List[Int]):Boolean = {
val list = l.view
!list.zip(list.tail).exists {case (x,y) => x>y}
}
Performing a sort just to check if the list is already sorted is a bit of an overkill. The optimal solution here seems to be the most obvious one, which is just describing the problem in human language and transferring it into code:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list match {
case Nil => true // an empty list is sorted
case x :: Nil => true // a single-element list is sorted
case x :: xs => ord.lteq(x, xs.head) && isSorted(xs) // if the first two elements are ordered and the rest are sorted, the full list is sorted too
}
If you want it shorter, you could trade the 2nd case for a bit of readability:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list match {
case Nil => true
case x :: xs => xs.headOption.fold(true)(ord.lteq(x, _)) && isSorted(xs)
}
If you want a one-liner, that would be not readable at all:
def isSorted[T](list: List[T])(implicit ord: Ordering[T]): Boolean = list.headOption.fold(true)(a => list.tail.headOption.fold(true)(ord.lteq(a, _) && isSorted(list.tail.tail)))
def isSorted(xs: List[Int]): Boolean = (xs.tail zip xs).forall(pair => pair._1 - pair._2 > 0)
Using `zip`
Lets do it without actually sorting the list.
Drop the head element in the intermediate list and then compare in pairs with original list. This way, ith element compares with i+1th element of the original list.
scala> val originalList = List(10, 20, 30, 40)
val originalList: List[Int] = List(10, 20, 30, 40)
scala> val intermediate = originalList.drop(1)
val intermediate: List[Int] = List(20, 30, 40)
scala> originalList.zip(intermediate)
val res5: List[(Int, Int)] = List((10,20), (20,30), (30,40))
scala> originalList.zip(intermediate).forall { case (orig, in) => orig <= in }
val res17: Boolean = true
A inefficient but easy to understand answer:
def specialSort(a: List[Int]): List[Int] =
if (a == a.sorted) a
else specialSort(a.filterNot(_ == a.min))
l == l.sorted didn't work for me, managed to do it with l sameElements l.sorted
Here your one-line homework solution
def removeMinWhileNotSorted[A: Ordering](xs: List[A]): List[A] = if (xs == xs.sorted) xs else xs.splitAt(xs.indexOf(xs.min)) match {case (prefix, m :: postfix) => removeMinWhileNotSorted(prefix ++ postfix)}
It does not exists. But it is easy to do: create a list with the joined version of the list and the same list sorted as you want and verify both elements of the joined list are the same.
Something like this:
import org.junit.Assert._
val sortedList = List(1, 3, 5, 7)
val unsortedList = List(10, 1, 8, 3, 5, 5, 2, 9)
// detailed test. It passes.
sortedList
.zip(sortedList.sortWith((a,b) => a.compareTo(b) < 0)) // this is the required sorting criteria.
.foreach(x => assertEquals("collection is not sorted", x._1, x._2))
// easier to read but similar test. It fails.
unsortedList
.zip(unsortedList.sorted) // this is the required sorting criteria.
.foreach(x => assertEquals("collection is not sorted", x._1, x._2))
a function could be:
def isSorted(list: List[Int]): Boolean = !list.zip(list.sortWith((a, b) => a.compareTo(b) < 0)).exists(p => !p._1.equals(p._2))
def isSorted[T <% Ordered[T]](list: List[T]): Boolean =
list.sliding(2).forall(p => (p.size==1) || p(0) < p(1))
I assumed that if two neighbor elements are equal it is legal too.
def isSorted[T <% Ordered[T]](l: List[T]):Boolean ={
val a = l.toArray
(1 until a.length).forall(i => a(i-1) <= a(i))
}
Another possibility (not necessarily any better than some of the other suggestions)
def isSorted[T <% Ordered[T]](a: List[T]): Boolean =
if (a == Nil) true // an empty list is sorted
else a.foldLeft((true, a.head))(
(prev, v1) => {
val (p, v0) = prev
(p && v0 <= v1, v1)
})._1
Results for a few test cases:
isSorted(Nil) -> true
isSorted(1 :: Nil) -> true
isSorted(2 :: 3 :: Nil) -> true
isSorted(1 :: 2 :: 5 :: 8 :: Nil) -> true
isSorted(1 :: 1 :: 2 :: 2 :: Nil) -> true
isSorted(3 :: 2 :: Nil) -> false
isSorted(1 :: 2 :: 3 :: 1 :: Nil) -> false
You can use tail recursion to less create objects and to avoid stack overflow for long lists. This version is lazy, function return value instantly after a first unordered pair.
#scala.annotation.tailrec
def isSorted[T : Ordering](values: List[T]): Boolean = {
import scala.math.Ordering.Implicits._
values match {
case fst :: snd :: _ if fst <= snd => isSorted(values.tail)
case _ :: _ :: _ => false
case _ => true
}
}
This works.
def check(list: List[Int]) = {
#tailrec
def isSorted(list: List[Int], no: Int, acc: Boolean): Boolean = {
if (list.tail == Nil) acc
else if (list.head > no) {
isSorted(list.tail, list.head, acc = true)
}
else isSorted(list.tail, list.head, acc=false)
}
isSorted(list, Integer.MIN_VALUE, acc = false)
}
How do I split a sequence into two lists by a predicate?
Alternative: I can use filter and filterNot, or write my own method, but isn't there a better more general (built-in) method ?
By using partition method:
scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))
Good that partition was the thing you wanted -- there's another method that also uses a predicate to split a list in two: span.
The first one, partition will put all "true" elements in one list, and the others in the second list.
span will put all elements in one list until an element is "false" (in terms of the predicate). From that point forward, it will put the elements in the second list.
scala> Seq(1,2,3,4).span(x => x % 2 == 0)
res0: (Seq[Int], Seq[Int]) = (List(),List(1, 2, 3, 4))
You might want to take a look at scalex.org - it allows you to search the scala standard library for functions by their signature. For example, type the following:
List[A] => (A => Boolean) => (List[A], List[A])
You would see partition.
You can also use foldLeft if you need something a little extra. I just wrote some code like this when partition didn't cut it:
val list:List[Person] = /* get your list */
val (students,teachers) =
list.foldLeft(List.empty[Student],List.empty[Teacher]) {
case ((acc1, acc2), p) => p match {
case s:Student => (s :: acc1, acc2)
case t:Teacher => (acc1, t :: acc2)
}
}
I know I might be late for the party and there are more specific answers, but you could make good use of groupBy
val ret = List(1,2,3,4).groupBy(x => x % 2 == 0)
ret: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(1, 3), true -> List(2, 4))
ret(true)
res3: List[Int] = List(2, 4)
ret(false)
res4: List[Int] = List(1, 3)
This makes your code a bit more future-proof if you need to change the condition into something non boolean.
If you want to split a list into more than 2 pieces, and ignore the bounds, you could use something like this (modify if you need to search for ints)
def split(list_in: List[String], search: String): List[List[String]] = {
def split_helper(accum: List[List[String]], list_in2: List[String], search: String): List[List[String]] = {
val (h1, h2) = list_in2.span({x: String => x!= search})
val new_accum = accum :+ h1
if (h2.contains(search)) {
return split_helper(new_accum, h2.drop(1), search)
}
else {
return accum
}
}
return split_helper(List(), list_in, search)
}
// TEST
// split(List("a", "b", "c", "d", "c", "a"), {x: String => x != "x"})
How do I split a sequence into two lists by a predicate?
Alternative: I can use filter and filterNot, or write my own method, but isn't there a better more general (built-in) method ?
By using partition method:
scala> List(1,2,3,4).partition(x => x % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4),List(1, 3))
Good that partition was the thing you wanted -- there's another method that also uses a predicate to split a list in two: span.
The first one, partition will put all "true" elements in one list, and the others in the second list.
span will put all elements in one list until an element is "false" (in terms of the predicate). From that point forward, it will put the elements in the second list.
scala> Seq(1,2,3,4).span(x => x % 2 == 0)
res0: (Seq[Int], Seq[Int]) = (List(),List(1, 2, 3, 4))
You might want to take a look at scalex.org - it allows you to search the scala standard library for functions by their signature. For example, type the following:
List[A] => (A => Boolean) => (List[A], List[A])
You would see partition.
You can also use foldLeft if you need something a little extra. I just wrote some code like this when partition didn't cut it:
val list:List[Person] = /* get your list */
val (students,teachers) =
list.foldLeft(List.empty[Student],List.empty[Teacher]) {
case ((acc1, acc2), p) => p match {
case s:Student => (s :: acc1, acc2)
case t:Teacher => (acc1, t :: acc2)
}
}
I know I might be late for the party and there are more specific answers, but you could make good use of groupBy
val ret = List(1,2,3,4).groupBy(x => x % 2 == 0)
ret: scala.collection.immutable.Map[Boolean,List[Int]] = Map(false -> List(1, 3), true -> List(2, 4))
ret(true)
res3: List[Int] = List(2, 4)
ret(false)
res4: List[Int] = List(1, 3)
This makes your code a bit more future-proof if you need to change the condition into something non boolean.
If you want to split a list into more than 2 pieces, and ignore the bounds, you could use something like this (modify if you need to search for ints)
def split(list_in: List[String], search: String): List[List[String]] = {
def split_helper(accum: List[List[String]], list_in2: List[String], search: String): List[List[String]] = {
val (h1, h2) = list_in2.span({x: String => x!= search})
val new_accum = accum :+ h1
if (h2.contains(search)) {
return split_helper(new_accum, h2.drop(1), search)
}
else {
return accum
}
}
return split_helper(List(), list_in, search)
}
// TEST
// split(List("a", "b", "c", "d", "c", "a"), {x: String => x != "x"})