胡闹
前情提要
这周末玩了一个好玩的。
识数鸡说:“我将赋予你加、减、乘、除、乘幂、对数、整数阶乘等七种能力,同时给你四个20以内的数字作为钥匙。”
小宅懵懂地点点头。
世界上还有另外一些拥有这些能力和数字的热血少年,你需要找到他们,用你们的数字钥匙和给定的运算能力算出接近\(π\)的一个数这样你们的电脑才能逃脱Matrix的限制,得到解锁。这样你才能继续上网课还有用电脑刷b站和打游戏了。”
每人领取到的是数,不是数字,不能进行拼接等操作;每个数在公式中只能使用一次;整数阶乘是唯一允许使用的一元运算,加、减、乘、除、乘幂、对数均为二元运算,且运算限制在实数域中。
有点意思,虽然老子现在欠着一箱deadline,但爷还是开干了
我的思路
基于python强大的eval函数和高精度库,肯定要用python写了啊
然后由于是四个数,括号处理问题很复杂
画了画,发现一共有五种括号形式:
\(((AB)C)D\)
\((AB)(CD)\)
\(A((BC)D)\)
\((A(BC))D\)
\(A(B(CD))\)
那么就对这4个数的全排列依次暴力枚举就可以了
二元运算符有\(+,-,*,/,**,log\) ,需要枚举6次
单元运算符有\(fac\) ,枚举两次就可以了
细节
看似这样就结束了,但是实际上细节恶心的很
在运算时候需要加一大坨特判防止炸掉,比如在我没有加特判的情况下电脑就开始算\(16^{27!}\),变得滚烫,算了算这个数大约需要十几个TB的内存
所以就用\(try,except\) 语句一点点试,然后把那些大的离谱或者小的离谱的数直接放缩成阈值就行了。
结果
用\(1,14,16,12\)这四个数算出来的是 \(log_{1+log_{14!}16!}12\),是\(3.12014\) 左右,还是有一定差距。
然而我随便试了四个新数,就是\(3.141\) 级别的了。
果真这玩意还是拼脸
不过这是我第一次自己独立用python写代码,整个过程还是挺有趣滴~~
代码
from math import *
from itertools import permutations
pi = acos(-1)
global minn,ans
minn = 100000
ans=''
def fac(n):
res=1
if n>=100 or n<0 or abs(n-int(n))>1e-6:
return 100000000
for i in range(1,int(n)+1):
res=res*i
return res
def dyadic(a,b,op):
try:
if op == 0:
return '(' + a + '+' + b + ')'
elif op == 1:
return '(' + a + '-' + b + ')'
elif op == 2:
return '(' + a + '*' + b + ')'
elif op == 3 and eval(b)!=0:
return '(' + a + '/' + b + ')'
elif op == 3:
return '(-10000000000)'
elif op == 4 and eval(a)!=0 and (abs(eval(b))<50 and abs(eval(a))<999999) and \\
isinstance(eval(a)**eval(b),complex)==False:
return '(' + a + '**' + b + ')'
# elif op==4 and eval(b)<0 and eval(b)>-50 and abs(eval(a))>1/999999 and abs(eval(a))<999999:
# return '(' + a + '**' + b + ')'
elif op==4:
return '(-10000000000)'
elif op == 5 and eval(b)!=1 and eval(b)>0 and eval(a)>0 :
return '(log(' + a + ',' + b + '))'
else :
return '(-10000000000)'
except:
print(eval(a),eval(b),op)
def unary(a,op):
if op == 0 :
return a
else :
return '(fac('+a+'))'
def update(str):
# print(str)
now_ans = eval(str)
if(now_ans>4 or now_ans<3):
return
print(str)
print(now_ans)
global minn,ans
if abs(now_ans - pi) < abs(minn - pi):
minn = now_ans
ans = str
def Up(str):
update(unary(str,0))
update(unary(str,1))
def calc(ls):
print(ls)
for i in range(6):
for j1 in range(2):
for j2 in range(2):
tmp1=dyadic(unary(ls[0],j1),unary(ls[1],j2),i)
for k in range(6):
for l in range(2):
tmp2=dyadic(tmp1,unary(ls[2],l),k)
for m in range(6):
for n in range(2):
tmp3=dyadic(tmp2,unary(ls[3],n),m)
Up(tmp3)
for i in range(6):
for j1 in range(2):
for j2 in range(2):
tmp1 = dyadic(unary(ls[0], j1), unary(ls[1], j2), i)
for k in range(6):
for l1 in range(2):
for l2 in range(2):
tmp2 = dyadic(unary(ls[2],l1), unary(ls[3], l2), k)
for m in range(6):
tmp3 = dyadic(tmp1, tmp2, m)
Up(tmp3)
# print("jbsm")
for i in range(6):
for j1 in range(2):
for j2 in range(2):
tmp1 = dyadic(unary(ls[1], j1), unary(ls[2], j2), i)
for k in range(6):
for l in range(2):
tmp2 = dyadic(tmp1, unary(ls[3], l), k)
for m in range(6):
for n in range(2):
tmp3 = dyadic(unary(ls[0],n),tmp2, m)
Up(tmp3)
for i in range(6):
for j1 in range(2):
for j2 in range(2):
tmp1 = dyadic(unary(ls[1], j1), unary(ls[2], j2), i)
for k in range(6):
for l in range(2):
tmp2 = dyadic(unary(ls[0],l),tmp1, k)
for m in range(6):
for n in range(2):
tmp3 = dyadic(tmp2, unary(ls[3], n), m)
Up(tmp3)
for i in range(6):
for j1 in range(2):
for j2 in range(2):
tmp1 = dyadic(unary(ls[2], j1), unary(ls[3], j2), i)
for k in range(6):
for l in range(2):
tmp2 = dyadic(unary(ls[1], l), tmp1, k)
for m in range(6):
for n in range(2):
tmp3 = dyadic(unary(ls[0], n),tmp2, m)
Up(tmp3)
def main():
number=['1','12','14','16']
for i in permutations(number):
calc(i)
print(ans)
print(eval(ans))
main()