Codewars第十三天–Simplifying multilinear polynomials
题目描述:
当我们上中学时被要求简化数学表达式,如“3x-yx + 2xy-x”(或通常更大),这很容易(“2x + xy”)。但告诉你的电脑,我们会看到!
写一个函数:
简化(聚)
在输入中取一个字符串,表示整数系数中的多线性非常数多项式(如“3x-zx + 2xy-x”),并返回另一个字符串作为输出,其中相同的表达式已按以下方式简化( - >表示简化的应用):
已经完成了等价单项式(“xy == yx”)的所有可能的和和减法,例如:
“cb + cba” - >“bc + abc”,“2xy-yx” - >“xy”,“ - a + 5ab + 3a-c-2a” - >“ - c + 5ab”
所有单项式都按变量数量的增加顺序出现,例如:
“-abc + 3a + 2ac” - >“3a + 2ac-abc”,“xyz-xz” - >“ - xz + xyz”
如果两个单项式具有相同数量的变量,则它们以字典顺序出现,例如:
“a + ca-ab” - >“a-ab + ac”,“xzy + zby” - >“byz + xyz”
如果第一个系数是正数,则没有前导+符号,例如:
“-y + x” - >“x-y”,但没有限制 - :“y-x” - >“ - x + y”
注:为了保持最简单,输入中的字符串被限制为仅表示多线性非常数多项式,因此您将找不到类似“-3 + yx ^ 2”的内容。在这种情况下,多线性意味着:每个变量的度数为1。
这个题目看起来不难,我们需要将每一个单项式的符号,数字和字符串分开来,符号和数字结合,对字符串进行排序,使用字典 来存储,key为字符串,对应的value就为对应的符号加数字的值,遍历所以的单项式,如果存在字典中,就改变value值,不存在就直接加入到字典即可。
最后还需要考虑输出格式的问题。需要按照单项式长度,以及value的大小来按顺序输出。
import re
def simplify(poly):
terms = {}
``` 将输入的多项式按照符号、数字、字母使用正则表达式将他们分割开来
并对他们使用不同的方法进行处理:
符号:如果符号为‘-’,则将其变为‘-1’,如果为‘+’,则赋值为‘1’ 数字:如果数字存在,则直接同符号相乘,如果不存在则使用1同符号相乘。
字母:对每一组字符串进行排序。这里使用join,是因为排序后的结果是一个列表,而我们需要的是一个字符串。需要使用join将他们链接为一个字符串。
构建一个字典terms,将字母作为keys,coef作为values想对应添加到字典中。这里在添加的同时使用了terms.get()来判断某一个key,也就是某一个单项式字母是否已经存在于字典中了。如果存在就将他们相加。不存在则添加该值。
最后对字典中的元素进行排序。使用两个key来进行排序:第一个是keys的长度从小到大排序,如果长度相同,则使用values进行排序,同样的按照从小到大的方式。
这一系列操作过后,我们的字典中已经有了计算好的多项式的结果,现在需要将他们链接起来返回简化后的多项式。使用format_term函数来对每一个item进行映射。
format_term()函数:对字典中的每一个item进行判断,如果item的values为0,则返回‘’也就是空,如果为1,则返回‘+’+ key。如果为-1,则返回‘-’+key,其他情况,则返回‘+’+ values + key。将每一个结果使用join链接起来就得到了最后的结果。并且需要移除头尾多出来的‘+’。
```
for sign, coef, vars in re.findall(r'([\-+]?)(\d*)([a-z]*)', poly):
sign = (-1 if sign == '-' else 1)
coef = sign * int(coef or 1)
vars = ''.join(sorted(vars))
terms[vars] = terms.get(vars, 0) + coef
# 通过字符串长度和,value大小对字典进行排序。
terms = sorted(terms.items(), key=lambda (v, c): (len(v), v))
return ''.join(map(format_term, terms)).strip('+')
def format_term((vars, coef)):
if coef == 0:
return ''
if coef == 1:
return '+' + vars
if coef == -1:
return '-' + vars
return '%+i%s' % (coef, vars)