21
\$\begingroup\$

Apply an indefinite integral to a given string. The only rules you will be using are defined as such:

∫cx^(n)dx = (c/(n+1))x^(n+1) + C, n ≠ -1
c, C, and n are all constants.

Specifications:

  • You must be able to integrate polynomials with any of the possible features:
    • A coefficient, possibly a fraction in the format (numerator/denominator).
    • Recognition that e and π are constants, and in their use, be able to form fractions or expressions containing them (can be held in a fraction like (e/denominator) or (numerator/e), or, if in exponents, x^(e+1))
      • Aside of these two special constants, all coefficients will be rational, real numbers.
    • An exponent, possibly a fraction, in the format x^(exponent)
      • Expressions with e or π in them, aside of themselves, will not be in exponents. (you will not have to integrate stuff like x^(e+1), but you might integrate x^(e))
    • Can use non-x 1-char variables (i.e. f)
      • This is only for ASCII ranges 65-90 and 97-122.
    • You do not have to use chain rule or integrate x^(-1).
  • Output must have padding (separation between terms, i.e. x^2 + x + C.
  • If it is unknown how to integrate with the above features, the program should print out "Cannot integrate "+input.
  • It must be a full program.

Bonuses:

  • -10% if you print out the "pretty" exponents formatted for markdown (instead of x^2, x<sup>2</sup>).
  • -10% if you print out the equation (i.e. ∫xdx = (1/2)x^2 + C)

Examples:

Input:

x

Output:

(1/2)x^(2) + C

Input:

-f^(-2)

Output:

f^(-1) + C

Input:

(1/7)x^(1/7) + 5

Output:

(1/56)x^(8/7) + 5x + C

Input:

πx^e

Output:

(π/(e+1))x^(e+1) + C

Input:

(f+1)^(-1)

Output:

Cannot integrate (f+1)^(-1)
\$\endgroup\$
18
  • 1
    \$\begingroup\$ Surprised we don't already have this question - but I couldn't find a dup. +1 \$\endgroup\$ Commented Dec 15, 2015 at 21:34
  • 3
    \$\begingroup\$ 1. I presume that other than e and π, the only values in coefficients will be rational numbers? I.e. it's not necessary to handle multivariable polynomials? 2. When you say "non-x 1-char variables", are you restricting to a-zA-Z or do you intend to include other Unicode ranges? \$\endgroup\$ Commented Dec 15, 2015 at 21:36
  • 1
    \$\begingroup\$ Do you think there should be a bonus if someone's program prints ln(x) + C for an input of x^(-1)? \$\endgroup\$
    – Arcturus
    Commented Dec 15, 2015 at 21:38
  • 1
    \$\begingroup\$ @Ampora No - that opens up a whole can of worms dealing with coefficients of ln. \$\endgroup\$ Commented Dec 15, 2015 at 21:39
  • 1
    \$\begingroup\$ @LeifWillerts 1) I meant that x^(e+1) will not be an integrand, but it may be the result of an integration. 2) There will not be multiple letter variables. 3) Yes. 4) Yes, but it should be (1/56)x^(1/7+1) + C (I made a mistake in the examples). \$\endgroup\$ Commented Feb 2, 2016 at 13:31

2 Answers 2

7
+50
\$\begingroup\$

MATLAB, 646 x 0.9 = 581.4 bytes

t=input('','s');p=char(960);s=regexprep(t,{p,'pi([a-zA-Z])','([a-zA-Z])pi','([\)e\d])([a-zA-Z])','([a-zA-Z])(([\(\d]|pi))','e^(\(.+?\))','e'},{'pi','pi*$1','$1*pi','$1*$2','$1*$2','exp($1)','exp(1)'});r=[s(regexp(s,'\<[a-zA-Z]\>')),'x'];r=r(1);e=0;try
I=int(sym(strsplit(s,' + ')),r);S=[];for i=I
S=[S char(i) ' + '];end
b=0;o=[];for i=1:nnz(S)
c=S(i);b=b+(c==40)-(c==41);if(c==42&&S(i+1)==r)||(b&&c==32)
c='';end
o=[o c];end
o=regexprep(char([8747 40 t ')d' r ' = ' o 67]),{'pi','exp\(1\)','exp','\^([^\(])',['1/' r]},{p,'e','e^','^($1)',[r '^(-1)']});catch
e=1;end
if e||~isempty(strfind(o,'log'))
disp(['Cannot integrate ' t]);else
disp(o);end

This is currently a work-in-progress using MATLABs built in symbolic integration capabilities. Currently the requirements have been updated so the format now matches the requirements. It also does qualify for the second -10% bonus.

If anyone wants to pitch in and suggest ways of correcting the output, or use this code as a basis for another answer, feel free :). If I can find the time, I'll keep playing with it and see if I can think how to reformat the output.

Update: Ok, so after a bit more work, here is how the code currently stands. It is still a work in progress, but now getting closer to matching the required output.

