Skip to content

Instantly share code, notes, and snippets.

@erose
Last active October 29, 2019 16:33
Show Gist options
  • Save erose/fa924ea0b7ebc0e09b2a18f3da85b329 to your computer and use it in GitHub Desktop.
Save erose/fa924ea0b7ebc0e09b2a18f3da85b329 to your computer and use it in GitHub Desktop.
Recurse Center application code -- symbolic differentiation
from typing import *
import sys
import re
def differentiate(expression: List[str], with_respect_to: str) -> List[str]:
# We do the differentiation in one pass, then simplify the result.
first_pass = [_differentiate_single_term(t, with_respect_to) for t in expression]
simplified = _simplify_expression(first_pass)
return simplified
def _differentiate_single_term(term: str, x: str) -> str:
# The derivative of a constant is zero.
if not x in term:
return "0"
# The derivative of x is 1.
if (f'{x}^' not in term): # If x occurs in term, but has an exponent of 1.
if term == x:
return "1"
else:
return term.replace(x, "")
# The derivative of x^n is nx^(n-1).
if (f'{x}^' in term):
pattern = f'{x}\^(\d+)'
match = re.search(pattern, term)
if match is None:
raise ValueError("Something has gone wrong.")
n = int(match.group(1))
return re.sub(pattern, f'{n}{x}^{n - 1}', term)
return term
def _simplify_expression(expression: List[str]):
# Remove zero terms.
expression = [t for t in expression if t != "0"]
# x^1 == x
expression = [t.replace("^1", "") for t in expression]
return expression
def raise_usage_error():
raise RuntimeError("Use like this: python differentiate.py d/dx '1 + 2x + x^2'")
if __name__ == "__main__":
if len(sys.argv) < 2:
raise_usage_error()
first_token = sys.argv[1]
other_tokens = sys.argv[2].split(' ')
if not first_token.startswith("d/d"):
raise_usage_error()
variable = first_token[-1]
resulting_expression = differentiate(other_tokens, variable)
print(' + '.join(resulting_expression))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment