Введение
Как-то возникла необходимость быстро восстановить ход решения одной задачи. Т.е. у меня был набор входных данных и полученные результаты. Хотелось быстро найти алгоритмы, по которому были получены все ответы. Я попытался написать программу-подсказчик.
Что было сделано
Начал я с малого — создал на python 2.7
программу, находящую по заданному частному делимое и делитель. Простым перебором. Затем добавил умножение, вычитание и деление, что пригодилось на поздних этапах. На данном этапе программа уже умела определить, что число 0.428571428571 получено путем 3/7.
Добавил (скорее для тестов) возможность вводить как число, так и функцию.
Позже добавил стандартные иррациональности. Программа находила, что 0.785398163397 было получено из pi/4.
# -*- coding: cp1251 -*-
#Concatenate 3.2.py+2.3.py
#==========================
#Программа для нахождения записи введенного вами числа
#как отношения двух целых чисел либо
#как функции целого числа.
#
#поддерживаемые функции:
#'sqrt(y)','exp(y)','log(y)','log10(y)','y**(1/3)','y**2','y**3','2**y','log2(y)'
from math import *
print ('For example: c=? (0.3752*sqrt(3.0)+exp(2.0))/cos(pi/4.0)-2.0**(-2.0)')
#print ('Use 0<c<9802' for 'a=range(1,101)')
c = float(input ('c=? '))
print 'c =',c
#Проверка отрицательности:
c1=0
if c<0: #Будем работать с положительными числами. Учтем это в логарифмах.
c=-c
c1=-1
#==========================
z=0 #индикатор
integer=[float(i) for i in range(1,101)]
i=0
while i<len(integer):
if c==integer[i]:
z=1 #индикатор
print 'integer'
i+=1
#==========================
#Add 2.3.py
"""
##all variables:
##a, b, c, d, e, j, i, f, g, h, k, l, m, n, e1, l1
##aa, bb, cc, dd, ee, jj, ii, ff, gg, hh, kk, ll, mm, nn, ee1, ll1
##p,q,
##r
"""
#import math
#from math import *
#
#Division
#used variables: a, b, c, d, e, j, i, e1. (7 items) (j and i are iteration's variables)
#c = float(raw_input('c=? '))
#print ('For example: c=? (0.3752*sqrt(3)+exp(2))/cos(pi/4)-2**(-2)')
#print ('Use 0<c<9802' for 'a=range(1,100)')
#c = input ('c=? ')
a=range(1,101) #1.you may change here. 'a=change(1,l1)' or 'a=change(1,1001)'
b=a = [float(i) for i in a]
i=0
d=1.1
e=[]
while i<len(a):
j=0
while j<len(b):
if abs(a[i]/b[j]-c)< d:
d=abs(a[i]/b[j]-c)
e.append([a[i],'/',b[j],'=',a[i]/b[j],'Error =',d])
e1=a[i]/b[j]
j+= 1
i+=1
"print e[-1]"
#====================
#Complication
#used variables: f, g, h, k, l, m, n, l1 (7 items)
"h = float(raw_input('h=? '))"
h=c
f=a
#f=range(0,101) #you may stay 'f=range(1,11)' or 'f=range(1,1001)'
g=f = [float(n) for n in f]
n=0
k=1.1
l=[]
while n<len(f):
m=0
while m<len(g):
if abs(f[n]*g[m]-h)< k:
k=abs(f[n]*g[m]-h)
l.append([f[n],'*',g[m],'=',f[n]*g[m],'Error =',k])
l1=f[n]*g[m]
m+= 1
n+=1
"print l[-1]"
#=================
#Addittion
#added variables: aa, bb, cc, dd, ee, jj, ii, ee1 (7 items)
"cc = float(raw_input('cc=? '))"
cc=c
aa=a
#aa=range(0,101) #you may stay 'aa=range(1,11)' or 'aa=range(1,1001)'
bb=aa = [float(ii) for ii in aa]
ii=0
dd=1.1
ee=[]
while ii<len(aa):
jj=0
while jj<len(bb):
if abs(aa[ii]+bb[jj]-cc)< dd:
dd=abs(aa[ii]+bb[jj]-cc)
ee.append([aa[ii],'+',bb[jj],'=',aa[ii]+bb[jj],'Error =',dd])
ee1=aa[ii]+bb[jj]
jj+= 1
ii+=1
"print ee[-1]"
#=================
#subtraction
#used variables: ff, gg, hh, kk, ll, mm, nn, ll1 (7 items)
"hh = float(raw_input('hh=? '))"
hh=c
ff=a
#ff=range(0,101) #you may stay 'ff=range(1,11)' or 'ff=range(1,1001)'
gg=ff = [float(nn) for nn in ff]
nn=0
kk=1.1
ll=[]
while nn<len(ff):
mm=0
while mm<len(gg):
if abs(ff[nn]-gg[mm]-hh)< kk:
kk=abs(ff[nn]-gg[mm]-hh)
ll.append([ff[nn],'-',gg[mm],'=',ff[nn]-gg[mm],'Error =',kk])
ll1=ff[nn]-gg[mm]
mm+= 1
nn+=1
"print ll[-1]"
#=================
#comparision.
#used variables: p,q
#print 'c =',c
p=min(d,k,dd,kk)
if p==d:
q=e[-1]
#print q
if p==k:
q=l[-1]
#print q
if p==dd:
q=ee[-1]
#print q
if p==kk:
q=ll[-1]
#print q
#print q
#for 4.0:
pp=p
qq=q
if c1==-1:
qq=['-']+qq
#=================================================================================
#=================================================================================
#Add 3.2.py
i=0
a = [float(i) for i in range(1,11)]
f=[sqrt(i) for i in a]
g=[exp(i) for i in a]
if c==-1:
m=[1.0/log[i] for i in a]
else:
m=[log(i) for i in a]
if c==-1:
n=[1.0/log10(i) for i in a]
else:
n=[log10(i) for i in a]
p=[i**(1/3.0) for i in a]
q=[i**2.0 for i in a]
s=[i**3.0 for i in a]
t=[2.0**i for i in a]
if c==-1:
u=[1.0/log(i,2) for i in a]
else:
u=[log(i,2) for i in a]
v=[(sqrt(5.0)+1.0)/2.0,pi/6.0,pi/4.0,pi/3.0,pi/2.0,pi,pi*3/2.0,pi*2.0,1/3.0,1/2.0]
#v=[pi*i for i in vpi]
h=a+f+g+m+n+p+q+s+t+u+v
i=0
r=10.1
while i <len(h):
if c>0:
if abs(c-h[i])<r:
k=h[i]
b=i
r=abs(c-h[i])
i+=1
#=======================================================
if z==0:
if abs(h[b]-c)<=pp:
if 0<=b<=9:
pass
#print 'Integer'
elif 10<=b<=19:
print 'sqrt(y)'
elif 20<=b<=29:
print 'exp(y)'
elif 30<=b<=39:
print 'log(y)'
elif 40<=b<=49:
print 'log10(y)'
elif 50<=b<=59:
print 'y**(1/3)'
elif 60<=b<=69:
print 'y**2'
elif 70<=b<=79:
print 'y**3'
elif 80<=b<=89:
print '2**y'
elif 90<=b<=99:
print 'log2(y)'
elif b==100:
print 'fi=(sqrt(5)+1)/2'
elif b==101:
print 'pi/6'
elif b==102:
print 'pi/4'
elif b==103:
print 'pi/3'
elif b==104:
print 'pi/2'
elif b==105:
print 'pi'
elif b==106:
print '3*pi/2'
elif b==107:
print '2*pi'
elif b==108:
print '1/3'
elif b==109:
print '1/2'
if 0<=b<=9:
bb=b
elif 10<=b<=99:
bb=b%10
elif 100<=b<=1000:
bb=b%100
if not 100<=b<=109:
print 'y =',bb+1
if c1==-1:
print '-f(y)=','-',h[b]
else:
print 'f(y)=',h[b]
print 'Error=',abs(h[b]-c)
else:
print qq
Следующим шагом добавил вторую итерацию — полученный массив данных на первом этапе проходил повторный прогон.
Программа находила по заданному 3.69314718056 искомые 3+log(2)
# -*- coding: cp1251 -*-
#iteration 2 step
from math import *
#--------------
#This version have MemoryError
#0 iteration
c = float(input ('c=? '))
#c=1/sqrt(2)
print 'c =',c
c1=1 #индикатор знака по умолчанию положителен.
if c<0:
c=-c
c1=-1 #индикатор знака - изменен на отрицательный.
k=10
#-1 iteration
z1=range(1,11)
z2=[]
z2=[pi,exp(1)]
z3=[]
z3=[sqrt(2),sqrt(3)]
z4=[]
z4=[sqrt(2)/2.0, sqrt(3)/2.0]
z5=[2**(1/3.0),3**(1/3.0)]
if c>=1:
z6=[log(2),log10(2)]
else:
z6=[-log(1/2.0),-log10(1/2.0)]
z=z1
z234=z2+z3+z4+z5+z6
if c1>=1:
z2345=['pi','exp(1)','sqrt(2)','sqrt(3)','sqrt(2)/2.0', 'sqrt(3)/2.0', '2**(1/3.0)','3**(1/3.0)','log(2)','log10(2)']
else:
z2345=['pi','exp(1)','sqrt(2)','sqrt(3)','sqrt(2)/2.0', 'sqrt(3)/2.0', '2**(1/3.0)','3**(1/3.0)','-log(1/2.0)','-log10(1/2.0)']
#z=z1+z234
a=z
#print len(a)
#0 iteration
b=a = [float(i) for i in a]
i=0
adivb=[]
while i<len(a):
j=0
while j<len(b):
ab=a[i]/b[j]
adivb.append(ab)
j+= 1
i+=1
#sqrt1=[sqrt(i) for i in a]
#exp1=[sqrt(i) for i in a]
#print len(adivb)
#-------------
#1 iteration
i=0
adivb1=[]
acomplb1=[]
asumb1=[]
asubb1=[]
a1=adivb
b1=z234
while i<len(a1):
j=0
while j<len(b1):
ab1=a1[i]/b1[j] #div
#adivb1.append(ab1)
if abs(ab1-c)<k:
k=abs(ab1-c)
q='/'
p=j
r=i
g=[a1[i],'/',z2345[j]]
# g=[a1[i],'/',b1[j]]
ax1=a1[i]*b1[j] #compl
#acomplb1.append(ax1)
if abs(ax1-c)<k:
k=abs(ax1-c)
q='*'
p=j
r=i
g=[a1[i],'*',z2345[j]]
# g=[a1[i],'*',b1[j]]
ay1=a1[i]+b1[j] #sum
#asumb1.append(ay1)
if abs(ay1-c)<k:
k=abs(ay1-c)
q='+'
p=j
r=i
g=[a1[i],'+',z2345[j]]
# g=[a1[i],'+',b1[j]]
az1=a1[i]-b1[j] #subtraction
#asubb1.append(az1)
if abs(az1-c)<k:
k=abs(az1-c)
q='-'
p=j
r=i
g=[a1[i],'-',z2345[j]]
# g=[a1[i],'-',b1[j]]
j+= 1
i+=1
#print r,k,p,z234[p]
print g
#-----------------------
#aabb=adivb1+acomplb1+asumb1+asubb1
#print len(aabb)
#-------------------------
#print "----------------------------"
"""
i=0
k=10
while i<len(aabb):
if abs(aabb[i]-c)<k:
k=abs(aabb[i]-c)
kk=i
i+=1
#print 'c = ',c
#print 'index =',kk
#print 'ближайшее значение =',aabb[kk]
#print 'k =',k #error
if kk>9:
bb=(kk)%10
if 0<=kk<=9:
print '1','/',kk+1
elif 10<=kk<=19:
print '2','/',bb+1
elif 20<=kk<=29:
print '3','/',bb+1
elif 30<=kk<=39:
print '4','/',bb+1
elif 40<=kk<=49:
print '5','/',bb+1
elif 50<=kk<=59:
print '6','/',bb+1
elif 60<=kk<=69:
print '7','/',bb+1
elif 70<=kk<=79:
print '8','/',bb+1
elif 80<=kk<=89:
print '9','/',bb+1
elif 90<=kk<=99:
print '10','/',bb+1
"""
#-------
#if c1>=1:
# z234=[pi,exp(1),sqrt(2),sqrt(3),sqrt(2)/2.0, sqrt(3)/2.0, 2**(1/3.0),3**(1/3.0),log(2),log10(2)]
#else:
# z234=[pi,exp(1),sqrt(2),sqrt(3),sqrt(2)/2.0, sqrt(3)/2.0, 2**(1/3.0),3**(1/3.0),-log(1/2.0),-log10(1/2.0)]
"""
#1 iteration
if kk>99:
bb=(kk)%100
if 0<=kk<=99:
pass
elif 100<=kk<=199:
print '1','/','(','1','/',kk+1,')'
elif 200<=kk<=299:
print '1','/','(','2','/',bb+1,')'
elif 300<=kk<=399:
print '1','/','(','3','/',bb+1,')'
elif 400<=kk<=499:
print '1','/','(','4','/',bb+1,')'
elif 500<=kk<=599:
print '1','/','(','5','/',bb+1,')'
elif 600<=kk<=690:
print '1','/','(','6','/',bb+1,')'
elif 700<=kk<=799:
print '1','/','(','7','/',bb+1,')'
elif 800<=kk<=899:
print '1','/','(','8','/',bb+1,')'
elif 900<=kk<=999:
print '1','/','(','9','/',bb+1,')'
elif 1000<=kk<=1099:
print '1','/','(','9','/',bb+1,')'
"""
К сожалению на 3-ю итерацию памяти питона уже не хватало. Поэтому находить по заданному 10.007106781 искомые 3+sqrt(2)*5 уже не получится. Оно и понятно, чудес не бывает.
Что хотелось реализовать, но сделано не было
1.Сервис не выложен в интернет.
2.Хотелось все-таки преодолеть лимит памяти в 2 действия.
3.Дать пользователю самому вводить область поиска — т.е. используемые значения. К примеру, если в тестовой задаче дано 6 конкретных чисел, то нет смысла использовать все натуральные и иррациональные числа, а достаточно оперировать только этими значениями.
(Другое дело, что этих значений может быть недостаточно — от пользователя могут потребоваться общие знания. Например, при заданных значениях длины и ширины прямоугольника, пользователь должен знать о удвоении этих величин при вычислении периметра. Программа-же заранее знать о назначении величин не может. Либо опять-таки надо добавлять к введенным пользователем величинам набор натуральных значений от 1 до 10 плюс стандартные иррациональности.)
4.Даже если пользователь получит все алгоритмы всех тестовых ответов, он все равно не знает, какой из них правильный. Хотя тут уже вопрос к пользователю, а не к программе-подсказчику.
Где можно применять
1.При решении простых тестовых задач по математике, физике.
2.Там, где требуется установить зависимости между входными и выходными данными.
Вопросы к читателям:
1.Будете ли вы при необходимости пользоваться программой (бесплатно, на сайте, где есть немного рекламы)?
2.Стоит ли добавлять нереализованные возможности?
3.Знаете ли вы более удобные аналоги программы?
Автор: Michael134096