与用户输入最接近的数字

时间:2018-06-27 14:55:23

标签: python algorithm

所以我想知道是否有可能从用户那里获取3个数字,范围从1-6,并再从用户那里获取1个输入,范围从1-144,并制作一个程序来获取您获得的前3个数字并找到使用加法,减法,乘法,除法,根数和幂的方法,以使用3个数字来找到方法,以获取第4个用户输入。如果您无法获得第4个用户输入,请从前3个输入中找到最接近的输入,然后程序应告诉您使用的操作以及使用的编号。这基本上是在重新创建游戏ThinkFun Math Dice。

例如:如果用户输入的前3个数字是5、2和9,第4个数字是86,则程序应执行9 ^ 2(即81)和81 + 5(即86)。在另一种情况下, 3个数字分别是6、4和2,最后的答案是(第4个输入)24,程序应执行6 * 4 -2或6 * 4 +2或4 ^ 2 + 6,因为它们全部等于26或22,没有解决方案获得24。

2 个答案:

答案 0 :(得分:1)

问题的核心是决定使用哪种格式写出可能的计算,列出它们,尝试每个计算并选择最佳的计算。

我将建议使用RPN表示法,因为它很容易使用。我给了您代码,以RPN表示法列出了可能的计算。您仍然需要执行IO并编写RPN计算器。 IO很简单。您可以在网上学习许多RPN计算器示例。

def list_perms (args):
    if 0 == len(args):
        yield []
    else:
        x = args[0]
        for p in list_perms(args[1:]):
            for i in range(0, len(p)+1):
                yield p[:i] + [x] + p[i:]


def list_rpn (x, y, z):
    ops = ['+', '-', '*', '/', '^', 'r']
    for p in list_perms([x, y, z]):
        for op1 in ops:
            for op2 in ops:
                yield p + [op1, op2]
                yield p[0:2] + [op1, p[2], op2]

def evaluate (calc):
    return 'you have to figure this out'

def find_best (x, y, z, r):
    best_val = x+y+z
    best_calc = [x, y, z, '+', '+']
    for calc in list_rpn(5, 6, 8):
        try:
            val = evaluate(calc)
            if val == r:
                return calc
            elif abs(val - r) < abs(best_val - r): 
                best_val = val
                best_calc = calc
        except Exception:
            # Throw exceptions on things like divide by 0, or powers of
            # negative numbers that aren't n or 1/n where n is an odd number
            pass

    return best_calc

# You should also do proper IO here.
print(find_best(5, 2, 9, 24))

答案 1 :(得分:1)

尽管btilly的答案是绝对正确的,但至少比python中的问题要多得多。使用itertools库和eval()函数,您可以使用更短,更简单的方法来解决问题。请注意,eval()exec()被认为是不安全的,因为它们将执行传递的所有内容,但是作为个人使用的脚本应该没问题。任何恶意代码很可能都会触发将输入强制转换为int的异常。 从itertools导入排列中

coeffs = list(map(int, input("Coefficents, separated by spaces:\n").split()))
target = int(input("Target value:\n"))

operators = ["({}+{})","({}-{})","({}*{})","({}/{})","({}**{})","({}**(1.0/{}))"]

def make_expr(expr, coeffs, target):
    if not coeffs:
        try:
            return eval(expr), expr
        except OverflowError:
            return None
        except ArithmeticError:
            return None

    solutions =  [make_expr(op.format(expr, coeffs[0]), coeffs[1:], target) for op in operators]
    solutions += [make_expr(op.format(coeffs[0], expr), coeffs[1:], target) for op in operators]
    solutions = [x for x in solutions if x is not None]
    val, expr = min(solutions, key=lambda x: abs(x[0]-target))
    return val, expr

def find_best(coeffs, target):
    assert(len(coeffs) > 1)
    solutions = [make_expr(perm[0], perm[1:], target) for perm in permutations(coeffs)]
    solutions = [x for x in solutions if x is not None]
    val, expr = min(solutions, key=lambda x: abs(x[0]-target))
    return "Closest value: {0}\nExpression: {1}".format(val, expr)

print(find_best(coeffs, target))

要支持更多的运算符,只需将其插入列表中,并以{}作为参数,并用parethese括起来。我增加了对额外运算符的支持,但是由于在找到完美解决方案时我不会缩短迭代过程,因此3个以上的运算符可能会花费很长时间。