Calcola l'ennesima iterata di un polinomio per un valore specifico; fⁿ (x)


19

Data una funzione polinomiale f (ad esempio come un elenco p di coefficienti reali in ordine crescente o decrescente), un numero intero non negativo n e un valore reale x , restituisce:

   f n ( x )

cioè il valore di f ( f ( f (… f ( x )…))) per n applicazioni di f su x .

Usa precisione e arrotondamenti ragionevoli.

Le soluzioni che prendono f come un elenco di coefficienti saranno probabilmente le più interessanti, ma se sei in grado di prendere f come una funzione reale (riducendo così questa sfida al banale "applica una funzione n volte"), sentiti libero di includerla dopo la tua soluzione non banale.

Casi di esempio

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

p  = [-0.1,2.3,4]o 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]o 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]o f  = 0.02x^4-0.01x^2-0.05,  n  = 100,  x  = 0.1:  f 100 (0.1) =-0.0500249



La mia risposta Jelly può prendere un collegamento Jelly e considerarlo una "funzione", per esempio?
Erik the Outgolfer

@EriktheOutgolfer Inizialmente avevo bisogno di input come elenco di coefficienti per evitare soluzioni così banali. Tuttavia, l'ho rilassato su richiesta. Ti suggerisco di pubblicare la versione dell'elenco e di aggiungere la versione banale come nota (o opposta).
Adám,

Ho già pubblicato la versione dell'elenco, ma la versione della funzione è molto più breve.
Erik the Outgolfer

@EriktheOutgolfer Sì, ovviamente. Vedi la mia nota aggiunta.
Adám,

Risposte:


7

Ottava , 49 byte

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

Provalo online!

Oppure, prendendo i coefficienti:

Ottava , 75 57 byte

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

Provalo online!

Un ringraziamento speciale per Suever a StackOverflow, per questa risposta qualche tempo fa su una mia domanda, dimostrando che una funzione anonima ricorsiva è possibile.

Questo definisce una funzione anonima, che è un wrapper per una funzione anonima ricorsiva ; qualcosa che non è un concetto nativo di Ottava e richiede un po 'di indicizzazione di array di celle.

Come bonus, la seconda versione è una bella lezione di scoping variabile in Octave. Tutte le istanze di rpossono essere legalmente sostituite da f, che quindi sovrascrive semplicemente quelle esistenti fnell'ambito più locale (simile per n)

Spiegazione

@(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`.

La chiave di ciò è che le funzioni anonime non vengono valutate quando vengono definite. Quindi, il @(), che sembra un po 'superfluo poiché definisce una funzione anonima che viene chiamata ()subito dopo, è in realtà strettamente necessario. Non viene chiamato a meno che non sia selezionato dall'istruzione di indicizzazione.

Ottava , 39 byte (modo noioso)

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

Solo per completezza, la soluzione Octave con il byte più breve. Sbadiglio. .


Proverò a rileggerlo un'altra volta, ma non riesco ancora a capirlo. Come grande fan di Octave posso solo dire, ottimo lavoro +1.
Michthan,

2
@Michthan proverò a fare una spiegazione migliore, ma è di gran lunga l'ottava più concisa che ho scritto - di solito, i nomi delle funzioni sono la maggior parte del conteggio dei byte. È quasi Lisp.
Sanchises,

1
@Michthan Speriamo che la nuova spiegazione abbia un senso, guardandola in una vista "esplosa".
Sanchises,

4

Mathematica, 56 47 28 byte

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

\[Function] richiede 3 byte in UTF-8.

Prendi i parametri in ordine p,x,n.

p (parametro 1) è in ordine crescente di grado.

Ovviamente se fpuò essere preso come una funzione, questo può essere ridotto solo a Nest.


Devi invertire i coefficienti?
Giuseppe,

@Giuseppe Ecco perché c'è Reversenel codice.
user202729

@ user202729 Penso che tu possa prendere i coefficienti nell'ordine che vuoi, sia in ordine crescente che decrescente.
Erik the Outgolfer

Ci è permesso di prenderli in ordine crescente o decrescente di grado, credo. (Non conosco affatto Mathematica)
Giuseppe,

Sì, puoi prenderli nell'ordine desiderato: in
Adám

4

Buccia , 5 byte

←↓¡`B

Provalo online!

L'idea chiave qui è quella di valutare un polinomio ad un certo punto x equivale all'esecuzione della conversione di base dalla base x .

Bquando viene fornita una base e un elenco di cifre esegue la conversione di base. Qui usiamo la sua versione capovolta, per prendere prima l'elenco delle cifre e applicare parzialmente questa funzione ad essa. Otteniamo quindi una funzione che calcola il valore del polinomio dato in un punto, la seconda parte di questa soluzione si occupa di ripetere questa funzione il numero di volte corretto:

Buccia , 3 byte

←↓¡

¡ è la funzione "iterazione", prende una funzione e un punto di partenza e restituisce la lista infinita di valori ottenuti ripetendo la funzione.

accetta un numero (il terzo argomento di questa sfida) e rilascia molti elementi dall'inizio dell'elenco.

restituisce il primo elemento dell'elenco risultante.



3

Rubino , 42 byte

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

C è l'elenco dei coefficienti in ordine decrescente

Versione di prova, dove f è una funzione lambda ( 26 byte ):

->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]

Provalo online!


3

JavaScript (ES6),  52 49 44  42 byte

Risparmiato 5 byte grazie a GB e altri 2 byte grazie a Neil

Accetta input nella sintassi del curry come (p)(n)(x), dove p è l'elenco dei coefficienti in ordine decrescente.

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

Casi test


Se p è in ordine decrescente, è possibile ridurre utilizzando s * x + v e ignorare i.
GB

