Polynomial derivative

From Rosetta Code
Revision as of 17:43, 9 November 2021 by Chunes (talk | contribs) (→‎{{header|Factor}}: update for new test cases)
Polynomial derivative is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Given a polynomial, represented by an ordered list of its coefficients by increasing degree (e.g. [-1, 6, 5] represents 5x2+6x-1), calculate the polynomial representing the derivative. For example, the derivative of the aforementioned polynomial is 10x+6, represented by [6, 10]. Test cases: 5, -3x+4, 5x2+6x-1, x3-2x2+3x-4, -x4-x3+x+1

Factor

<lang factor>USING: generalizations kernel math.polynomials prettyprint ;

{ 5 } { 4 -3 } { -1 6 5 } { -4 3 -2 1 } { 1 1 0 -1 -1 }

[ pdiff ] 5 napply .s clear</lang>

Output:
{ }
{ -3 }
{ 6 10 }
{ 3 -4 3 }
{ 1 0 -3 -4 }

The implementation of pdiff:

<lang factor>USING: kernel math.vectors sequences ; IN: math.polynomials

pdiff ( p -- p' ) dup length <iota> v* rest ;</lang>

FreeBASIC

<lang freebasic>sub polydiff( p() as integer )

   'differentiates the polynomial
   'p(0) + p(1)x + p(2)x^2 +... + p(n)x^n
   'in place
   dim as integer i, n = ubound(p)
   if n=0 then
       p(0)=0
       return
   end if
   for i = 0 to n - 1
       p(i) = (i+1)*p(i+1)
   next i
   redim preserve p(0 to n-1)
   return

end sub

sub print_poly( p() as integer )

   'quick and dirty display of the poly
   if ubound(p)=0 and p(0)=0 then
       print 0
       return
   end if
   for i as integer = 0 to ubound(p)
       if i = 0 then print p(i);" ";
       if i = 1 and p(i)>0 then print using "+ #x";p(i);
       if i = 1 and p(i)<0 then print using "- #x";-p(i);
       if i > 1 and p(i)>0 then print using "+ #x^#";p(i);i;
       if i > 1 and p(i)<0 then print using "- #x^#";-p(i);i;        
   next i
   print

end sub

'test cases redim as integer p(0) p(0) = 5 print_poly(p()) print "Differentiates to " polydiff(p()) print_poly(p()): print

redim as integer p(1) p(0) = 4 : p(1) = -3 print_poly(p()) print "Differentiates to " polydiff(p()) print_poly(p()): print

redim as integer p(2) p(0) = -1 : p(1) = 6 : p(2) = 5 print_poly(p()) print "Differentiates to " polydiff(p()) print_poly(p()): print

redim as integer p(3) p(0) = 4 : p(1) = 3 : p(2) = -2 : p(3) = 1 print_poly(p()) print "Differentiates to " polydiff(p()) print_poly(p()): print

redim as integer p(4) p(0) = 1 : p(1) = 1 : p(2) = 0 : p(3) = -1 : p(4) = -1 print_poly(p()) print "Differentiates to " polydiff(p()) print_poly(p()): print</lang>

Output:

5 Differentiates to 0

4 - 3x Differentiates to -3

-1 + 6x+ 5x^2 Differentiates to 6 + %10x

4 + 3x- 2x^2+ 1x^3 Differentiates to 3 - 4x+ 3x^2

1 + 1x- 1x^3- 1x^4 Differentiates to

1 - 3x^2- 4x^3

Julia

<lang julia>using Polynomials

testcases = [

   ("5", [5]),
   ("-3x+4", [4, -3]),
   ("5x2+6x-1", [-1, 6, 5]),
   ("x3-2x2+3x-4", [-4, 3, -2, 1]),
   ("-x4-x3+x+1", [1, 1, 0, -1, -1]),

]

for (s, coef) in testcases

   println("Derivative of $s: ", derivative(Polynomial(coef)))

end

</lang>

Output:
Derivative of 5: 0
Derivative of -3x+4: -3
Derivative of 5x2+6x-1: 6 + 10*x
Derivative of x3-2x2+3x-4: 3 - 4*x + 3*x^2
Derivative of -x4-x3+x+1: 1 - 3*x^2 - 4*x^3

Raku

<lang perl6>use Lingua::EN::Numbers:ver<2.8+>;

sub pretty (@poly) {

   join( '+', (^@poly).reverse.map: { @poly[$_] ~ "x{.&super}" } )\
   .subst(/['+'|'-']'0x'<[⁰¹²³⁴⁵⁶⁷⁸⁹]>*/, , :g).subst(/'x¹'<?before <-[⁰¹²³⁴⁵⁶⁷⁸⁹]>>/, 'x')\
   .subst(/'x⁰'$/, ).subst(/'+-'/, '-', :g).subst(/(['+'|'-'|^])'1x'/, {"$0x"}, :g) || 0

}

for [5], [4,-3], [-1,3,-2,1], [-1,6,5], [1,1,0,-1,-1] -> $test {

  say "Polynomial: " ~ "[{$test.join: ','}] ➡ " ~ pretty $test;
  my @poly = |$test;
  (^@poly).map: { @poly[$_] *= $_ };
  shift @poly;
  say "Derivative: " ~ "[{@poly.join: ','}] ➡ " ~ pretty @poly;
  say ;

}</lang>

Output:
Polynomial: [5] ➡ 5
Derivative: [] ➡ 0

Polynomial: [4,-3] ➡ -3x+4
Derivative: [-3] ➡ -3

Polynomial: [-1,3,-2,1] ➡ x³-2x²+3x-1
Derivative: [3,-4,3] ➡ 3x²-4x+3

Polynomial: [-1,6,5] ➡ 5x²+6x-1
Derivative: [6,10] ➡ 10x+6

Polynomial: [1,1,0,-1,-1] ➡ -x⁴-x³+x+1
Derivative: [1,0,-3,-4] ➡ -4x³-3x²+1

Wren

<lang ecmascript>var derivative = Fn.new { |p|

   if (p.count == 1) return [0]
   var d = p[1..-1].toList
   for (i in 0...d.count) d[i] = p[i+1] * (i + 1)
   return d

}

var ss = ["", "", "\u00b2", "\u00b3", "\u2074", "\u2075", "\u2076", "\u2077", "\u2078", "\u2079"]

// for n <= 20 var superscript = Fn.new { |n| (n < 10) ? ss[n] : (n < 20) ? ss[1] + ss[n - 10] : ss[2] + ss[0] }

var polyPrint = Fn.new { |p|

   if (p.count == 1) return p[0].toString
   var terms = []
   for (i in 0...p.count) {
       if (p[i] == 0) continue
       var c = p[i].toString
       if (i > 0 && p[i].abs == 1) c = (p[i] == 1) ? "" : "-"
       var x = (i > 0) ? "x" : ""
       terms.add("%(c)%(x)%(superscript.call(i))")
   }
   return terms[-1..0].join("+").replace("+-", "-")

}

System.print("The derivatives of the following polynomials are:\n") var polys = [ [5], [4, -3], [-1, 6, 5], [-4, 3, -2, 1], [1, 1, 0, -1, -1] ] for (poly in polys) {

   var deriv = derivative.call(poly)
   System.print("%(poly) -> %(deriv)")

} System.print("\nOr in normal mathematical notation:\n") for (poly in polys) {

   var deriv = derivative.call(poly)
   System.print("Polynomial : %(polyPrint.call(poly))")
   System.print("Derivative : %(polyPrint.call(deriv))\n")

}</lang>

Output:
The derivatives of the following polynomials are:

[5] -> [0]
[4, -3] -> [-3]
[-1, 6, 5] -> [6, 10]
[-4, 3, -2, 1] -> [3, -4, 3]
[1, 1, 0, -1, -1] -> [1, 0, -3, -4]

Or in normal mathematical notation:

Polynomial : 5
Derivative : 0

Polynomial : -3x+4
Derivative : -3

Polynomial : 5x²+6x-1
Derivative : 10x+6

Polynomial : x³-2x²+3x-4
Derivative : 3x²-4x+3

Polynomial : -x⁴-x³+x+1
Derivative : -4x³-3x²+1

XPL0

<lang XPL0>int IntSize, Cases, Case, Len, Deg, Coef; [IntSize:= @Case - @Cases; Cases:=[[ 5],

       [ 4, -3],
       [-1,  6,  5],
       [-4,  3, -2,  1],
       [ 1,  1,  0, -1, -1],
       [ 0]];

for Case:= 0 to 5-1 do

   [Len:= (Cases(Case+1) - Cases(Case)) / IntSize;
   for Deg:= 0 to Len-1 do
       [Coef:= Cases(Case, Deg);
       if Deg = 0 then Text(0, "[")
       else    [IntOut(0, Coef*Deg);
               if Deg < Len-1 then
                   Text(0, ", ");
               ];
       ];
   Text(0, "]^M^J");
   ];

]</lang>

Output:
[]
[-3]
[6, 10]
[3, -4, 3]
[1, 0, -3, -4]