Поліномацепція


22

З огляду на два поліноми f,gдовільної міри над цілими числами, ваша програма / функція повинна оцінювати перший многочлен у другому многочлені. f(g(x))(він же склад (fog)(x) двох поліномів)

Деталі

Вбудовані дозволені. Ви можете вважати будь-яке розумне форматування як вхід / вихід, але формат введення та виведення повинен збігатися. Наприклад, форматування як рядок

x^2+3x+5

або як перелік коефіцієнтів:

[1,3,5] or alternatively [5,3,1]

Крім того, можна вважати, що вхідні поліноми будуть повністю розширені, і очікується також, що результати будуть повністю розширені.

Приклади

A(x) = x^2 + 3x + 5, B(y) = y+1
A(B(y)) = (y+1)^2 + 3(y+1) + 5 = y^2 + 5y + 9

A(x) = x^6 + x^2 + 1, B(y) = y^2 - y
A(B(y))= y^12 - 6y^11 + 15y^10 - 20y^9 + 15y^8 - 6y^7 + y^6 + y^4 - 2 y^3 + y^2 + 1

A(x) = 24x^3 - 144x^2 + 288x - 192, B(y) = y + 2
A(B(y)) = 24y^3

A(x) = 3x^4 - 36x^3 + 138x^2 - 180x + 27, B(y) = 2y + 3
A(B(y)) = 48y^4 - 96y^2

що з вбудованими?
Мальтісен

1
@Maltysen "Подробиці: Будинки дозволені. (...)" : D
недолік

2
Я думаю, що "будь-який розумний формат" може бути трохи розтяжним. Якщо функція, яка оцінює поліном, дозволена, то функція композиції (.)- це відповідь у Haskell. Ви, мабуть, маєте на увазі деяке представлення списку коефіцієнтів.
xnor

1
Заголовок! Я щойно зрозумів :-D
Луїс Мендо

2
@LuisMendo Quick thinker = P
flawr

Відповіді:


10

Haskell, 86 72 байти

u!c=foldr1((.u).zipWith(+).(++[0,0..])).map c
o g=(0:)!((<$>g).(*))!pure

Визначає таку функцію o, яка o g fобчислює склад f ∘ g. Поліноми представлені непорожнім списком коефіцієнтів, починаючи з постійного члена.

Демо

*Main> o [1,1] [5,3,1]
[9,5,1]
*Main> o [0,-1,1] [1,0,1,0,0,0,1]
[1,0,1,-2,1,0,1,-6,15,-20,15,-6,1]
*Main> o [2,1] [-192,288,-144,24]
[0,0,0,24]
*Main> o [3,2] [27,-180,138,-36,3]
[0,0,-96,0,48]

Як це працює

Ніяких поліноміальних вбудованих або бібліотек. Спостерігайте подібні рецидиви

f (x) = a + f₁ (x) x ⇒ f (x) g (x) = ag (x) + f₁ (x) g (x) x,
f (x) = a + f₁ (x) x ⇒ f (g (x)) = a + f₁ (g (x)) g (x),

для поліномного множення і складу відповідно. Вони обидва приймають форму

f (x) = a + f₁ (x) x ⇒ W (f) (x) = C (a) (x) + U (W (f₁)) (x).

Оператор !вирішує повтор цієї форми для W, заданих U і C, використовуючи zipWith(+).(++[0,0..])для додавання поліномів (якщо припустити, що другий аргумент довший - для наших цілей це завжди буде). Потім,

(0:)помножує многочлен аргумент на x (попередньо додавши нульовий коефіцієнт);
(<$>g).(*)помножує скалярний аргумент на поліном g;
(0:)!((<$>g).(*))помножує многочлен аргумент на поліном g;
pureпідводить скалярний аргумент до постійного многочлена (одинарний список);
(0:)!((<$>g).(*))!pureскладає поліноміальний аргумент з поліномом g.


9

Математика, 17 байт

Expand[#/.x->#2]&

Приклад використання:

In[17]:= Expand[#/.x->#2]& [27 - 180x + 138x^2 - 36x^3 + 3x^4, 3 + 2x]

              2       4
Out[17]= -96 x  + 48 x

7

TI-Basic 68 к, 12 байт

a|x=b→f(a,b)

Використання просте, наприклад для першого прикладу:

f(x^2+3x+5,y+1)

Який повертається

y^2+5y+9

Мені здається, що мені підман вимагає, щоб вхідні дані були в різних змінних. Чи має значення ця відповідь?
feersum

Не соромтеся це робити, я прямо дозволив будь-який розумний зручний формат введення.
недолік

Щодо редагування вашого коментаря: так, це має значення.
flawr

Я не надто знайомий з правилами на цьому сайті. Чи правильно 1 байт у TI-BASIC?
asmeurer

@asmeurer Дійсно: TI-Basic оцінюється кодуванням, яке використовується на відповідних калькуляторах. Якщо вас цікавлять деталі, ви можете прочитати це тут на мета . Таблицю жетонів можна знайти тут на ti-basic-dev .
flawr

6

Python 2, 138 156 162 байт

Очікується, що спочатку дані будуть цілими списками з найменшими потужностями.

def c(a,b):
 g=lambda p,q:q>[]and q[0]+p*g(p,q[1:]);B=99**len(`a+b`);s=g(g(B,b),a);o=[]
 while s:o+=(s+B/2)%B-B/2,;s=(s-o[-1])/B
 return o

Безголівки:

def c(a,b):
 B=sum(map(abs,a+b))**len(a+b)**2
 w=sum(B**i*x for i,x in enumerate(b))
 s=sum(w**i*x for i,x in enumerate(a))
 o=[]
 while s:o+=min(s%B,s%B-B,key=abs),; s=(s-o[-1])/B
 return o

У цьому обчисленні коефіцієнти поліномів розглядаються як цифри (які можуть бути негативними) числа в дуже великій основі. Після того, як поліноми знаходяться в такому форматі, множення або додавання - це ціла ціла операція. Поки база достатньо велика, не буде жодних носіїв, які переливаються на сусідні цифри.

-18 від покращення, пов'язаного з Bпропозицією @xnor.


Хороший метод. Бо B, чи 10**len(`a+b`)вистачило б?
xnor

@xnor Можливо ... мені важко сказати.
feersum

+1 Це дійсно креативне рішення та приємне використання bigints !!!
flawr

@xnor Тепер мені вдалося переконати себе, що довжина коефіцієнта hte лінійна у вхідній довжині :)
feersum

5

Python + SymPy, 59 35 байт

from sympy import*
var('x')
compose

Дякуємо @asmeurer за те, що виграли 24 байти!

Тестовий запуск

>>> from sympy import*
>>> var('x')
x
>>> f = compose
>>> f(x**2 + 3*x + 5, x + 1)
x**2 + 5*x + 9

1
SymPy має compose()функцію.
асмеурер

1
Де відповідь? Він більше не визначає жодних функцій і нічого не робить ...
feersum

1
@feersum Це ніколи не було. Ви щойно відредагували цю мета-публікацію.
Мего

3
@feersum Ви відредагували прийняте мета-повідомлення, щоб змінити політику для вашого порядку денного. Це не нормально.
Мего

3
@feersum Хоча, можливо, ви думали, що ваше формулювання було неоднозначним, воно, очевидно, не було для решти громади. Ми прийняли консенсус, який from module import*;functionбув дійсним поданням. Незважаючи на це , це більш пізня політика, яка дозволяє імпортувати та допоміжні функції з неназваними лямбдами.
Мего

3

Шавлія, 24 байти

lambda A,B:A(B).expand()

Станом на Sage 6.9 (версія, що працює на http://sagecell.sagemath.org) ), виклики функцій без явного призначення аргументів ( f(2) rather than f(x=2)) спричиняють надрукування і непридатне повідомлення для друку на STDERR. Оскільки STDERR можна ігнорувати за замовчуванням у коді гольфу, це все ще справедливо.

Це дуже схоже на відповідь Денніса SymPy, тому що Sage a) побудований на Python, і b) використовує Maxima , систему комп’ютерної алгебри, дуже схожу на SymPy. Однак Sage набагато потужніший, ніж Python із SymPy, і, таким чином, є достатньо іншою мовою, на яку він заслуговує власної відповіді.

Перевірте всі тестові випадки в Інтернеті


2

PARI / GP , 19 байт

(a,b)->subst(a,x,b)

що дозволяє вам робити

%(x^2+1,x^2+x-1)

отримати

% 2 = x ^ 4 + 2 * x ^ 3 - x ^ 2 - 2 * x + 2


1

MATLAB з символічною панеллю інструментів, 28 байт

@(f,g)collect(subs(f,'x',g))

Це анонімна функція. Щоб зателефонувати, призначте його змінній або використовуйте ans. Введення - це рядки з форматом (пробіли необов’язкові)

x^2 + 3*x + 5

Приклад виконання:

>> @(f,g)collect(subs(f,'x',g))
ans = 
    @(f,g)collect(subs(f,'x',g))
>> ans('3*x^4 - 36*x^3 + 138*x^2 - 180*x + 27','2*x + 3')
ans =
48*x^4 - 96*x^2

1

Python 2, 239 232 223 байт

r=range
e=reduce
a=lambda*l:map(lambda x,y:(x or 0)+(y or 0),*l)
m=lambda p,q:[sum((p+k*[0])[i]*(q+k*[0])[k-i]for i in r(k+1))for k in r(len(p+q)-1)]
o=lambda f,g:e(a,[e(m,[[c]]+[g]*k)for k,c in enumerate(f)])

"Правильна" реалізація, яка не зловживає основами. Найменше значущий коефіцієнт.

aє поліноміальним складанням, mє множинним поліном і oє складом.


Хіба m([c],e(m,[[1]]+[g]*k))не те саме, що e(m,[[c]]+[g]*k)?
Ніл

@Neil Добрий дзвінок, може розігнати двох в одному з цим!
orlp

a=lambda*l:map(lambda x,y:(x or 0)+(y or 0),*l)
Андерс Касеорг

@AndersKaseorg Правильно, я додав це, дякую :)
orlp

Можливо, можна спростити додавання поліномів, оскільки я думаю, що один список завжди буде довшим, ніж інший, тому ( or 0)в цій версії вам не потрібно .
Ніл

1

JavaScript (ES6), 150 103 байт

(f,g)=>f.map(n=>r=p.map((m,i)=>(g.map((n,j)=>p[j+=i]=m*n+(p[j]||0)),m*n+(r[i]||0)),p=[]),r=[],p=[1])&&r

Приймає та повертає многочлени як масив a = [a 0 , a 1 , a 2 , ...], який представляє 0 + a 1 * x + a 2 * x 2 ...

Редагувати: Збережено 47 байт шляхом переходу з рекурсивного на ітераційне множення поліномів, що дозволило мені об'єднати два mapвиклики.

Пояснення: r - результат, який починається з нуля, представлений порожнім масивом, а p - g h , який починається з одиниці. p помножується на кожну f h по черзі, а результат, накопичений у r . p також множиться на g одночасно.

(f,g)=>f.map(n=>            Loop through each term of f (n = f[h])
 r=p.map((m,i)=>(           Loop through each term of p (m = p[i])
  g.map((n,j)=>             Loop though each term of g (n = g[j])
   p[j+=i]=m*n+(p[j]||0)),  Accumulate p*g in p
  m*n+(r[i]||0)),           Meanwhile add p[i]*f[h] to r[i]
  p=[]),                    Reset p to 0 each loop to calculate p*g
 r=[],                      Initialise r to 0
 p=[1]                      Initialise p to 1
)&&r                        Return the result


1

Ruby 2,4 + многочлен , 41 + 12 = 53 байти

Використовує прапор -rpolynomial. Вхід - два Polynomialоб'єкти.

Якщо хтось перевершить мене у ванільній Рубі (немає зовнішньої бібліотеки поліномів), я буду дуже вражений.

->a,b{i=-1;a.coefs.map{|c|c*b**i+=1}.sum}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.