Программа итерационного поиска

от автора

Введение

Как-то возникла необходимость быстро восстановить ход решения одной задачи. Т.е. у меня был набор входных данных и полученные результаты. Хотелось быстро найти алгоритмы, по которому были получены все ответы. Я попытался написать программу-подсказчик.

Что было сделано

Начал я с малого — создал на python 2.7 программу, находящую по заданному частному делимое и делитель. Простым перебором. Затем добавил умножение, вычитание и деление, что пригодилось на поздних этапах. На данном этапе программа уже умела определить, что число 0.428571428571 получено путем 3/7.
Добавил (скорее для тестов) возможность вводить как число, так и функцию.
Позже добавил стандартные иррациональности. Программа находила, что 0.785398163397 было получено из pi/4.

Вот версия 4.6:

# -*- 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)

Версия 5.1:

# -*- 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.Знаете ли вы более удобные аналоги программы?

image
image

ссылка на оригинал статьи http://habrahabr.ru/post/184556/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *