How to do parenthesis balancing using scala, recursion ,one function and one parameter for the function? - scala

I am builing a little method for parenthesis balancing using scala and recursion.
I came out this code which surprisingly doesn't work.
object Test{
def balance(chars: List[Char]): Boolean=
{
var opening_index: Int = -1
var closing_index: Int = -1
opening_index = chars.indexOf('(')
closing_index = chars.indexOf(')')
println(opening_index)
println(closing_index)
if ( chars.size == 0 ) true
if ((opening_index == -1) & (closing_index== -1))
{
true
}
if (closing_index> -1 & opening_index> -1)
{
if (closing_index< opening_index) return(false)
else
{
balance(chars.filter(_!=chars(closing_index)).filter(_!=chars(opening_index)))
}
}
else
return (false)
}
val lst:List[Char] = List('(',')' ,'3','4')
balance(lst)
}
I am aware that there are other similar posts but I am more interested in using this approach than the other ones.

You probably wanted to filter by index, not by character. As it is, your code erases all parentheses in the first round.
This here works with zipWithIndex, and compares the index with opening_index and closing_index:
def balance(chars: List[Char]): Boolean = {
val opening_index = chars.indexOf('(')
val closing_index = chars.indexOf(')')
if ( chars.size == 0 ) {
true
} else if ((opening_index == -1) && (closing_index== -1)) {
true
} else if (closing_index > -1 && opening_index > -1) {
if (closing_index < opening_index) {
false
} else {
balance(
chars.zipWithIndex.filterNot{
case (c, i) => i == opening_index || i == closing_index
}.map(_._1)
)
}
} else {
false
}
}
println(balance("()34".toList))
println(balance("()34)".toList))
println(balance("(x)(y(z))".toList))
println(balance("(x)(y(z)".toList))
Output:
true
false
true
false

You can use below solution to check balance parenthesis.
object Driver extends App{
def balance(chars: List[Char]): Boolean=
{
if (chars.mkString("").length() == 0) {
return true;
}
if (chars.mkString("").contains("()")) {
return balance(chars.mkString("").replaceFirst("\\(\\)", "").toCharArray.toList);
}
if (chars.mkString("").contains("[]")) {
return balance(chars.mkString("").replaceFirst("\\[\\]", "").toCharArray.toList);
}
if (chars.mkString("").contains("{}")) {
return balance(chars.mkString("").replaceFirst("\\{\\}", "").toCharArray.toList);
} else {
return false;
}
}
println(balance(List('(','{','}')))
println(balance(List('(','{','}',')')))
}

There are two main (functional) problems with this code.
Firstly, this test does nothing because the result is thrown away
if ((opening_index == -1) & (closing_index== -1))
{
true
}
You probably meant return true
Secondly, the recursive call is wrong
balance(chars.filter(_ != chars(closing_index)).filter(_ != chars(opening_index)))
These two calls to filter are removing all the parentheses from the list, so the call to balance will always succeed even if the rest of the list is unbalanced.
You probably want to use three slice calls to remove the specific parentheses at opening_index and closing_index.

Related

Continue in Scala for loops

How do i convert below Java code to scala and use continue in for loop, this program remove minimum number of extra closed parenthesis in a given string
input : lee(t(c)o)de)
output : leet(t(c)o)de
public String minRemoveToMakeValid(String s){
StringBuilder sb =new StringBuilder();
in open =0;
for (char c : s.toCharArray()){
if(c == '('){
open++
}
else if(c == ')'){
if(open == 0) continue;
open --;
}
sb.append(c)
}
return sb
}
https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/
import util.control.Breaks._
val searchMe = "peter piper picked a peck of pickled peppers"
var numPs = 0
for (i <- 0 until searchMe.length) {
breakable {
if (searchMe.charAt(i) != 'p') {
break // break out of the 'breakable', continue the outside loop
} else {
numPs += 1
}
}
}
println("Found " + numPs + " p's in the string.")
Try it: https://scastie.scala-lang.org/R9sr95WESLyiKamCHHUVdQ
Im able to get it worked using below code
def minRemoveToMakeValid(s: String): String = {
var open = 0
val sb = new StringBuilder
for (c <- s.toCharArray) {
breakable {
if (c == '(') open += 1
else if (c == ')') {
if (open == 0)break
open -= 1
}
sb.append(c)
}
}
var result = new StringBuilder()
for(i<-sb.length()-1 to 0 by -1)
{
breakable{
open-=1
if(sb.charAt(i) == '(' && open >0) break
result.append(sb.charAt(i))
}
}
result.reverse.toString()
}

Access ArrayList outside nested If else block in Scala

I have following code :-
var ArrayStop = new ArrayList[imeistoppage]()
val listings = rddStopCalculate.zipWithIndex().map(p => {
if (p._2 == 0) {
imei = p._1.imei
lat = p._1.latitude
long = p._1.longitude
gpsdt = p._1.gpsdt
} else if (p._2 > 0 && p._2 != lastindex) {
if (p._1.imei.equals(imei) && p._1.latitude == lat && p._1.longitude == long) {
flag += 1
newgpsdt = p._1.gpsdt
} else {
if (flag > 0) {
timeDiff = newgpsdt.getTime() - gpsdt.getTime()
if (timeDiff > 60000) {
ArrayStop.add(imeistoppage(p._1.imei, lat, long, timeDiff))
}
flag = 0
}
imei = p._1.imei
lat = p._1.latitude
long = p._1.longitude
gpsdt = p._1.gpsdt
}
} else {
if (p._1.imei.equals(imei) && p._1.latitude == lat && p._1.longitude == long) {
flag += 1
newgpsdt = p._1.gpsdt
}
if (flag > 0) {
timeDiff = newgpsdt.getTime() - gpsdt.getTime()
if (timeDiff > 60000) {
ArrayStop.add(imeistoppage(p._1.imei, lat, long, timeDiff))
}
flag = 0
}
}
ArrayStop
}).collect()
val returnList = listings(listings.length - 1)
val tempCollection = returnList.asScala
val tempRDD = sc.parallelize(tempCollection)
tempRDD.saveToCassandra("db", "table", SomeColumns("imei", "lat", "long", "duration"))
As we can see in above code I'm actually adding data to ArrayStop for specific IF condition only and I want this to be accessed outside this rdd loop but I was unable to do so So I created a variable "listings" to store data which is actually taking all the rows whereas I want only those entries which are added in ArrayStop. So what is the best way to bring any array outside nested If-else block. This is different from this issue
Scala spark, listbuffer is empty
Thanks,

