Scala 如何递归平衡括号
我正在编写一些平衡括号的代码,这被证明对算法最有用 我用我的第一语言(PHP)实现了它,但我正在学习Scala并尝试转换代码 以下是我的PHP代码:Scala 如何递归平衡括号,scala,recursion,Scala,Recursion,我正在编写一些平衡括号的代码,这被证明对算法最有用 我用我的第一语言(PHP)实现了它,但我正在学习Scala并尝试转换代码 以下是我的PHP代码: function balanced($string) { return isBalanced($string, ""); } function isBalanced($chars, $stack) { if (!strlen($chars)) return empty($stack); switch ($chars[0])
function balanced($string) {
return isBalanced($string, "");
}
function isBalanced($chars, $stack) {
if (!strlen($chars))
return empty($stack);
switch ($chars[0]) {
case '(':
// prepend stack with '(', move to next character
return isBalanced(substr($chars, 1), $chars[0] . $stack);
case ')':
// if '(' seen previously, shift stack, move to next character
return !empty($stack) && isBalanced(substr($chars, 1), substr($stack, 1));
default:
// do nothing to stack, move to next character
return isBalanced(substr($chars, 1), $stack);
}
}
我已经测试过了,它很有效。但是,当我将其转换为Scala时,它在平衡字符串上失败
我的Scala代码:
object Main {
def balance(chars: List[Char]): Boolean = {
def balanced(chars: List[Char], stack: String): Boolean = {
if (chars.isEmpty)
stack.isEmpty
else if (chars.head == ')')
balanced(chars.tail, chars.head + stack)
else if (chars.head == '(')
!stack.isEmpty && balanced(chars.tail, stack.tail)
else
balanced(chars.tail, stack)
}
balanced(chars, "")
}
}
我知道这不是最好的Scala代码,但我才刚刚开始。一些测试:
balance("(if (0) false (x))".toList) - fails
balance("profit and loss (P&L).\n(cashflow)".toList) - fails
balance(":)".toList) - passes
balance(")(()".toList) - passes
PHP等价物通过了所有这些测试。我在Scala实现中犯了什么错误?您混淆了
(
和)
值得一提的是,这里有一个更惯用的Scala实现:
def balance(chars: List[Char]): Boolean = {
@tailrec def balanced(chars: List[Char], open: Int): Boolean =
chars match {
case Nil => open == 0
case '(' :: t => balanced(t, open + 1)
case ')' :: t => open > 0 && balanced(t, open - 1)
case _ :: t => balanced(t, open)
}
balanced(chars, 0)
}
为了完整起见,我发现了一个更简洁的“scala-esque”实现,它来自:
看来我们在上同一门课。我的解决方案:
def balance(chars: List[Char]): Boolean =
doBalance(chars, 0) == 0;
def doBalance(chars: List[Char], parenthesisOpenCount: Int): Int =
if(parenthesisOpenCount <0) -100;
else
if(chars.isEmpty) parenthesisOpenCount
else
chars.head match {
case '(' => return doBalance(chars.tail, parenthesisOpenCount+1)
case ')' => return doBalance(chars.tail, parenthesisOpenCount-1)
case _ => return doBalance(chars.tail, parenthesisOpenCount)
}
def余额(字符:列表[Char]):布尔=
多平衡(字符,0)=0;
def doBalance(chars:List[Char],括号isopencount:Int):Int=
if(括号内的IsoPenCount返回doBalance(chars.tail,括号内的IsoPenCount+1)
case')=>返回双平衡(chars.tail,圆括号isopencount-1)
case=>返回doBalance(chars.tail,圆括号)
}
与Aaron Novstrup的答案相同,但使用“if-else”。我也参加了同样的课程,但我们的课程到目前为止都是关于if/else的
def balance(chars: List[Char]): Boolean = {
def balanced(chars: List[Char], open: Int): Boolean =
if (chars.isEmpty) open == 0
else if (chars.head == '(') balanced(chars.tail, open + 1)
else if (chars.head == ')') open > 0 && balanced(chars.tail, open - 1)
else balanced(chars.tail, open)
balanced(chars, 0)
}
我的解决方案
def balance(chars: List[Char]): Boolean = {
var braceStack = new Stack[Char]()
def scanItems(strList:List[Char]):Boolean = {
if(strList.isEmpty)
braceStack.isEmpty
else{
var item = strList.head
item match {
case '(' => braceStack.push(item)
scanItems(strList.tail)
case ')'=> if(braceStack.isEmpty){
false
}
else {
braceStack.pop
scanItems(strList.tail)
}
case _ => scanItems(strList.tail)
}
}
}
scanItems(chars)
}您可以使用递归来高效地解决问题,而不是使用Switch case 下面是我用递归实现的代码。您需要将我的方法的字符串转换为列表 代码:
object Balance {
def main(args: Array[String]): Unit = {
var paranthesis = "(234(3(2)s)d)" // Use your string here
println(bal(paranthesis.toList)) // converting the string to List
}
def bal(chars: List[Char]): Boolean ={
// var check = 0
def fun(chars: List[Char],numOfOpenParan: Int): Boolean = {
if(chars.isEmpty){
numOfOpenParan == 0
}
else{
val h = chars.head
val n =
if(h == '(') numOfOpenParan + 1
else if (h == ')') numOfOpenParan - 1
else numOfOpenParan
// check = check + n
if (n >= 0) fun(chars.tail,n)
else false
}
}
fun(chars,0)
}
}
添加到Vigneshwaran的答案中(包括注释和过滤不必要的信件以避免额外的递归调用):
看起来你把
(“
和”)“
:)的情况搞混了!谢谢-我已经盯着这个代码看了太久了:)本,如果你把这个作为回答,我想你应该得到你首先得到的荣誉。哈哈-我很高兴你这么认为,但我太骄傲了,不能因为这么一件小事而获得这个荣誉;)Greg K:抱歉,没有看到您的评论。在open parens案例中,您似乎需要将“count”替换为“open”。
val myStack = new Stack[Char]
def balance(chars: List[Char]): Boolean = {
def processParanthesis(x: Char, a: List[Char]): Stack[Char] = {
if (x == '(') {
myStack.push('(');
} else if (x == ')') {
if (!myStack.empty())
myStack.pop();
else
myStack.push(')');
}
if (a.length == 0)
return myStack;
else
return processParanthesis(a.head, a.tail);
}
return processParanthesis(chars.head, chars.tail).empty();
}
object Balance {
def main(args: Array[String]): Unit = {
var paranthesis = "(234(3(2)s)d)" // Use your string here
println(bal(paranthesis.toList)) // converting the string to List
}
def bal(chars: List[Char]): Boolean ={
// var check = 0
def fun(chars: List[Char],numOfOpenParan: Int): Boolean = {
if(chars.isEmpty){
numOfOpenParan == 0
}
else{
val h = chars.head
val n =
if(h == '(') numOfOpenParan + 1
else if (h == ')') numOfOpenParan - 1
else numOfOpenParan
// check = check + n
if (n >= 0) fun(chars.tail,n)
else false
}
}
fun(chars,0)
}
}
def balance(chars: List[Char]): Boolean = {
@scala.annotation.tailrec
def recurs_balance(chars: List[Char], openings: Int): Boolean = {
if (chars.isEmpty) openings == 0
else if (chars.head == '(') recurs_balance(chars.tail, openings + 1)
else openings > 0 && recurs_balance(chars.tail, openings - 1)
}
recurs_balance(chars.filter(x => x == '(' || x == ')'), 0)
}