t=input('','s'); %Get input as a string
p=char(960); %Pi character
s=regexprep(t,{p,'pi([a-zA-Z])','([a-zA-Z])pi','([\)e\d])([a-zA-Z])','([a-zA-Z])(([\(\d]|pi))','e^(\(.+?\))','e'},{'pi','pi*$1','$1*pi','$1*$2','$1*$2','exp($1)','exp(1)'}); %Reformat input to work with built in symbolic integration
r=[s(regexp(s,'\<[a-zA-Z]\>')),'x'];r=r(1); %determine the variable we are integrating
e=0; %Assume success
try
    I=int(sym(strsplit(s,' + ')),r); %Integrate each term seperately to avoid unwanted simplificaiton
    S=[];
    for i=I
        S=[S char(i) ' + ']; %Recombine integrated terms
    end
    %Now postprocess the output to try and match the requirements
    b=0;o=[];
    for i=1:nnz(S)
        %Work through the integrated string character by character
        c=S(i);
        b=b+(c=='(')-(c==')'); %Keep track of how many layers deep of brackets we are in
        if(c=='*'&&S(i+1)==r)||(b&&c==' ') %If a '*' sign preceeds a variable. Also deblank string.
            c=''; %Delete this character
        end
        o=[o c]; %merge into new output string.
    end
    o=regexprep([char(8747) '(' t ')d' r ' = ' o 'C'],{'pi','exp\(1\)','exp','\^([^\(])',['1/' r]},{p,'e','e^','^($1)',[r '^(-1)']});
catch
    e=1; %failed to integrate
end
if e||~isempty(strfind(o,'log'))
    disp(['Cannot integrate ' t])  %bit of a hack - matlab can integrate 1/x, so if we get a log, we pretend it didn't work.
else
    disp(o)% Display it.
end

Here are some examples of what it currently produces. As you can see, it's not quite right, but getting closer.

Inputs:

x
-f^(-2)
(1/7)x^(1/7) + 5
πx^e
(f+1)^(-1)

Outputs:

∫(x)dx = x^(2)/2 + C
∫(-f^(-2))df = f^(-1) + C
∫((1/7)x^(1/7) + 5)dx = x^(8/7)/8 + 5x + C
∫(πx^(e))dx = (πx^(e+1))/(e+1) + C
Cannot integrate (f+1)^(-1)
\$\endgroup\$
6
  • \$\begingroup\$ I assume the problem with output that you're having is that the fractions don't simplify/go into a single coefficient? \$\endgroup\$ Commented Dec 20, 2015 at 18:13
  • \$\begingroup\$ @FlagAsSpam, the fractions are simplifying, but the trouble is they end up on the wrong side of the variable. For instance in the third example it results in x^(8/7)/8 which while mathematically correct is not in the form you want it - (1/8)x^(8/7). \$\endgroup\$ Commented Dec 20, 2015 at 18:27
  • \$\begingroup\$ Considering that you are the only answer so far, I might consider changing that if no more answers come through in a day or two to "any mathematically correct, valid output" for fractions. \$\endgroup\$ Commented Dec 20, 2015 at 18:46
  • \$\begingroup\$ Your answer is valid - You do not have to simplify fractional output anymore. c: \$\endgroup\$ Commented Dec 21, 2015 at 21:46
  • \$\begingroup\$ I will golf it down a bit then and count the bytes. \$\endgroup\$ Commented Dec 22, 2015 at 6:23
2
+250
\$\begingroup\$

Mathematica 478 * 0.9 = 430.2

φ=(α=ToExpression;Π=StringReplace;σ="Cannot integrate "<>#1;Λ=DeleteDuplicates@StringCases[#1,RegularExpression["[a-df-zA-Z]+"]];μ=Length@Λ;If[μ>1,σ,If[μ<1,Λ="x",Λ=Λ[[1]]];Ψ=α@Π[#1,{"e"->" E ","π"->" π "}];Φ=α@Λ;Θ=α@Π[#1,{"e"->" 2 ","π"->" 2 "}];λ=Exponent[Θ,Φ,List];Θ=Simplify[Θ*Φ^Max@@Abs@λ];Θ=PowerExpand[Θ/.Φ->Φ^LCM@@Denominator@λ];If[Coefficient[Ψ,Φ,-1]==0&&PolynomialQ[Θ,Φ],"∫("<>#1<>")d"<>Λ<>" = "<>Π[ToString[Integrate[Ψ,Φ],InputForm],{"E"->"e","Pi"->"π"}]<>" + C",σ]])&

This creates a true function φ that takes one String as Input. (Does that count as complete program for Mathematica?)

The ungolfed version would be:

φ=(
    σ="Cannot integrate "<>#1;
    Λ=DeleteDuplicates@StringCases[#1,RegularExpression["[a-df-zA-Z]+"]];
    If[Length@Λ>1,σ,
        If[Length@Λ<1,Λ="x",Λ=Λ[[1]]];
        Ψ=ToExpression@StringReplace[#1,{"e"->" E ","π"->" π "}];
        Φ=ToExpression@Λ;
        Θ=ToExpression@StringReplace[#1,{"e"->" 2 ","π"->" 2 "}];
        λ=Exponent[Θ,Φ,List];
        Θ=Simplify[Θ*Φ^Max@@Abs@λ];
        Θ=PowerExpand[Θ/.Φ->Φ^LCM@@Denominator@λ];
        If[Coefficient[Ψ,Φ,-1]==0&&PolynomialQ[Θ,Φ],
            "∫("<>#1<>")d"<>Λ<>" = "<>StringReplace[ToString[Integrate[Ψ,Φ],InputForm],{"E"->"e","Pi"->"π"}]<>" + C",
            σ
        ]
    ]
)&

Note that the Greek letters are necessary to be able to use all the other letters in the input.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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