对于由字符串表示的给定化学式,计算分子中包含的每个元素的原子数并返回一个对象:Java 中的 Map
例如:
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 中有一个铁原子、两个氮原子和六个氧原子。
请注意,括号可以是圆形、方形或卷曲的,也可以是嵌套的。大括号后的索引是可选的。
本题我解得非常复杂,在我提交之后看到有更好的答案, 这里分享一下我认为不错的答案。
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"))
}