Вычислить n-ю итерацию полинома для определенного значения; fⁿ (х)


19

Для заданной полиномиальной функции f (например, в виде списка p действительных коэффициентов в порядке возрастания или убывания), неотрицательного целого числа n и действительного значения x вернуть:

   f n ( x )

то есть значение f ( f ( f (… f ( x )…))) для n применений f на x .

Используйте разумную точность и округление.

Решения, которые принимают f в качестве списка коэффициентов, вероятно, будут наиболее интересными, но если вы можете принять f в качестве фактической функции (тем самым сводя эту задачу к тривиальному «применить функцию n раз»), не стесняйтесь включать ее после вашего нетривиального решения.

Примеры случаев

p  = [1,0,0]или f  = x^2,  n  = 0,  x  = 3:  f 0 (3) =3

p  = [1,0,0]или f  = x^2,  n  = 1,  x  = 3:  f 1 (3) =9

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 0,  x  = 2.3:  f 0 (2.3) =2.3

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 1,  x  = 2.3:  f 1 (2.3) =-8.761

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 2,  x  = 2.3:  f 2 (2.3) =23.8258

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 3,  x  = 2.3:  f 3 (2.3) =-2.03244

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 4,  x  = 2.3:  f 4 (2.3) =1.08768

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  =5 ,  x  = 2.3:  f 5 (2.3) =-6.38336

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  =6 ,  x  = 2.3:  f 6 (2.3) =14.7565

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  =7 ,  x  = 2.3:  f 7 (2.3) =-16.1645

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  =8 ,  x  = 2.3:  f 8 (2.3) =59.3077

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 9,  x  = 2.3:  f 9 (2.3) =211.333

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 10,  x  = 2.3:  f 10 (2.3) =3976.08

p  = [0.1,-2.3,-4]или f  = 0.1x^2-2.3x-4,  n  = 11,  x  = 2.3:  f 11 (2.3) =1571775

p  = [-0.1,2.3,4]или f  = −0.1x^2+2.3x+4,  n  = 0,  x  = -1.1:  f 0 (-1.1) =-1.1

p  = [-0.1,2.3,4]или f  = −0.1x^2+2.3x+4,  n  = 1,  x  = -1.1:  f 1 (-1.1) =1.349

p  = [-0.1,2.3,4]или f  = −0.1x^2+2.3x+4,  n  = 2,  x  = -1.1:  f 2 (-1.1) =6.92072

p  = [-0.1,2.3,4]или f  = −0.1x^2+2.3x+4,  n  = 14,  x  = -1.1:  f 14 (-1.1) =15.6131

p  = [0.02,0,0,0,-0.05]или f  = 0.02x^4-0.05,  n  = 25,  x  = 0.1:  f 25 (0,1) =-0.0499999

p  = [0.02,0,-0.01,0,-0.05]или f  = 0.02x^4-0.01x^2-0.05,  n  = 100,  x  = 0.1:  f 100 (0.1) =-0.0500249



Может ли мой ответ Jelly взять ссылку Jelly и считать ее "функцией", например?
Эрик Outgolfer

@EriktheOutgolfer Первоначально я требовал ввода в виде списка коэффициентов, чтобы предотвратить такие тривиальные решения. Тем не менее, я смягчил это по запросу. Я предлагаю вам опубликовать версию списка и добавить тривиальную версию в виде заметки (или наоборот).
17

Я уже разместил список версий, но функциональная версия намного короче.
Эрик Outgolfer

@EriktheOutgolfer Да, конечно. Смотрите мою добавленную заметку.
17

Ответы:


7

октава , 49 байт

@(p,x,n)(f=@(r,m){@()p(r(r,m-1)),x}{~m+1}())(f,n)

Попробуйте онлайн!

Или, принимая коэффициенты:

Октава , 75 57 байт

@(p,x,n)(f=@(f,n){@()polyval(p,f(f,n-1)),x}{~n+1}())(f,n)

Попробуйте онлайн!

Особая благодарность Suever за StackOverflow, за этот ответ, который я некоторое время назад на мой вопрос, доказывая, что возможна рекурсивная анонимная функция.

Это определяет анонимную функцию, которая является оберткой для рекурсивной анонимной функции ; что-то, что не является родной концепцией Octave и требует некоторой необычной индексации массива ячеек.

В качестве бонуса, вторая версия - хороший урок в области видимости переменных в Octave. Все экземпляры rмогут быть законно заменены на f, которые затем просто перезаписывают существующие fв самой локальной области (аналогично для n)

объяснение

@(p,x,n)(f=@(r,m){@()p(r(r,m-1)),x}{~m+1}())(f,n)
@(p,x,n)         .                ..    .  ..   .   % Defines main anonymous function    
        (f=@(r,m).                ..    .  ).   .   % Defines recursive anonymous function
                 .                ..    .   .   .   %  r: Handle ('pointer') to recursive function
                 .                ..    .   .   .   %  m: Current recursion depth (counting from n to 0)
                 .                ..    .   (f,n)   % And call it, with
                 .                ..    .           %  r=f (handle to itself)
                 .                ..    .           %  m=n (initial recursion)
                 {                }{    }           % Create and index into cell array
                                    ~m+1            %  Index: for m>0: 1; for m==0: 2.
                                ,x                  %  Index 2: final recursion, just return x.
                  @()                               %  Index 1: define anonymous function, taking no inputs.
                     p(        )                    %   which evaluates the polynomial 
                       r(     )                     %    of the recursive function call
                         r,m-1                      %     which is called with r 
                                                    %     and recursion depth m-1 
                                                    %     (until m=0, see above)
                                         ()         % Evaluate the result of the cell array indexing operation.
                                                    %  which is either the anonymous function
                                                    %  or the constant `x`.

Ключом к этому является то, что анонимные функции не оцениваются, когда они определены. Итак, то @(), что кажется немного лишним, поскольку определяет анонимную функцию, которая вызывается ()непосредственно после, на самом деле строго необходимо. Это не называется, если он не выбран оператором индексации.

Октава , 39 байт (скучно)

function x=f(p,x,n)for i=1:n;o=p(o);end

Просто для полноты, решение Octave с самым коротким байтовым счетом. Йон. ,


Я попробую перечитать это в другой раз, но я все еще не совсем понимаю ... Как большой поклонник Октавы, я могу только сказать, отличная работа +1.
Михтан

2
@Michthan, я постараюсь дать лучшее объяснение, но это, безусловно, самая краткая октава, которую я написал - обычно имена функций составляют большинство подсчета байтов. Это почти Лисп.
Санчиз

1
@Michthan Надеюсь, новое объяснение имеет какой-то смысл, глядя на него в «взорванном» виде.
Санчиз

4

Mathematica, 56 47 28 байт

Nest[x\[Function]x#+#2&~Fold~#,##2]&

\[Function] занимает 3 байта в UTF-8.

Привести параметры в порядок p,x,n .

p (параметр 1) в порядке возрастания степени.

Очевидно, что если fэто можно принять за функцию, то это можно уменьшить только до Nest.


Вам нужно поменять коэффициенты?
Джузеппе

@Giuseppe Вот почему есть Reverseв коде.
user202729

@ user202729 Я думаю, что вы можете взять коэффициенты в любом порядке, вы хотите, либо по возрастанию, либо по убыванию.
Эрик Outgolfer

Я считаю, что мы можем принимать их в порядке увеличения или уменьшения. (Я совсем не знаю Mathematica)
Джузеппе

Да, вы можете взять их в желаемом порядке: в порядке возрастания или убывания
Adám

4

Шелуха , 5 байт

←↓¡`B

Попробуйте онлайн!

Ключевая идея здесь заключается в том, что оценка полинома в точке x эквивалентна выполнению преобразования базы из базы x .

Bпри задании базы и списка цифр выполняет конвертацию базы. Здесь мы используем его перевернутую версию, чтобы сначала взять список цифр и частично применить к нему эту функцию. Затем мы получаем функцию, которая вычисляет значение данного полинома в точке, вторая часть этого решения имеет дело с итерацией этой функции правильное количество раз:

Шелуха , 3 байта

←↓¡

¡ является функцией "iterate", она берет функцию и отправную точку и возвращает бесконечный список значений, полученных при итерации функции.

принимает число (третий аргумент этой задачи) и удаляет столько элементов с начала списка.

возвращает первый элемент полученного списка.



3

Рубин , 42 байта

->c,n,x{n.times{x=c.reduce{|s,r|s*x+r}};x}

C - список коэффициентов в порядке убывания

Тривиальная версия, где f - лямбда-функция ( 26 байт ):

->f,n,x{n.times{x=f[x]};x}

# For example:
# g=->f,n,x{n.times{x=f[x]};x}
# p g[->x{0.02*x**4-0.01*x**2-0.05},100,0.1]

Попробуйте онлайн!


3

JavaScript (ES6),  52 49 44  42 байта

Сохранено 5 байтов благодаря ГБ и еще 2 байта благодаря Нейлу

Принимает ввод в синтаксисе каррирования как (p)(n)(x), где p - список коэффициентов в порядке убывания.

p=>n=>g=x=>n--?g(p.reduce((s,v)=>s*x+v)):x

Контрольные примеры


Если p в порядке убывания, вы можете уменьшить, используя s * x + v и игнорируя i.
GB

В этом случае, вы можете опустить ,0сокращение?
Нил

@Neil Хороший улов. :-)
Арно

2

J 15 байт

0{(p.{.)^:(]{:)

Попробуйте онлайн!

Принимает полином как список коэффициентов возрастающих степеней.

объяснение

0{(p.{.)^:(]{:)  Input: polynomial P (LHS), [x, n] (RHS)
            {:   Tail of [x, n], gets n
           ]     Right identity, passes n
  (    )^:       Repeat n times starting with g = [x, n]
     {.            Head of g
   p.              Evaluate P at that value
                   Return g = [P(head(g))]
0{               Return the value at index 0

2

05AB1E , 10 9 байтов

-1 байт благодаря Эрику Аутгольферу

sF³gݨm*O

Попробуйте онлайн!

Принимает x в качестве первого аргумента, n в качестве второго и p в порядке возрастания в качестве третьего.

объяснение

sF³gݨm*O
s         # Forces the top two input arguments to get pushed and swaped on the stack
 F        # Do n times...
  ³        # Push the third input (the coefficients)
   g       # Get the length of that array...
    ݨ     # and create the range [0 ... length]
      m    # Take the result of the last iteration to these powers (it's just x for the first iteration)
       *   # Multiply the resuling array with the corresponding coefficients
         O # Sum the contents of the array
          # Implicit print

1
Вы можете удалить второй ³.
Эрик Outgolfer

Также (This is in case n is 0 so x is on the stack)это неправильно, вам все еще нужно sдля ненулевого n.
Эрик Outgolfer

Да, это правда. Я больше думал о замене ¹².with, sчтобы он выполнял задачу передачи x в стек за 1 байт без необходимости зацикливания хотя бы один раз. Наверное, следовало бы сказать, что лучше ^^ '. Также спасибо за -1!
Датбой

Я имел в виду, что он вам все еще нужен, поскольку 05AB1E использует последний ввод для неявного ввода, если все входные данные были прочитаны.
Эрик Outgolfer

" sF³gݨm³O" и в объяснении тоже ...
Эрик Outgolfer

2

Haskell , 15 байт

((!!).).iterate

Попробуйте онлайн!

Спасибо полностью человеческому за 11 байтов от обоих решений

Это определяет неявную функцию, которая принимает функцию в качестве первого аргумента и n второго аргумента и создает эту функцию для себя nраз. Затем его можно вызвать с аргументом, xчтобы получить окончательное значение. Благодаря магии карри это эквивалентно одной функции, принимающей три аргумента.


Взять список коэффициентов вместо аргумента функции:

Haskell , 53 байта

((!!).).iterate.(\p x->sum$zipWith(*)p[x^i|i<-[0..]])

Попробуйте онлайн!

Это то же самое, что и приведенный выше код, но состоит из лямбда-функции, которая преобразует список коэффициентов в полиномиальную функцию. Коэффициенты взяты в обратном порядке из примеров - в качестве возрастающих степеней x.



TIO из второго следует взять список в качестве аргумента, а не функции;) Хотя вы можете сохранить несколько байтов, используя сгиб как этого (заметим , что нулевой многочлен может не быть , []но должно быть что - то вроде [0]или подобное ).
ბიმო

2

APL (Dyalog) , 20 9 байтов

{⊥∘⍵⍣⎕⊢⍺}

Попробуйте онлайн!

Это принимает xв качестве левого аргумента, коэффициенты функции в качестве правого аргумента и nиз STDIN.

Оглядываясь на это спустя много времени, я понял, что могу упростить вычисления, используя базовое преобразование .


APL (Dyalog), 5 байтов

Если мы можем принять функцию как функцию Dyalog APL, то это может быть 5 байтов.

⎕⍣⎕⊢⎕

Принимает x, nа затем функцию ввода от STDIN.


2

R , 96 58 55 52 байт

f=function(n,p,x)`if`(n,f(n-1,p,x^(seq(p)-1)%*%p),x)

Попробуйте онлайн!

Объяснение:

seq(p)генерирует список, 1, 2, ..., length(p)когда pявляется вектором, так же seq(p)-1как и экспоненты полинома, следовательно x^(seq(p)-1), эквивалентен x^0(всегда равен 1), , x^1, x^2, ...и вычисление точечного произведения %*%с pвычислением полинома вx .

Кроме того, если Pвзять в качестве функции, то это будет 38 байтов:

function(n,P,x)`if`(n,f(n-1,P,P(x)),x)

И мы можем, конечно , всегда генерируют PпутемP=function(a)function(x)sum(x^(seq(a)-1)*a)



1

Python 3 , 70 69 байт

f=lambda p,n,x:n and f(p,n-1,sum(c*x**i for i,c in enumerate(p)))or x

Принимает pв порядке возрастания, т.е. если pis, [0, 1, 2]то соответствующий многочлен is p(x) = 0 + 1*x + 2*x^2. Простое рекурсивное решение.

Попробуйте онлайн!


1

C # (.NET Core) , 82 байта

using System.Linq;f=(p,n,x)=>n<1?x:p.Select((c,i)=>c*Math.Pow(f(p,n-1,x),i)).Sum()

Попробуйте онлайн!

Принимает список коэффициентов в порядке, противоположном тестовым примерам (в порядке возрастания?), Так что их индекс в массиве равен степени x, на которую следует повысить.

И тривиальная версия в 30 байтов:

f=(p,n,x)=>n<1?x:f(p,n-1,p(x))

Попробуйте онлайн!

Принимает делегата и применяет его рекурсивно n раз.


1

MATL , 11 байт

ii:"ZQ6Mw]&

Попробуйте онлайн!

Чуть менее интересный, чем мой ответ на Octave, хотя я думаю, что есть некоторые хитрые манипуляции с входными данными, чтобы убедиться, что они n=0работают, как ожидалось.


1

Юлия 0.6.0 (78 байт)

using Polynomials;g(a,n,x)=(p=Poly(a);(n>0&&(return g(a,n-1,p(x)))||return x))

Explainations:

Пакет Полиномы довольно понятен: он создает многочлены. После этого это довольно простая рекурсия.

Чтобы иметь многочлен: -4.0 - 2.3 * x + 0.1 * x ^ 2, вход aдолжен быть похож наa = [-4, -2.3, 0.1]


1

Аксиома, 91 байт

f(n,g,x)==(for i in 1..n repeat(v:=1;r:=0;for j in 1..#g repeat(r:=r+v*g.j;v:=v*x);x:=r);x)

изрезанный

fn(n,g,x)==
     for i in 1..n repeat
          v:=1; r:=0
          for j in 1..#g repeat(r:=r+v*g.j;v:=v*x)
          x:=r
     x

На входе для полинома г это один список чисел, обратный примеру упражнения. например

[1,2,3,4,5]  

это будет представлять полиномию

1+2*x+3*x^2+4*x^3+5*x^4

тестовое задание:

(3) -> f(0,[0,0,1],3)
   (3)  3
                                                    Type: PositiveInteger
(4) -> f(1,[0,0,1],3)
   (4)  9
                                                    Type: PositiveInteger
(5) -> f(0,[-4,-2.30,0.1],2.3)
   (5)  2.3
                                                              Type: Float
(6) -> f(1,[-4,-2.30,0.1],2.3)
   (6)  - 8.7610000000 000000001
                                                              Type: Float
(7) -> f(2,[-4,-2.30,0.1],2.3)
   (7)  23.8258121
                                                              Type: Float
(8) -> f(9,[-4,-2.30,0.1],2.3)
   (8)  211.3326335688 2052491
                                                              Type: Float
(9) -> f(9,[-4,-2.30,0.1,0,0,0,0,1],2.3)
   (9)  0.4224800431 1790652974 E 14531759
                                                              Type: Float
                                   Time: 0.03 (EV) + 0.12 (OT) = 0.15 sec
(10) -> f(2,[-4,-2.30,0.1,0,0,0,0,1],2.3)
   (10)  44199336 8495528344.36
                                                              Type: Float


1

C ++ 14, 71 байт

Как общая безымянная лямбда, возвращающаяся через xпараметр:

[](auto C,int n,auto&x){for(auto t=x;t=0,n--;x=t)for(auto a:C)t=a+x*t;}

Ungolfed и testcase:

#include<iostream>
#include<vector>

using namespace std;

auto f=
[](auto C,int n,auto&x){
 for(
  auto t=x; //init temporary to same type as x
  t=0, n--; //=0 at loop start, also check n
  x=t       //apply the result
  )
  for(auto a:C)
   t=a+x*t; //Horner-Scheme
}
;


int main() {
 vector<double> C = {0.1,-2.3,-4};//{1,0,0};
 for (int i = 0; i < 10; ++i) {
  double x=2.3;
  f(C, i, x);
  cout << i << ": " << x << endl;
 }
}

0

QBIC , 19 байт

[:|:=:*c^2+:*c+:}?c

Принимает входные данные как

  • Количество итераций
  • начальное значение х
  • Тогда 3 части полинома

Образец вывода:

Command line: 8 2.3 0.1 -2.3 -4
 59.30772

0

Clojure, 66 байт

#(nth(iterate(fn[v](apply +(map *(iterate(partial * v)1)%3)))%2)%)

Полный пример:

(def f #(nth(iterate(fn[v](apply +(map *(iterate(partial * v)1)%3)))%2)%))
(f 10 2.3 [-4 -2.3 0.1])
; 3976.0831439050253

Составление функции составляет 26 байтов:

#(apply comp(repeat % %2))

(def f #(apply comp(repeat % %2)))
((f 10 #(apply + (map * [-4 -2.3 0.1] (iterate (partial * %) 1)))) 2.3)
; 3976.0831439050253

0

Japt , 18 байт

Довольно просто, делает то, что говорит вызов на жестяной банке.

o r_VË*ZpVÊ-EÉÃx}W
o                  // Take `n` and turn it into a range [0,n).
  r_            }W // Reduce over the range with initial value of `x`.
    VË             // On each iteration, map over `p`, yielding the item
      *Z           // times the current reduced value
        pVÊ-EÉ     // to the correct power,
              Ãx   // returning the sum of the results.

Принимает входные сигналы в порядке n, p, x.

Попробуйте онлайн!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.