4
\$\begingroup\$

Symbolic Differentiation 2: Back on the Chain Gang

Task

Write a program that takes in a certain sort of function from stdin and differentiates it with respect to x, using the chain rule.* The input function will be a string of the following form:

"trig_1 trig_2 trig_3 ... x"

where trig_n is a trigonometric function sin or cos, and there are at most four functions in the term. The example string

"cos sin sin x"

represents the function cos(sin(sin(x))).

Your output must take the following form:

k(trig_1 trig_2 x)(trig_a trig_b trig_c x)(trig_m trig_n x) et cetera

where k is a constant and parentheses represent groups to be multiplied together.

*The chain rule states that D[f(g(x))] = f'(g(x)) * g'(x)

Examples

"sin sin sin sin x" ==> 1(cos x)(cos sin x)(cos sin sin x)(cos sin sin sin x)
"cos x" ==> -1(sin x)
"cos sin x" ==> -1(cos x)(sin sin x)

Scoring

Your score is the length of your program in bytes, multiplied by three if you use a built-in or a library that does symbolic algebra.

Similar Challenges

The previous installment: polynomial differentiation
Polynomial integration
General differentiation

\$\endgroup\$
  • \$\begingroup\$ (Maybe [trigonometry] is an inappropriate tag?) \$\endgroup\$ – hYPotenuser Mar 2 '16 at 7:01
  • 2
    \$\begingroup\$ This is less of a calculus question. It's more like a parsing challenge than anything. \$\endgroup\$ – Addison Crump Mar 2 '16 at 11:00
1
\$\begingroup\$

Java 8, 224 214 bytes

Let the games begin!

interface B{static void main(String[]a){String o="";int v=2,z=a.length-1,i=z,k;for(;i>0;o+="x)"){if(a[--i].equals("cos")){o+="(sin ";v=(v+2)%4;}else o+="(cos ";for(k=i;++k<z;)o+=a[k]+" ";}System.out.print(v-1+o);}}

This could (theoretically) extend infinitely.

Output for sin cos sin sin cos sin cos sin sin sin cos sin sin cos sin cos cos cos sin x:

1(cos x)(sin sin x)(sin cos sin x)(sin cos cos sin x)(cos cos cos cos sin x)(sin sin cos cos cos sin x)(cos cos sin cos cos cos sin x)(cos sin cos sin cos cos cos sin x)(sin sin sin cos sin cos cos cos sin x)(cos cos sin sin cos sin cos cos cos sin x)(cos sin cos sin sin cos sin cos cos cos sin x)(cos sin sin cos sin sin cos sin cos cos cos sin x)(sin sin sin sin cos sin sin cos sin cos cos cos sin x)(cos cos sin sin sin cos sin sin cos sin cos cos cos sin x)(sin sin cos sin sin sin cos sin sin cos sin cos cos cos sin x)(cos cos sin cos sin sin sin cos sin sin cos sin cos cos cos sin x)(cos sin cos sin cos sin sin sin cos sin sin cos sin cos cos cos sin x)(sin sin sin cos sin cos sin sin sin cos sin sin cos sin cos cos cos sin x)(cos cos sin sin cos sin cos sin sin sin cos sin sin cos sin cos cos cos sin x)
\$\endgroup\$
1
\$\begingroup\$

sed, 88 + 1 = 123 89 bytes

+1 for the -r (extended regex) flag.

s/^/d/
:
s/d(-?)sin (.*)/(\1cos \2)d\2/
s/d(-?)cos (.*)/(\1-sin \2)d\2/
s/--//
s/dx/1/
t

Explanation

Note: A single d is used as short version of d/dx in the golfed program.

First, preceed the string with d/dx. Then, reapeat the following replacements until the string does not change anymore:

d/dx sin ...    => (cos ...)d/dx ...
d/dx cos ...    => (-sin ...)d/dx ...
d/dx -sin ...   => (-cos ...)d/dx ...
d/dx -cos ...   => (sin ...)d/dx ...
d/dx x          => 1

Edit: The positive and negative cases are now handled within a single regex. This requires an additional search and replace to drop a double minus and is less elegant, but way shorter.

\$\endgroup\$
  • \$\begingroup\$ Elegant solution! \$\endgroup\$ – hYPotenuser Mar 2 '16 at 15:52
0
\$\begingroup\$

Mathematica, 115 bytes

ToExpression["d["<>StringReplace[#,{" "->"@"}]<>"]"]//.d[x_[y__]]->d[x][y]d[y]/.{d[sin]->cos,d[cos]->-sin,d[x]->1}&
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.