The Wayback Machine - https://web.archive.org/web/20140619023413/http://codegolf.stackexchange.com:80/questions/31930/help-me-with-differential-calculus
Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

I love programming and know every language, but I suck at math. Unfortunately, my school requires that computers students must take a year of calculus. There's a test next week, and I don't know any of the formulas for derivatives!

Please help me find the formulas. I need a cheat sheet - a program (as short as possible so my teacher won't notice it) that takes an expression (like 4*x^3-2) as input and outputs the derivative. (I don't care if the input and output uses command line arguments, STDIN, STDOUT, or whatever, since I'm doing all of the calculation in my head anyway.)

The test covers the following types of functions:

  • Constants, like -3 or 8.5
  • Power functions, like x^0.5 or x^-7
  • Exponential functions, like 0.5^x or 7^x (the base is always positive)
  • A constant multiplied by a function, like 3*x^5 or -0.1*0.3^x
  • The sum and difference of multiple functions, like -5*x^2+10-3^x

My teacher always formats his questions in the exact same way, as shown above. He also doesn't use any fractions, numbers like pi or e, or really big numbers (bigger than 1,000). He never uses parentheses, and always shows multiplication using an asterisk (*). The only variable used is always x.

On the other hand, my teacher is pretty lenient about answers. They don't need to be simplified at all or formatted exactly as shown above, as long as it's clear what the answer is saying.

While I can use any language, remember that I can't figure out derivatives by myself. So if the program uses built-in functions to deal with equations or calculate derivatives, I won't be able to use it.

During the test, I won't have access to the Internet or any files other than the program on the cheat sheet.

share|improve this question
3  
Can we expect that x is always the variable to differentiate? –  Kyle Kanos yesterday
2  
Must the answer be simplified? Do we need to add like terms? –  Rusher yesterday
1  
Should we assume there are no parens? –  Charles yesterday
2  
I've answered most of these questions in my edit. There is no scientific notation or product rule. –  Ypnypn yesterday
1  
Oh. So no chain rule. –  Cruncher 8 hours ago
show 4 more comments

8 Answers

Perl - 121 122

(+2 for -p)

s/(?<![-\d.*^])-?[\d.]+(?![*^\d.])/0/g;s/(?<!\^)x(?!\^)/1/g;s/x\^(-?[\d.]+)/"$1*x^".($1-1)/ge;s/([\d.]+)\^x/ln($1)*$&/g

Test:

$ perl -p diff.pl << EOF
> -3
> 8.5
> x^0.5
> x^-7
> 0.5^x
> 7^x
> 3*x^5
> -0.1*0.3^x
> -5*x^2+10-3^x
> EOF
0
0
0.5*x^-0.5
-7*x^-8
ln(0.5)*0.5^x
ln(7)*7^x
3*5*x^4
-0.1*ln(0.3)*0.3^x
-5*2*x^1+0-ln(3)*3^x
share|improve this answer
    
Yet another reason for me to learn regex... –  Kyle Kanos yesterday
3  
@KyleKanos Don't. Regex is bad, regex is terrific. –  mniip yesterday
    
Meh, beat me to it. Not bad! (PS: regex is beautiful) –  m.buettner yesterday
5  
I have no idea what's going on here. +1 –  qwr 20 hours ago
3  
Explanation: Constant --> 0, x --> 1, x^n --> n*x^(n-1), a^x --> ln(a)*a^x –  n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ 16 hours ago
show 2 more comments

Wolfram 136 134

Limited support for product and chain rules.

n=n_?NumberQ;P=Power;d[v_Plus]:=d/@v;d[v_]:=v/.{P[x_,n]:>P[x,n-1]d[x]n,P[n,x_]:>Log[n]P[n,x]d[x],Times[x_,y__]:>d[x]y+d[y]x,n:>0,x:>1}

Example:

d[3^(x^2)*(x^3+2*x)^2]
>> 2*3^x^2*(2+3*x^2)*(2*x+x^3) + 2*3^x^2*x*(2*x+x^3)^2*Log[3]

Note that this does not use any "built-in functions to deal with equations or calculate derivatives": only pattern-matching is involved*.

[*Well... technically the interpreter also parses and builds a sort of AST from the input too]


Ungolfed:

d[expr_Plus] := d /@ expr;
d[expr_] := v /. {
   Power[x_, n_?NumberQ] :> n Power[x, n - 1] d[x],
   Power[n_?NumberQ, x_] :> Log[n] Power[n, x] d[x],
   Times[x_, y__] :> d[x] y + d[y] x,
   n_?NumberQ :> 0,
   x :> 1
}
share|improve this answer
add comment

Lua 296 268 263

function d(a)l=""i=a:find"x" if i then if a:sub(i-1,i-1)=="^"then l="log("..a:sub(1,i-2)..")*"..a elseif a:sub(i+1,i+1)=="^"then l=a:sub(i+2).."*"..a:sub(1,i)p=a:sub(i+2)-1 if p~=1 then l= l..a:sub(i+1,i+1)..p end else l=a:sub(1,i-2)end else l="0"end return l end

Not very golfed and cannot currently handle multiple terms (you can just run it a few times, right?), but it can handle n^x, x^n and n as input.


Ungolfed...

function d(a)
   l=""
   i=a:find"x"
   if i then
      if a:sub(i-1,i-1)=="^" then
         l="log("..a:sub(1,i-2)..")*"..a
      elseif a:sub(i+1,i+1)=="^" then
         l=a:sub(i+2).."*"..a:sub(1,i)
         p=a:sub(i+2)-1 -- this actually does math here
         if p~=1 then
            l= l..a:sub(i+1,i+1)..p
         end
      else
         l=a:sub(1,i-2)
      end
   else
      l="0"
   end
   return l
end
share|improve this answer
    
str.func(str,...) == str:func(...), that's why strings got the metatable after all... –  mniip yesterday
    
@mniip: Still learning Lua. Thanks for the tip. –  Kyle Kanos yesterday
1  
Since the OP is only looking for code "he can calculate in his head", I wouldn't bother with defining a function and declaring l local. Just expect the input to be stored in a and say the output will be stored in l. –  m.buettner yesterday
    
You can omit parentheses in a:find("x"), also note that 1then only works in Lua 5.2 –  mniip yesterday
    
@mniip: Whoa, that's pretty cool that () is optional. The 1then was just fixed as I don't have 5.2 (not doing any CPU updates until after dissertation is done b/c I don't want to mess anything up). –  Kyle Kanos yesterday
add comment

Prolog 176

d(N,0):-number(N).
d(x,1).
d(-L,-E):-d(L,E).
d(L+R,E+F):-d(L,E),d(R,F).
d(L-R,E-F):-d(L,E),d(R,F).
d(L*R,E*R+L*F):-d(L,E),d(R,F).
d(L^R,E*R*L^(R-1)+ln(L)*F*L^R):-d(L,E),d(R,F).

Supported operators: binary +, binary -, binary *, binary ^, unary -. Note that unary + is not supported.

Sample run:

49 ?- d(-3,O).
O = 0.

50 ?- d(8.5,O).
O = 0.

51 ?- d(x^0.5,O).
O = 1*0.5*x^ (0.5-1)+ln(x)*0*x^0.5.

52 ?- d(x^-7,O).
ERROR: Syntax error: Operator expected
ERROR: d(x
ERROR: ** here **
ERROR: ^-7,O) . 
52 ?- d(x^ -7,O).
O = 1* -7*x^ (-7-1)+ln(x)*0*x^ -7.

53 ?- d(x,O).
O = 1.

54 ?- d(0.5^x,O).
O = 0*x*0.5^ (x-1)+ln(0.5)*1*0.5^x.

55 ?- d(7^x,O).
O = 0*x*7^ (x-1)+ln(7)*1*7^x.

56 ?- d(3*x^5,O).
O = 0*x^5+3* (1*5*x^ (5-1)+ln(x)*0*x^5).

57 ?- d(-0.1*0.3^x,O).
O = 0*0.3^x+ -0.1* (0*x*0.3^ (x-1)+ln(0.3)*1*0.3^x).

58 ?- d(-5*x^2+10-3^x,O).
O = 0*x^2+ -5* (1*2*x^ (2-1)+ln(x)*0*x^2)+0- (0*x*3^ (x-1)+ln(3)*1*3^x).

Prolog is confused when it runs into ^- sequence. A space must be inserted between ^ and - for it to parse the expression correctly.

Hope your teacher doesn't mind the mess of equation.

Crazy time:

59 ?- d(x^x,O).
O = 1*x*x^ (x-1)+ln(x)*1*x^x.

60 ?- d((x^2-x+1)*4^ -x,O).
O = (1*2*x^ (2-1)+ln(x)*0*x^2-1+0)*4^ -x+ (x^2-x+1)* (0* -x*4^ (-x-1)+ln(4)* - 1*4^ -x).
share|improve this answer
add comment

ECMAScript 6, 127 bytes

Here is my regex attempt (using a single regex and some logic in the replacement callback):

i.replace(/(^|[*+-])(\d+|(?:([\d.]+)\^)?(x)(?:\^(-?[\d.]+))?)(?![.*^])/g,(m,s,a,b,x,e)=>s+(b?'ln'+b+'*'+a:e?e--+'*x^'+e:x?1:0))

This expects the input string to be stored in i and simply returns the result. Try it out in an ECMAScript 6 compliant console (like Firefox's).

share|improve this answer
add comment

Haskell 38 Chars

The function d takes a function and returns a function. It is inputted in the form of a power series, and is outputted the same way (which is a type of whatever.)

d=zipWith(*)[1..].tail

For example, if we input x->x^2, we get x->2*x.

λ <Prelude>: d [0,0,1]
[0,2]

And for the exponential function.

λ <Prelude>: take 10 exp --exp redefined above to be in power series notation
[1.0,1.0,0.5,0.16666666666666666,4.1666666666666664e-2,8.333333333333333e-3,1.388888888888889e-3,1.984126984126984e-4,2.48015873015873e-5,2.7557319223985893e-6]
λ <Prelude>: let d=zipWith(*)[1..].tail in take 10 $ d exp
[1.0,1.0,0.5,0.16666666666666666,4.1666666666666664e-2,8.333333333333333e-3,1.388888888888889e-3,1.984126984126984e-4,2.48015873015873e-5,2.7557319223985893e-6]
share|improve this answer
5  
But the OP doesn't know any maths! Can we expect him to express his exponential input as a power series? –  Saran yesterday
    
Well he obviously knows notation. He just doesn't know how to do the derivative operation. –  PyRulez yesterday
5  
Can this handle 2^x? –  Kyle Kanos yesterday
2  
What witchcraft is this? –  Christofer Olsson 19 hours ago
6  
I don't see where it "takes an expression (like 4*x^3-2) as input", as required by the OP. –  Gabe 13 hours ago
show 5 more comments

Ruby, 152

...or 150 if you don't need to print... or 147 if you also are ok with an array that you need to join yourself.

run with ruby -nal

p gsub(/(?<!\^)([-+])/,'#\1').split(?#).map{|s|s[/x\^/]?$`+$'+"x^(#{$'}-1)":s[/-?(.*)\^(.*)x/]?s+"*ln(#{$1}*#{$2[0]?$2:1})":s[/\*?x/]?($`[0]?$`:1):p}*''

ungolfed:

p gsub(/(?<!\^)([-+])/,'#\1').split(?#). # insert a # between each additive piece, and then split.
map{ |s|                                 
    if s[/x\^/]                          # if it's c*x^a
        $` + $' + "x^(#{$'}-1)"          #      return c*ax^(a-1)
    elsif s[/-?(.*)\^(.*)x/]             # if it's c*b^(a*x)
        ln = $1 + ?* + ($2[0] ? $2 : 1)  #      return c*b^(a*x)*ln(b*a)
        s+"*ln(#{ln})"
    elsif s[/\*?x/]                      # if it's c*x
        ($`[0] ? $` : 1)                 #      return c
    else                                 # else (constant)
        nil                              #      return nil
    end
}*''

My main problem with this one is the number of characters proper splitting takes. The only other way I could think of was split(/(?<!\^)([-+])/) which gives + and - as their own results. Any hints for a better solution?

Also, is there a shorter way to return s if it's not empty, but otherwise return y? I've used s[0]?y:s? In JS I'd just do s||y, but "" is truthy in Ruby.

share|improve this answer
    
Would a lookahead assertion help, like so: split(/(?<!\^)(?=[-+])/)? –  DLosc 1 hour ago
add comment

sed, 110

Taking very literally "They don't need to be simplified at all or formatted exactly as shown above, as long as it's clear what the answer is saying":

s/.*/__&_/;s/x\^(-?[0-9.]+)/\1*x^(\1-1)/g;s/([0-9.]+)\^/ln\1*\1^/g;s/([^(][-+_])[0-9.]+([-+_])/\10\2/g;s/_//g

The byte count includes 1 for the r flag.

Ungolfed, with comments:

# Add underscores before and after the string, to help with solo-constant recognition
s/.*/__&_/
# Power rule: replace x^c with c*x^(c-1) where c is a number
s/x\^(-?[0-9.]+)/\1*x^(\1-1)/g
# Exponentials: replace c^ with lnc*c^ where c is a number
# (This assumes that there will be an x after the ^)
s/([0-9.]+)\^/ln\1*\1^/g
# Constants: replace ?c? with ?0? where c is a number and ? is +, -, or _
# Except if it's prededed by a parenthesis then don't, because this matches c*x^(c-1)!
s/([^(][-+_])[0-9.]+([-+_])/\10\2/g
# Get rid of the underscores
s/_//g

Sample run:

$ cat derivatives.txt
-3
8.5
x^0.5
x^-7
0.5^x
7^x
3*x^5
-0.1*0.3^x
-5*x^2+10-3^x

$ sed -re 's/.*/__&_/;s/x\^(-?[0-9.]+)/\1*x^(\1-1)/g;s/([0-9.]+)\^/ln\1*\1^/g;s/([^(][-+_])[0-9.]+([-+_])/\10\2/g;s/_//g' derivatives.txt
-0
0
0.5*x^(0.5-1)
-7*x^(-7-1)
ln0.5*0.5^x
ln7*7^x
3*5*x^(5-1)
-0.1*ln0.3*0.3^x
-5*2*x^(2-1)+0-ln3*3^x

I bet this could be golfed further; it's my first try at sed. Fun!

share|improve this answer
add comment

protected by Quincunx 12 hours ago

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

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