import math mc_colors = [ ['红色染料', '#B02E26', 'red'], ['绿色染料', '#5E7C16', 'green'], ['紫色染料', '#8932B8', 'purple'], ['青色染料', '#169C9C', 'cyan'], ['淡灰色染料', '#9D9D97', 'silver'], ['灰色染料', '#474F52', 'gray'], ['粉红色染料', '#F38BAA', 'pink'], ['黄绿色染料', '#80C71F', 'lime'], ['黄色染料', '#FED83D', 'yellow'], ['淡蓝色染料', '#3AB3DA', 'lightBlue'], ['品红色染料', '#C74EBD', 'magenta'], ['橙色染料', '#F9801D', 'orange'], ['黑色染料', '#1D1D21', 'black'], ['棕色染料', '#835432', 'brown'], ['蓝色染料', '#3C44AA', 'blue'], ['白色染料', '#F9FFFE', 'white'] ] def parse_mc_color(colors): parsed_color = {} for color in colors: name, value, key = color value = value.strip('#') assert len(value) == 6 r = int(value[:2], base=16) g = int(value[2:4], base=16) b = int(value[4:], base=16) parsed_color[key] = { "name": name, "key": key, "value": [r, g, b] } return parsed_color mc_colors = parse_mc_color(mc_colors) def calculate_fused_color(counts): num_colors = sum(counts.values()) if num_colors == 0: return [160, 101, 64] avg_color = [] # calculate total color. for i in range(3): this_total_color = sum([mc_colors[key]['value'][i]*count for key, count in counts.items()]) avg_color.append(this_total_color//num_colors) # calculate average maximum. average_maximum = 0 for key, count in counts.items(): average_maximum += max(mc_colors[key]['value']) * count average_maximum //= num_colors # calculate gain factor. maximum_of_average = max(avg_color) gain_factor = average_maximum / maximum_of_average # generate result. fused = [int(x * gain_factor) for x in avg_color] return fused def calculate_diff_color(c1, c2): return sum([abs(x - y) for x, y in zip(c1, c2)]) def calculate_multipler(diff): diff = 256 if diff > 256 else diff multiplier = (1 - (0.50) * (256.0 - diff) / 256.0); return multiplier * math.log(80) / math.log(125) def export_recipe(recipe): return ', '.join(['{0}:{1}'.format(mc_colors[key]['name'], recipe[key]) for key in recipe if recipe[key] > 0]) def find_best_color(luckycolor, limit=1): min_diff = 10000 best_recipe = None best_color = None avaliable_colors = list(mc_colors.keys()) current_stat = [0] * len(avaliable_colors) search_space = (limit+1)**len(current_stat) print('正在搜索 {0} 种可能的组合'.format(search_space)) def get_next_stat(curent_stat): digit = limit + 1 multipiler = 1 value = 0 # encode for stat in current_stat[::-1]: value += stat * multipiler multipiler *= digit # add value += 1 # decode. if value >= digit**len(current_stat): return None next_stat = [] while value > 0: this_digit = value % digit value = value // digit next_stat.append(this_digit) next_stat += [0] * (len(current_stat) - len(next_stat)) return next_stat[::-1] searched = 0 while current_stat is not None: this_color = {key:value for key, value in zip(avaliable_colors, current_stat)} fused_color = calculate_fused_color(this_color) diff_color = calculate_diff_color(luckycolor, fused_color) if diff_color < min_diff: min_diff = diff_color best_recipe = this_color best_color = fused_color current_stat = get_next_stat(current_stat) searched += 1 if searched % 10000 == 0: print('[进度:{0}%]{1}/{2} 已完成, 当前最小误差为: {3}, 此时配方为: {4}'.format( "%.2f"%(searched*100/search_space), searched, search_space, min_diff, export_recipe(best_recipe) )) return min_diff, best_recipe, best_color if __name__ == '__main__': luckycolor = None limit = 1 while luckycolor is None: note = '\n'.join( [ '请输入你的幸运色,用空格分隔。', '如你的幸运色为100, 200, 100, 请输入 100 200 100。', '默认每一种颜色采用的最大数量为1,若你希望用更多的颜色,可以在幸运色后追加一个数字表示每种颜色最大使用的颜色数量,如 100 200 100 2 表示每种颜色最多使用两个', '不建议指定超过两个以上的颜色,所需的搜索空间可能过大导致无法在可接受的时间范围内计算完成,如一种颜色搜索空间为2^16=65536种组合,两种为3^16=43046721种组合。' ]) print(note) try: luckycolor_str = input('>>> ') luckycolor = luckycolor_str.split() luckycolor = [int(x) for x in luckycolor] if len(luckycolor) < 3 or len(luckycolor) > 4: raise ValueError if len(luckycolor) == 4: limit = luckycolor[3] except Exception: print('幸运色颜色格式错误qwq') min_diff, best_recipe, best_color = find_best_color(luckycolor, limit=limit) print('搜索完成!') print('=================================') print('你的幸运色为:', luckycolor) print('最小颜色误差:', min_diff) print('最佳配方:', export_recipe(best_recipe)) print('由此配方获得的幸运色:', best_color) print('当穿着单件衣服时伤害减免为:', calculate_multipler(min_diff)) print('当穿着全套衣服时伤害减免为:', calculate_multipler(min_diff)**4) print('=================================')