How to claculate adjacent data with spark/scala

I hava a RDD,the RDD type is Tuple2(value,timestamp),value is 1 or 0 , timestamp is a sequential, and a variable limitTime=4. When I map the RDD, if the value is 1 the output value from current timestamp to (timestamp +limitTime) is 1 ,else current value is 0, I call it is period. But there is a special case,when the value is 1 and its timestamp is in period,then it is ignored, the current value of output is 0
input : (0,0),(1,1),(0,3),(0,5),(0,7),(0,8),(0,10),(1,12),(0,14),(0,15)
expected output :(0,0),(1,1),(1,3),(1,5),(0,7),(0,8),(0,10),(1,12),(1,14),(1,15)
special input2: (0,0),(1,1),(0,3),(1,5),(0,7),(1,8),(0,10),(1,12),(0,14),(0,15)
expected output2:(0,0),(1,1),(1,3),(1,5),(0,7),(1,8),(1,10),(1,12),(0,14),(0,15)
this is my try:
var limitTime=4
var startTime= -limitTime
val rdd=sc.parallelize(List((0,0),(1,1),(0,3),(1,5),(0,7),(1,8),(0,10),(1,12),(0,14),(0,15)),4)
val results=rdd.mapPartitions(parIter => {
var resultIter = new ArrayBuffer[Tuple2[Int,Int]]()
while (parIter.hasNext) {
val iter = parIter.next()
if(iter._1==1){
if(iter._2<=startTime+limitTime&&iter._2!=0&&iter._2>=startTime){
resultIter.append(iter)
}else{
resultIter.append(iter)
startTime=iter._2
}
}else{
if(iter._2<=startTime+limitTime&&iter._2!=0&&iter._2>=startTime){
resultIter.append((1,iter._2))
}else{
resultIter.append(iter)
}
}
}
resultIter.toIterator
})
results.collect().foreach(println)
it's so inefficient,how can I get the same result without array?
Following code should work for both of your cases.
var limitTime=3
var first = true
var previousValue = 0
val rdd=sc.parallelize(List((0,0),(1,1),(0,3),(0,5),(0,7),(0,8),(0,10),(1,12),(0,14),(0,15)), 4)
val tempResult = rdd.collect.map(pair => {
if(first){
first = false
previousValue = pair._1
(pair._1, pair._2)
}
else {
if ((pair._1 == 1 || previousValue == 1) && limitTime > 0) {
limitTime -= 1
previousValue = 1
(1, pair._2)
}
else {
if (limitTime == 0) limitTime = 3
previousValue = pair._1
(pair._1, pair._2)
}
}
})
tempResult.foreach(print)
If it doesn't please let me know

How to define count without using var

I have this simple function that return some Status:
def getStatus : String =
{
//...
}
And i want to wait until this return specific status but still count this number of calls before exit:
def wait =
{
var count = 0
while (getStatus != "smeStatus" && count < 10) {
// some code here
count++
}
}
How can i avoid of using var ?
You can use a recursive method that takes the count-so-far and returns it + 1:
def waitUntilDone(countSoFar: Int): Int = {
if (getStatus != "smeStatus" && countSoFar < 10) {
// some code here
waitUntilDone(countSoFar + 1)
} else {
countSoFar
}
}
// invoke it starting with 0:
val count = waitUntilDone(0)
def status = ""
def waiting: Unit = {
def check(count: Int): Unit = {
if(count < 10 && status != "smeStatus") {
// do something
check(count + 1)
}
}
check(0)
}

Return list with the values on odd positions

Why does the following code return a empty list instead of a list with the values at odd positions ?
def f(arr:List[Int]) : List[Int] = {
def odd_concat(list_odd:List[Int], arr_index:Int) : List[Int] = {
if(arr_index == arr.size) {
list_odd
}
else if(arr_index % 2 == 0) {
odd_concat(list_odd, arr_index + 1)
}
else {
//println(arr(arr_index))
list_odd:+arr(arr_index)
odd_concat(list_odd, arr_index + 1)
}
}
odd_concat(List(), 0)
}
You are using immutable list, immutable means the object cannot be change.
Your code:
list_odd:+arr(arr_index)
It does not change the list_odd with the value of arr(arr_index) rather give a new instance of List with values added.
Try to insert that code inside the odd_concat() instead, like the following:
def f(arr:List[Int]) : List[Int] = {
def odd_concat(list_odd:List[Int], arr_index:Int) : List[Int] = {
if(arr_index == arr.size) {
list_odd
}
else if(arr_index % 2 == 0) {
odd_concat(list_odd, arr_index + 1)
}
else {
//println(arr(arr_index))
odd_concat(list_odd:+arr(arr_index), arr_index + 1)
}
}
odd_concat(List(), 0)
}