import yaml import pkgutil def load(path, withNumbers=True): """ 功能:从当前工作目录中加载 YAML 数据库 输入:路径 path 输出:yaml 解析器加载后的数据 """ return yaml.load(open(path, encoding='utf-8'), Loader=yaml.SafeLoader if withNumbers else yaml.BaseLoader) def loadFromPackage(path, withNumbers=True): """ 功能:从模块包中加载 YAML 数据库 输入:路径 path 输出:yaml 解析器加载后的数据 """ return yaml.load(pkgutil.get_data(__package__, path).decode(), Loader=yaml.SafeLoader if withNumbers else yaml.BaseLoader) def checkCompleteness(strokeDict): """ 功能:检查笔画定义完整性 输入:笔画定义字典 strokeDict 形如{type:[strokes]} 输出:缺失笔画列 lostStrokes 形如 [strokes] """ allstrokes = [ '横', '提', '竖', '竖钩', '撇', '点', '捺', '横钩', '横撇', '横折', '横折钩', '横斜钩', '横折提', '横折折', '横折弯', '横撇弯钩', '横折弯钩', '横折折撇', '横折折折', '横折折折钩', '竖提', '竖折', '竖弯', '竖弯钩', '竖折撇', '竖折折钩', '竖折折', '撇点', '撇折', '弯钩', '斜钩' ] strokeCategory = {} # 读取用户对笔画的大类进行的自定义 for category, strokeTypeList in strokeDict.items(): for strokeType in strokeTypeList: strokeCategory[strokeType] = category # 校验是否所有单笔画都有定义 lostStrokes = [x for x in allstrokes if x not in strokeCategory] return lostStrokes def expand(indexList): """ 功能:展开形如 [1, ..., 6] 的省略式的笔画索引列 输入:笔画索引列 indexList 输入:展开后的笔画索引列 returnList ,形如 [1, 2, 3, 4, 5, 6] """ if '...' in indexList: splitList = [list(map(int, x.split(' '))) for x in (' '.join(map(str, indexList))).split(' ... ')] returnList = splitList[0] for n in range(len(splitList) - 1): startNum = splitList[n][-1] stopNum = splitList[n+1][0] returnList.extend(list(range(startNum + 1, stopNum))) returnList.extend(splitList[n+1]) else: returnList = list(map(int, indexList)) return returnList def nextRoot(n): """ 功能:给定字未拆完的部分,求拆出下一个字根的所有可能性 输入:数 n 输出:在数的二进制表示中左边第一位取 1 ,其余所有「1」的位上取 1 或取 0 的所有可能的数的列表 备注:一个含有n笔的字可用一个十进制数2**n-1表达其笔画状态 例如一个3笔的字可以用7来表示,其对应二进值是111 对于字的任意切片,可同理表示,上字含首末笔的切片为101,对应十进值为5 以下算法基于位运算 """ powerList = [0] while n: # 直到当前序列所有「1」位都被置0之前,做: # 找到右边第一个「1」,如1110010的右二位,将其置0,得余待检序列1110000 t = n & (n-1) # 当前序列扣除余待检序列,获得当前位及其右边所有位,1110010-1110000=10 m = n - t # 将余待检序列设为当前序列,用于下一loop n = t # 对列表中每一个已有位扩增当前位「1」,并以此列表扩增原列表 powerList = powerList + [x + m for x in powerList] # 当前位的「0」选项,将会在下一位「1」扩增时扩增 # 将所有不足笔数长度的序列剔除,表明所取切片必含输入切片的第一笔 return powerList[len(powerList)//2:]