From abbab157fd7926f05c7081f5848f46eaa42ed93e Mon Sep 17 00:00:00 2001 From: mingyang Date: Wed, 22 Jun 2022 14:07:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20'find=5Fmy=5Fluckycolor.py?= =?UTF-8?q?'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- find_my_luckycolor.py | 156 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 find_my_luckycolor.py diff --git a/find_my_luckycolor.py b/find_my_luckycolor.py new file mode 100644 index 0000000..9f333d3 --- /dev/null +++ b/find_my_luckycolor.py @@ -0,0 +1,156 @@ +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('=================================')