kotlin完成 Code War 题目 解析分子公式

题目

对于由字符串表示的给定化学式,计算分子中包含的每个元素的原子数并返回一个对象:Java 中的 Map<String,Integer>。

例如:

var water = 'H2O';
parseMolecule(water); // return {H: 2, O: 1}

var magnesiumHydroxide = 'Mg(OH)2';
parseMolecule(magnesiumHydroxide); // return {Mg: 1, O: 2, H: 2}

var fremySalt = 'K4[ON(SO3)2]2';
parseMolecule(fremySalt); // return {K: 4, O: 14, N: 2, S: 4}

如您所见,某些公式中包含括号。括号外的索引告诉您,您必须在该索引上乘以括号内每个原子的计数。例如,在 Fe(NO3)2 中有一个铁原子、两个氮原子和六个氧原子。

请注意,括号可以是圆形、方形或卷曲的,也可以是嵌套的。大括号后的索引是可选的。

本题我解得非常复杂,在我提交之后看到有更好的答案, 这里分享一下我认为不错的答案。

解题思路

  • 逆向for循环公式
    • 这样的话,只需要用大写字母做结束符
  • 使用list作为栈来解决括号带来的叠加问题
  • 使用正则来判断是否合法

解题代码:

fun getAtomsRepeat(formula: String):Map<String, Int>{
    val counter = mutableMapOf<String, Int>()
    var atom = ""
    var digit = ""
    val numbers = mutableListOf(1)
    
    if ("\\{\\w*[\\]\\)]|\\(\\w*[\\]\\}]|\\[\\w*[\\}\\)]".toRegex().containsMatchIn(formula) ||
        formula.replace("\\w".toRegex(), "").length % 2 != 0) throw IllegalArgumentException()

    for(char in formula.reversed()){
        when{
            char in listOf(')', ']', '}') -> {
                numbers.add(digit.toIntOrNull()?:1)
                digit = ""
            }
            char in listOf('(','[', '{') -> numbers.removeAt(numbers.lastIndex)
            char.isDigit() -> digit = "$char$digit"
            char.isLowerCase() -> atom = "$char$atom"
            char.isUpperCase() ->{
                atom = "$char$atom"
                val number = numbers.reduce(Int::times) * (digit.toIntOrNull()?:1)
                counter[atom] = counter[atom]?.let { it+number }?:number
                digit = ""
                atom = ""
            }
        }
        println("当前char:$char atom:$atom numbers:$numbers digit:$digit counter:${counter}")
    }
    return counter
}

fun main() {
    println(getAtomsRepeat("As2{Be4C5[BCo3(CO2)3]2}4Cu15"))
//    println(getAtomsRepeat(")5"))
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值