2

I used the below code from a different thread in order to solve String Arithmetic Expressions in my Kotlin Android Application. It works most of the time, but I identified it gives an error for some expressions. Below are some of them.

((4 - 12) - 4) - 14

((9 - 7) - 19) - 4

((8 - 10) - 6) - 11

((2 - 5) * 16) - 3

((6 - 15) - 5) / 15
import kotlin.math.pow

fun basic(rightNum:String?, leftNum:String?, op:String?):Double? {
    return when (op) {
        "+" -> {
            (rightNum?.toDouble()!! + leftNum?.toDouble()!!)
        }
        "-" -> {
            (rightNum?.toDouble()!! - leftNum?.toDouble()!!)
        }
        "*" -> {
            (rightNum?.toDouble()!! * leftNum?.toDouble()!!)
        }
        "^" -> {
            ((rightNum?.toDouble()!!).pow(leftNum?.toDouble()!!))
        }
        else -> {
            (rightNum?.toDouble()!! / leftNum?.toDouble()!!)
        }
    }
}


fun elemInside(mainString:String?, listCheck:List<String>):Boolean {
    for (ops in listCheck) {
        if (mainString?.contains(ops)!!){
            return true
        }
    }
    return false
}

fun getOpIndex(query: String?, operations:List<String>):Array<Int> {
    var allIndex:Array<Int> = arrayOf()
    var dupQuery = query
    while (elemInside(dupQuery, operations)) {
        for (op in operations) {
            if (dupQuery?.contains(op)!!) {
                allIndex = allIndex.plusElement(dupQuery.indexOf(op))
                dupQuery = dupQuery.substring(0, dupQuery.indexOf(op)) + '1' + dupQuery.substring(dupQuery.indexOf(op) + 1)
            }
        }
    }

    allIndex.sort()
    return allIndex
}


fun parseSimple(query:String?):Double? {
    val operations = listOf("^", "/", "*", "-", "+")
    var allIndex: Array<Int> = arrayOf()

    var calcQuery = query
    while (elemInside(calcQuery, operations) && (allIndex.size > 1 || if (allIndex.isEmpty()) true else allIndex[0] != 0)) {
        for (op in operations) {
            calcQuery = calcQuery?.replace("-+", "-")
            calcQuery = calcQuery?.replace("--", "+")
            calcQuery = calcQuery?.replace("+-", "-")
            allIndex = getOpIndex(calcQuery, operations)
            if (calcQuery?.contains(op)!!) {
                val indexOp = calcQuery.indexOf(op)
                val indexIndexOp = allIndex.indexOf(indexOp)
                val rightIndex =
                    if (indexIndexOp == allIndex.lastIndex) calcQuery.lastIndex else allIndex[indexIndexOp + 1]
                val leftIndex = if (indexIndexOp == 0) 0 else allIndex[indexIndexOp - 1]
                val rightNum =
                    calcQuery.slice(if (rightIndex == calcQuery.lastIndex) indexOp + 1..rightIndex else indexOp + 1 until rightIndex)
                val leftNum = calcQuery.slice(if (leftIndex == 0) leftIndex until indexOp else leftIndex + 1  until indexOp)
                val result = basic(leftNum, rightNum, op)
                calcQuery = (if (leftIndex != 0) calcQuery.substring(
                    0,
                    leftIndex + 1
                ) else "") + result.toString() + (if(rightIndex != calcQuery.lastIndex) calcQuery.substring(
                    rightIndex..calcQuery.lastIndex
                ) else "")
            }
        }
    }
    return calcQuery?.toDouble()
}

fun getAllIndex(query: String?, char: Char, replacement:String="%"):List<Int> {
    var myQuery = query
    var indexes:List<Int> = listOf()
    while (char in myQuery!!) {
        val indexFinded = myQuery.indexOf(char)
        indexes = indexes.plus(indexFinded)
        myQuery = myQuery.substring(0 until indexFinded) + replacement + myQuery.substring(indexFinded+1..myQuery.lastIndex)
    }
    return indexes
}

fun getBrackets(query: String?): List<Int> {
    val allEndIndex = getAllIndex(query, ')')
    val allStartIndex = getAllIndex(query, '(')
    val firstIndex = allStartIndex[0]
    for (endIndex in allEndIndex) {
        val inBrac = query?.substring(firstIndex+1 until endIndex)
        val inBracStart = getAllIndex(inBrac, '(')
        val inBracEnd = getAllIndex(inBrac, ')')
        if (inBracStart.size == inBracEnd.size){
            return listOf(firstIndex, endIndex)
        }
    }
    return listOf(-1, -1)
}

fun evaluate(query:String?):Double? {
    var calcQuery = query
    var index = 0;
    // Check if brackets are present
    while (calcQuery?.contains('(')!! && index < 200){
        val startBrackets = getBrackets(calcQuery)[0]
        val endBrackets = getBrackets(calcQuery)[1]
        val inBrackets = calcQuery.slice(startBrackets+1 until endBrackets)
        if ('(' in inBrackets && ')' in inBrackets){
            val inBracValue = evaluate(inBrackets)
            calcQuery = calcQuery.substring(0, startBrackets) + inBracValue.toString() + (if(endBrackets == calcQuery.lastIndex) "" else calcQuery.substring(endBrackets+1..calcQuery.lastIndex))
        }
        else {
            val inBracValue = parseSimple(inBrackets)
            calcQuery = calcQuery.substring(0, startBrackets) + inBracValue.toString() + (if(endBrackets == calcQuery.lastIndex) "" else calcQuery.substring(endBrackets+1..calcQuery.lastIndex))
        }
        index++
    }

    return parseSimple(calcQuery)
}


fun main() {
    print("Enter the equation: ")
    val equation = readLine()
    println(evaluate(equation))
}

Below is the returned error.

Exception in thread "main" java.lang.NumberFormatException: empty String
 at jdk.internal.math.FloatingDecimal.readJavaFormatString (:-1) 
 at jdk.internal.math.FloatingDecimal.parseDouble (:-1) 
 at java.lang.Double.parseDouble (:-1) 

Alternatively if someone could suggest me a different method to solve arithmetic expressions in a Kotlin Android Application that would also help.

Tried this but didn’t work.

Thank you in advance.

0 Answers0