취미로 주식하는 사람인 L씨는 어느날 자신이 투자한 한 종목에 조작이 있음을 직감하였다. 약간의 계산 후 그는 주가가 어떤 고차 다항함수를 따라서 움직인다고 추정하였다. 만약 그 다항함수를 구할 수 있다면 L은 부자가 될 게 명백했다.
L씨를 도와서 2개 이상의 좌표가 주어지면, 그 좌표를 모두 지나는 최소 차수의 다항함수를 출력하는 프로그램을 만들어라.
*다항함수:x^2+x+1 따위를 의미한다. 이 때 x^2에서 2를 차수라고 하며 차수는 0이상의 정수여야 한다.
ex.(1,1), (2,2)가 주어지면 y=x
7개의 풀이가 있습니다.
파이썬 입니다
from itertools import combinations
n=input("좌표 개수를 입력하세요\n")
if int(n)<=1:
exit()
location_list_x=[]
location_list_y=[]
for k in range(int(n)):
temp_location_x=float(input("x좌표를 입력하세요\n")) #입력하고자하는 좌표가 (1,2)라면 여기서 1 다음줄에서 2 이렇게 했습니다
temp_location_y=float(input('y좌표를 입력하세요\n'))
location_list_x.append(temp_location_x)
location_list_y.append(temp_location_y)
degree_list=[] #리스트에 n-1차계수,n-2차계수,.....1차,0차 이런 순서로 저장할려고 이렇게 했습니다
for l in range(int(n)): #라그랑주 보간법 이용해서 다항식 구하는 과정
degree_list.append(0)
for i in range(int(n)):
temp_denominator=1
for_combination=[]
for j in range(int(n)):
if i==j:
continue
temp_denominator*=((location_list_x[i])-(location_list_x[j]))
for_combination.append((location_list_x[j]))
for g in range(int(n)):
if temp_denominator==0:
degree_list[g]=0
continue
if g==0:
degree_list[g]+=((location_list_y[i])/temp_denominator)
continue
comb=combinations(for_combination,g)
temp_sum=0
if g==1: # ex) (x-a)(x-b)(x-c) 계수 1 다음 a+b+c 다음 ab+bc+ca일때 만약 a,b,c중에 0포함고려
for a in comb:
temp_sum+=sum(a)
if g>=2:
for f in comb:
num=1
for b in f:
num*=b
temp_sum+=num
degree_list[g]+=((-1)**(g))*(location_list_y[i])/temp_denominator*temp_sum #여기서 다항식 구하는 과정 끝
ans_str ="y=" #출력하는 과정(출력시 계수가 실수로 나오는데 입력값이 실수일때를 고려했습니다.. )
for c in range(int(n)):
if c==(int(n)-1) and degree_list[c]>0:
ans_str+="+%s"%(degree_list[-1])
break
elif c==(int(n)-1) and degree_list[c]<0:
ans_str+="%s"%(degree_list[-1])
break
elif c==(int(n)-1) and degree_list[c]==0:
break
elif degree_list[c]>0:
ans_str+= "+%sx^%s" % ((degree_list[c]), (int(n)-1 - c))
elif degree_list[c]==0:
continue
else:
ans_str += "%sx^%s" % ((degree_list[c]), (int(n)-1 - c))
print(ans_str)
exit()
파이썬 3.6
import sympy
def inputdata():
p = int(input('▶ 좌표의 개수를 입력하세요: '))
data,x,y = [],0,0
for i in range(p):
x,y = map(float,input('').split())
data.append([x,y])
return data
def polynomialfunc(data):
n = len(data)
x = sympy.Symbol('x')
l,L = 1,0
for i in range(n):
for h in range(n):
if i == h:
pass
else:
l *= (x-data[h][0])/(data[i][0]-data[h][0])
L += data[i][1]*l
l = 1
print(sympy.expand(L))
if __name__ == "__main__":
data = inputdata()
print(data)
polynomialfunc(data)
# y = tan(x) 그래프상의 점들에 대한 다항식
▶ 좌표의 개수를 입력하세요: 5
-1.5 -14.1014
-0.75 -0.931596
0 0
0.75 0.931596
1.5 14.1014
[[-1.5, -14.1014], [-0.75, -0.931596], [0.0, 0.0], [0.75, 0.931596], [1.5, 14.1014]]
L(x) = 4.83484760493827*x**3 - 1.47747377777778*x
▶ 좌표의 개수를 입력하세요: 2
1 1
2 2
[[1.0, 1.0], [2.0, 2.0]]
L(x) = 1.0*x
이 문제를 통해 sympy 모듈을 처음 다뤄보았습니다. 좋은 문제 공유 감사합니다. 실행속도가 빠르지 않은데 어떻게 개선할 수 있을까요?
from sympy import *
def lagrange(a):
result = 0
x = Symbol('x')
for i in range(len(a)):
l = a[i][1]
for j in range(len(a)):
if i == j:
pass
else:
l *= (x - a[j][0]) / (a[i][0] - a[j][0])
result += expand(l)
return result
a = list()
while 1:
n = input()
if n == '':
break
else:
a.append(list(map(float, n.split())))
print(lagrange(a))
from functools import reduce
def calc_polynomial(a,b):
return ((i[0]+j[0],i[1]*j[1]) for i in a for j in b)
def Lagrange(coordinate):
LagrangeEq = []
result = []
solution = {}
for i in range(len(coordinate)): solution[i] = 0
x = [i[0] for i in coordinate]
y = [i[1] for i in coordinate]
for i in range(len(coordinate)):
LagrangeEq += [[((0, y[i]/reduce(lambda t1, t2: t1*t2, (x[i]-x[j] for j in range(len(coordinate)) if i != j))),)]]
LagrangeEq[-1] += tuple(((1,1),(0,-x[j])) for j in range(len(coordinate)) if i != j)
for i in LagrangeEq:
result += reduce(lambda t1,t2:calc_polynomial(t1,t2),i)
for i in result:
solution[i[0]] += i[1]
return solution
# 좌표 입력
coord = set()
while 1:
temp = input('(x,y) 형태로 좌표 입력(입력종료는 엔터): ')
if temp == '': break
coord.add(eval(temp))
# 라그랑주 계산
Lcalc = Lagrange(coord)
# 출력
print('\n다항식: ',end='')
for i in range(len(coord)-1,0,-1):
if Lcalc[i] == 0: continue
if i == 1: print('{}x + '.format(Lcalc[i]),end='')
else: print('{}x^{} + '.format(Lcalc[i],i),end='')
print(Lcalc[0])
(x,y) 형태로 좌표 입력(입력종료는 엔터): 1,1
(x,y) 형태로 좌표 입력(입력종료는 엔터): 2,7
(x,y) 형태로 좌표 입력(입력종료는 엔터): 0,1
(x,y) 형태로 좌표 입력(입력종료는 엔터):
다항식: 3.0x^2 + -3.0x + 1.0
(x,y) 형태로 좌표 입력(입력종료는 엔터): 23,58
(x,y) 형태로 좌표 입력(입력종료는 엔터): 12,84
(x,y) 형태로 좌표 입력(입력종료는 엔터): -23.3242,-23.234
(x,y) 형태로 좌표 입력(입력종료는 엔터): 0,0
(x,y) 형태로 좌표 입력(입력종료는 엔터): -12,1
(x,y) 형태로 좌표 입력(입력종료는 엔터):
다항식: -0.0006717455457842552x^4 + -0.004614238543956924x^3 + 0.39187024748182164x^2 + 4.12278368366313x + 0.0
#다항함수 구하기
import numpy.linalg as lin
n=int(input('좌표의 수 입력:'))
x=[]
y=[]
for i in range(1,n+1):
print('번호: ',i)
xn=int(input('x좌표 입력: '))
x.append(xn)
yn=int(input('y좌표 입력: '))
y.append(yn)
print('x좌표',x)
print('y좌표',y)
#2차원 배열(Vandermonde Matrix)
def matrix2(x):
xx=[]#전체
for i in range(0,n):
xx2=[]#각 행
for j in range(0,n):
xx1=x[i]**j
xx2.append(xx1)
xx.append(xx2)
return xx
xx=matrix2(x)
#xx는 Vandermonde Matrix
#역행렬 구하기
inxx=lin.inv(xx)
k=[]#다항식의 계수
for i in range(0,n):
kk=0
for j in range(0,n):
kk+=inxx[[i],[j]]*y[j]
k.append(kk)
print('다항식의 계수(상수항,x,x^2,...x^(n-1) 순으로): ',k)
#구하는 다항식은 k[0]+k[1]*x+k[2]*x^2+k[3]*x^3+....+k[n-1]*x^(n-1)이다.
import sympy
import re
inp_com, inp_LIST = re.compile("([-]?\d*\.?\d+)"), []
x, inter, kou = Symbol('x'), [], []
while True :
inp_LIST.append(inp_com.findall(input("INPUT(\'-.1\' to quit) : ")))
if inp_LIST[-1] == ['-.1'] :
del inp_LIST[-1]
break
print(inp_LIST)
for i in range(0, len(inp_LIST)) :
for m in range(1, len(inp_LIST)) :
inter.append('((x-%s)/(%s-%s))'% (inp_LIST[(i+m)%len(inp_LIST)][0], inp_LIST[i][0], inp_LIST[(i+m)%len(inp_LIST)][0] ))
kou.append("*".join(inter)+'*'+str(inp_LIST[i][1]))
inter = []
print('y=', sympy.expand(('+'.join(kou))))
먼저 풀이를 적어주신 분들의 답을 참고삼아 라그랑주 보간법으로 풀었습니다. sympy는 처음 써보는데 매트랩의 심볼릭 툴박스가 생각나네요
** 조금 난잡해 보이기도 하고 결과예시가 너무 단순해 보여서 조금 수정했습니다.
결과
INPUT('-.1' to quit) : 2 0
INPUT('-.1' to quit) : 1 0
INPUT('-.1' to quit) : 3 2
INPUT('-.1' to quit) : -1 6
INPUT('-.1' to quit) : -.1
[['2', '0'], ['1', '0'], ['3', '2'], ['-1', '6']]
y= x**2 - 3*x + 2
from future.moves import itertools
def getCoordinates():
N = int(input('좌표 갯수는? '))
cp = []
for n in range(N):
x, y = map(int, input('{}번째 x y 좌표는: '.format(n+1)).split())
cp.append([x,y])
return cp
def nthCoefficient(cp, coef):
nth = len(cp)
co = []
for i in range(nth):
a = cp[i][1]
ad = 1
for j in range(nth):
if not i == j:
ad *= (cp[i][0] - cp[j][0])
co.append(a / ad)
coef.append(co)
def lowthCoefficient(nth, cp, coef):
idx = [i for i in range(nth)]
for i in range(1, nth):
Cb = itertools.combinations(idx, i)
lst = list(Cb)
tmp = []
for j in range(nth):
for l in range(len(lst)):
if not j in lst[l]:
b = 1
for k in lst[l]:
b *= (-cp[k][0])
tmp.append(b * coef[0][j])
coef.append(tmp)
def printFunction(nth, res):
y = ''
index = nth
for n in res:
if n == 0:
continue
elif n == 1 or n == -1:
if n == 1:
y += ' + x**' + str(nth)
else:
y += ' - x**' + str(nth)
else:
if n > 0:
y += ' + ' + str(n) + ' x**' + str(nth)
else:
y += ' - ' + str(abs(n)) + ' x**' + str(nth)
nth -= 1
print('\n y = ', y)
cp = getCoordinates()
coef = []
nthCoefficient(cp, coef)
lowthCoefficient(len(cp), cp, coef)
allCoef = []
for co in coef:
allCoef.append(sum(co))
print(allCoef)
printFunction(len(cp) - 1, allCoef)