15
\$\begingroup\$

A first order separable ordinary differential equation is (arguably) the easiest type of differential equation to solve, and takes the form of

$$N(y)\frac{dy}{dx} = M(x) \\ y(x_0) = y_0$$

For two given functions \$N(y)\$ and \$M(x)\$ and an initial condition \$y(x_0) = y_0\$.

Your task is to take \$N(y)\$, \$M(x)\$, \$x_0\$ and \$y_0\$ and output the solution to that differential equation.

How to solve a separable differential equation

The differential equation

$$N(y)\frac{dy}{dx} = M(x)$$

can be solved through the following method:

$$ \begin{align} N(y)\frac{dy}{dx} & = M(x) \\ \int{N(y)\frac{dy}{dx}dx} & = \int{M(x)dx} \\ \int{N(y)dy} & = \int{M(x)dx} \end{align} $$

Once the integrals have been calculated, we can remove one of the constants of integration, leaving the equation

$$f(y) = g(x) + c$$

where

$$ f(y) = \int{N(y)dy} \\ g(x) = \int{M(x)dx} $$

After this, \$c\$ can be calculated by applying the initial condition:

$$ c = f(y_0) - g(x_0) $$

and a final solution for \$f(y)\$ can be given.

Challenge

You are to take in four inputs:

  • The function \$N(y)\$
  • The function \$M(x)\$
  • \$x_0\$
  • \$y_0\$

Both \$x_0\$ and \$y_0\$ can be any real number, and can be taken as input in many reasonable manner (i.e. a list, tuple, two integers etc.). The functions, in order to avoid having to focus on parsing mathematical input, will be limited to a type of Laurent polynomials - i.e polynomials in the form

$$ p(x) = \alpha \cdot x^n + \beta \cdot x^{n-1} + \dots + \gamma + \delta \cdot x^{-2} + \epsilon \cdot x^{-3} + \dots + \zeta \cdot x^{-m+1} + \eta \cdot x^{-m} \\ \alpha, \beta, \dots, \eta \in \mathbb{R}, \:\: n, m \in \mathbb{N} $$

Notice that we'll never have \$x^{-1}\$ in the polynomial, and that because of this, the integrals will always be Laurent polynomials of the same form (with \$x^{-1}\$ included after integrating).

With inputs in this format, there are multiple ways you could represent them for input. As with the mapping, any reasonable representation is acceptable, and if you aren't sure, ask. However, here are some that are definitely allowed (for the example \$p(x) = 3x^2 + x + 6 - 2x^{-2} + 7x^{-5}\$):

  • Nested list: [[3, 2], [1, 1], [6, 0], [-2, -2], [7, -5]]
  • A pair of lists of coefficients: [3, 1, 6] and [0, -2, 0, 0, 7]
  • A string representation: "3x^2 + x + 6 - 2x^-2 + 7x^-5"
  • etc.

Given these four inputs, you are to output the solution to the differential equation they represent.

In order to avoid having to algebraically manipulate your solutions to get into the form \$y(x) = ...\$, you can output two Laurent polynomials, in the same form as the input; one representing \$y\$ and the other \$x\$.

This is so the shortest code in bytes wins!

Test cases

Both the MathJax and text-based inputs will be included for each example, where the text based will use the nested list input format above. In addition, I will walk through the first example for clarity.

In:
  N = [[1, -2]]
  M = [[6, 1]]
  1 -> 1/25 = 0.04
Out:
  y = [[-1, -1]]
  x = [[3, 2], [28, 0]]

$$ \begin{align} \frac{1}{y^2}\frac{dy}{dx} & = 6x \\ y(1) & = \frac{1}{25} = 0.04 \\ \\ \int{N(y)dy} & = \int{M(x)dx} \\ \int{\frac{1}{y^2}dy} & = \int{6xdx} \\ -\frac{1}{y} & = 3x^2 + c \\ -25 & = c + 3 \implies c = -28 \\ -\frac{1}{y} & = 3x^2 - 28 \end{align} $$

In:
  N = [[2, 1], [-4, 0]]
  M = [[3, 2], [4, 1], [-4, 0]]
  1 -> 3
Out:
  y = [[1, 2], [-4, 1]]
  x = [[1, 3], [2, 2], [-4, 1], [-2, 0]]

$$ N(y) = 2y - 4, \:\: M(x) = 3x^2 + 4x - 4 \\ y(1) = 3 \\ \:\\ y^2 - 4y = x^3 + 2x^2 - 4x + c \\ c = -2 \\ y^2 - 4y = x^3 + 2x^2 - 4x - 2 \\ $$

In:
  N = [[1, 0]]
  M = [[3, 2], [2, 0]]
  0 -> 0
Out:
  y = [[1, 1]]
  x = [[1, 3], [2, 1]]

$$ N(y) = 1, \:\: M(x) = 3x^2 + 2 \\ y(0) = 0 \\ \:\\ y = x^3 + 2x + c \\ c = 0 \\ y = x^3 + 2x \\ $$

\$\endgroup\$
  • \$\begingroup\$ Sandbox. Please do not hesitate to leave any and all suggestions for improvements. \$\endgroup\$ – caird coinheringaahing Jun 1 at 1:32
8
\$\begingroup\$

Python 2, 123 122 bytes

def f(p,P):R=[[[a/-~b,b+1]for a,b in F]for F in P];a,b=map(lambda F,x:sum(a*x**b for a,b in F),R,p);R[1]+=[a-b,0],;print R

Try it online!

Straight-forward implementation. A function that takes arguments in the form (y, x), (N, M), and prints the resulting 2 polynomials to STDOUT.

| improve this answer | |
\$\endgroup\$
5
\$\begingroup\$

SageMath, 60 59 58 bytes

Saved a byte thanks to Dingus!!!

lambda N,M,b:desolve(diff(y,x)*N-M,y,b)
y=function('y')(x)

Try it online!

Inputs two functions \$N(y)\$ and \$M(x)\$ and a boundary condition \$[x_0,y_0]\$ and returns the solution to the differential equation \$N(y)\frac{dy}{dx}=M(x)\$ where \$y(x_0)=y_0\$.

| improve this answer | |
\$\endgroup\$
4
\$\begingroup\$

Wolfram Language (Mathematica), 33 bytes

DSolve[{y'@x#==#2,y@#3==#4},y,x]&

Try it online!

Tool for the job, and all that. Uses Mathematica's builtin DSolve. The TIO link shows the input and output formats (a warning message is issued for the second case, but the solution is correct). This builtin does automatically solve for \$y\$ in terms of \$x\$.

| improve this answer | |
\$\endgroup\$
3
\$\begingroup\$

Maxima, 50 bytes

f(N,M,a,b):=ic1(ode2(N*'diff(y,x)=M,y,x),x=a,y=b);

Try it online!

Takes maths-like expressions as input, e.g. 3*x^2+4*x-4. Outputs a quaint formatted ASCII string!

| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ Love the ASCII art output! :D \$\endgroup\$ – Noodle9 Jun 1 at 14:03
1
\$\begingroup\$

JavaScript (ES6), 114 bytes

Just a port of @SurculoseSputum's answer.

Takes input as ([y, x])([N, M]).

p=>P=>(R=P.map(p=>p.map(([a,b])=>[a/++b,b])))[1].push([(g=i=>R[i].reduce((t,[a,b])=>t+a*p[i]**b,0))(0)-g(1),0])&&R

Try it online!

| improve this answer | |
\$\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.