In tal caso, puoi omettere ,0di ridurre?
Neil,

@Neil Buona cattura. :-)
Arnauld

2

J , 15 byte

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

Provalo online!

Prende il polinomio come un elenco di coefficienti di poteri ascendenti.

Spiegazione

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 byte

-1 byte grazie a Erik the Outgolfer

sF³gݨm*O

Provalo online!

Prende x come primo argomento, n come secondo e p in ordine crescente come terzo.

Spiegazione

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
Puoi rimuovere il secondo ³.
Erik the Outgolfer

Inoltre (This is in case n is 0 so x is on the stack)è sbagliato, hai ancora bisogno di sper zero diverso da n.
Erik the Outgolfer

Sì è vero. Stavo pensando di più sulla ¹²falsariga di sostituire .with in smodo da ottenere il compito di spingere x nello stack fatto in 1 byte senza la necessità di eseguire il loop almeno una volta. Probabilmente avrebbe dovuto formularlo meglio ^^ '. Grazie anche per il -1!
Datboi,

Volevo dire che ne avresti ancora bisogno poiché 05AB1E utilizza l'ultimo input per input implicito se tutti gli input sono stati letti.
Erik the Outgolfer

" sF³gݨm³O" e anche nella spiegazione ...
Erik the Outgolfer

2

Haskell , 15 byte

((!!).).iterate

Provalo online!

Grazie a totalmente umano per 11 byte di sconto su entrambe le soluzioni

Questo definisce una funzione tacita che accetta una funzione come primo argomento e ncome secondo argomento, e compone quella funzione con se stessa nvolte. Questo può quindi essere chiamato con un argomento xper ottenere il valore finale. Grazie alla magia del curry, questo equivale a una funzione che accetta tre argomenti.


Prendendo un elenco di coefficienti anziché un argomento di funzione:

Haskell , 53 byte

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

Provalo online!

Questo è lo stesso del codice sopra, ma composto con una funzione lambda che converte un elenco di coefficienti in una funzione polinomiale. I coefficienti sono presi in ordine inverso dagli esempi - come poteri ascendenti di x.



Il TIO del secondo dovrebbe prendere una lista come argomento, non come una funzione;) Sebbene tu possa salvare una manciata di byte usando una piega come questa (nota che il polinomio zero non può essere []ma deve essere qualcosa di simile [0]o simile ).
ბიმო

2

APL (Dyalog) , 20 9 byte

{⊥∘⍵⍣⎕⊢⍺}

Provalo online!

Questo prende xcome argomento di sinistra, i coefficienti della funzione come argomento di destra e nda STDIN.

Ripensandoci dopo molti anni, mi sono reso conto che avrei potuto semplificare il calcolo usando la conversione di base .


APL (Dyalog), 5 byte

Se possiamo prendere la funzione come una funzione APL di Dyalog, allora questo può essere di 5 byte.

⎕⍣⎕⊢⎕

Prende x, nquindi la funzione come input da STDIN.


2

R , 96 58 55 52 byte

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

Provalo online!

Spiegazione:

seq(p)genera la lista 1, 2, ..., length(p)quando pè un vettore, così seq(p)-1come gli esponenti del polinomio, quindi x^(seq(p)-1)equivale a x^0(sempre uguale a 1) , x^1, x^2, ...e il calcolo di un prodotto punto %*%con pvaluta il polinomio in x.

Inoltre, se Pviene preso come una funzione, questo sarebbe 38 byte:

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

E ovviamente possiamo sempre generare PdaP=function(a)function(x)sum(x^(seq(a)-1)*a)



1

Python 3 , 70 69 byte

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

Prende pin ordine crescente, cioè se pè [0, 1, 2]allora il polinomio corrispondente è p(x) = 0 + 1*x + 2*x^2. Soluzione di ricorsione semplice.

Provalo online!


1

C # (.NET Core) , 82 byte

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

Provalo online!

Prende un elenco di coefficienti nell'ordine opposto rispetto ai casi di test (ordine crescente?) In modo che il loro indice nell'array sia uguale alla potenza a cui dovrebbe essere elevato.

E la versione banale in 30 byte:

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

Provalo online!

Prende un delegato e lo applica ricorsivamente n volte.


1

MATL , 11 byte

ii:"ZQ6Mw]&

Provalo online!

Leggermente meno interessante della mia risposta di Octave, anche se penso che ci sia qualche giocoleria intelligente di input per assicurarsi che n=0funzioni come previsto.


1

Julia 0.6.0 (78 byte)

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

spiegazioni:

Il pacchetto Polinomi è piuttosto autoesplicativo: crea polinomi. Dopo di che è una ricorsione piuttosto semplice.

Per avere un polinomio: -4,0 - 2,3 * x + 0,1 * x ^ 2 l'input adeve essere similea = [-4, -2.3, 0.1]


1

Assioma, 91 byte

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)

frastagliato

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

l'input per la polinomia g è un elenco di numeri sul retro dell'esempio dell'esercizio. per esempio

[1,2,3,4,5]  

rappresenterebbe la polinomia

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

test:

(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 byte

Come generico lambda senza nome, che ritorna tramite il xparametro:

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

Ungolfed e 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 byte

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

Accetta input come

  • Numero di iterazioni
  • valore iniziale di x
  • Quindi le 3 parti del polinomio

Uscita campione:

Command line: 8 2.3 0.1 -2.3 -4
 59.30772

0

Clojure, 66 byte

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

Esempio completo:

(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

La composizione di una funzione è di 26 byte:

#(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 byte

Abbastanza semplice, fa quello che la sfida dice sulla scatola.

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.

Prende ingressi in ordine n, p, x.

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.