どう書く.org課題「化学反応式の完成」をgroovyでそこはかとなく解いてみました。
Groovyには2つのリストを処理できるリスト処理(Haskellでいうzip関数みたいなもの)が無いことに気づいた。不便だ。実装がArrayListだとあまり効率よく処理できないとは思うが。
インデックス付きのcollectみたいなの(collectWithIndex?)があればせめて良いのだけど。
O = ["O"] Mg = ["Mg"] C = ["C"] H = ["H"] O2 = O*2 H2 = H*2 C2 = C*2 MgO = Mg + O CO2 = C + O2 H2O = H2 + O MAX=5 def expand(list, mult) { def result = [] list.eachWithIndex { it, idx -> result += it * mult[idx] } return result.sort() } def printAnswer(list, mult) { list.eachWithIndex { it, idx -> print mult[idx]==1?"":mult[idx] print it.join().replaceAll(/(.)\1/, '$12') if (idx != list.size()-1) { print " + " } } } def resolv(pre, post) { preanswers = (([1..MAX]*pre.size()).combinations()) postanswers = (([1..MAX]*post.size()).combinations()) ([preanswers,postanswers].combinations()).grep { expand(pre, it[0]) == expand(post, it[1]) }.each { printAnswer(pre, it[0]) print " ==> " printAnswer(post, it[1]) println(); } } resolv([Mg, O2], [MgO]) // 以下が出力される // 2Mg + O2 ==> 2MgO // 4Mg + 2O2 ==> 4MgO resolv([C2, H2, O2], [CO2, H2O]) // 以下が出力される // C2 + 2H2 + 3O2 ==> 2CO2 + 2H2O // 2C2 + 2H2 + 5O2 ==> 4CO2 + 2H2O // C2 + 4H2 + 4O2 ==> 2CO2 + 4H2O