Helfen Sie mir mit Differentialrechnung!


52

Ich liebe das Programmieren und kenne jede Sprache, aber ich mag Mathe. Leider verlangt meine Schule, dass Computer-Studenten ein Jahr Rechenzeit benötigen. Nächste Woche gibt es einen Test und ich kenne keine der Formeln für Derivate!

Bitte helfen Sie mir, die Formeln zu finden. Ich benötige ein Spickzettel - ein Programm (so kurz wie möglich, damit mein Lehrer es nicht bemerkt), das einen Ausdruck (wie 4*x^3-2) als Eingabe verwendet und die Ableitung ausgibt. (Es ist mir egal, ob die Eingabe und Ausgabe Befehlszeilenargumente, STDIN, STDOUT oder was auch immer verwendet, da ich die gesamte Berechnung sowieso in meinem Kopf mache.)

Der Test deckt die folgenden Arten von Funktionen ab:

  • Konstanten, wie -3oder8.5
  • Power-Funktionen, wie x^0.5oderx^-7
  • Exponentialfunktionen, wie 0.5^xoder 7^x(die Basis ist immer positiv)
  • Eine Konstante multipliziert mit einer Funktion wie 3*x^5oder-0.1*0.3^x
  • Die Summe und Differenz mehrerer Funktionen, wie z -5*x^2+10-3^x

Mein Lehrer formatiert seine Fragen immer genauso wie oben gezeigt. Er verwendet auch keine Brüche, Zahlen wie pi oder e oder wirklich große Zahlen (größer als 1.000). Er verwendet niemals Klammern und zeigt die Multiplikation immer mit einem Sternchen ( *) an. Die einzige verwendete Variable ist immer x .

Andererseits ist mein Lehrer bei Antworten ziemlich nachsichtig. Sie müssen überhaupt nicht vereinfacht oder genau wie oben dargestellt formatiert werden, solange klar ist, was die Antwort sagt.

Ich kann zwar jede Sprache verwenden, denke aber daran, dass ich selbst keine Ableitungen finden kann. Wenn das Programm also integrierte Funktionen verwendet, um mit Gleichungen umzugehen oder Ableitungen zu berechnen, kann ich sie nicht verwenden.

Während des Tests habe ich keinen Zugriff auf das Internet oder andere Dateien als das Programm auf dem Spickzettel.

Hinweis: Dieses Szenario ist vollständig fiktiv. Im wirklichen Leben ist das Betrügen und Helfen anderer falsch und sollte niemals getan werden.


3
Können wir erwarten, dass ximmer die Variable zu unterscheiden ist?
Kyle Kanos

2
Muss die Antwort vereinfacht werden? Müssen wir ähnliche Begriffe hinzufügen?
Rainbolt

1
Ich denke, es ist Zeit für mein Kalkülprojekt bei scrblnrd3.github.io/Javascript-CAS zu glänzen, wenn ich es tatsächlich Golf spielen kann
scrblnrd3

1
Sollen wir davon ausgehen, dass es keine Eltern gibt?
Nicht dass Charles

2
Ich habe die meisten dieser Fragen in meiner Bearbeitung beantwortet . Es gibt keine wissenschaftliche Notation oder Produktregel.
Ypnypn

Antworten:


8

Wolfram 136 134 109 [Danke an Calle für seinen Kommentar unten]

Eingeschränkte Unterstützung für Produkt- und Kettenregeln.

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

Beispiel:

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]

Beachten Sie, dass hierbei keine "integrierten Funktionen zum Behandeln von Gleichungen oder zum Berechnen von Ableitungen" verwendet werden: Es handelt sich nur um eine Mustererkennung *.

[* Nun ... technisch gesehen parst und erstellt der Interpreter auch eine Art AST aus den Eingaben]


Ungolfed:

d[expr_Plus] := d /@ expr;
d[expr_] := expr /. {
   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
}

Dies ist eine andere Version . Sie müssen nicht schreiben Power, Timesusw. IDK, um wie viel dies Ihre Golfversion verbessert, aber Sie haben mindestens eine, Timesdamit Sie def. Speichern Sie einige Zeichen. Beachten Sie auch, dass in Ihrer ungolfed Version steht d[expr_]:= v/....

1
@Calle "IDK, wie viel das Ihre Golfversion verbessern wird" - 25 Bytes! Prost!
Saran

26

Perl - 121 122

(+2 für -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

Prüfung:

$ 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

Ein weiterer Grund für mich, Regex zu lernen ...
Kyle Kanos

3
@KyleKanos Nicht. Regex ist schlecht, Regex ist großartig.
Mittwoch,

Meh, schlag mich dazu. Nicht schlecht! (PS: Regex ist schön)
Martin Ender

8
Ich habe keine Ahnung, was hier los ist. +1
QWR

4
Erklärung: Konstante -> 0, x -> 1, x ^ n -> n * x ^ (n-1), a ^ x -> ln (a) * a ^ x
n̴̖̋h̴̖̋ã̷͉h̷̭̿d̸̡̅ẗ̵̨́

7

Haskell 38 Zeichen

Die Funktion dübernimmt eine Funktion und gibt eine Funktion zurück. Es wird in Form einer Potenzreihe eingegeben und auf die gleiche Weise ausgegeben (was eine Art von allem ist).

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

Wenn wir zum Beispiel eingeben x->x^2, erhalten wir x->2*x.

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

Und für die Exponentialfunktion.

λ <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]

5
Aber das OP kennt keine Mathematik! Können wir erwarten, dass er seinen exponentiellen Input als Potenzreihe ausdrückt?
Saran

Nun, er kennt offensichtlich die Notation. Er weiß einfach nicht, wie er die Ableitungsoperation durchführen soll.
PyRulez

5
Kann das gehen 2^x?
Kyle Kanos

5
Was für eine Hexerei ist das?
Christofer Ohlsson

7
Ich sehe nicht, wo es "einen Ausdruck (wie 4*x^3-2) als Eingabe nimmt", wie vom OP gefordert.
Gabe

5

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).

Unterstützte Operatoren: binär +, binär -, binär *, binär ^, unär -. Beachten Sie, dass Unary +nicht unterstützt wird.

Probelauf:

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 ist verwirrt, wenn es in ^-Sequenz läuft . Ein Raum ist zwischen eingefügt werden ^und -für die es zu analysieren , um die Expression korrekt.

Ich hoffe, Ihr Lehrer hat nichts dagegen, die Gleichung durcheinander zu bringen.

Verrückte Zeit:

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).

4

C 260

Hey, ich glaube ich kenne deinen Lehrer! Ist es nicht jemand, der die übernatürliche Fähigkeit besitzt, Schüler zu entdecken, die Bibliotheksmuster-Abgleichfunktionen in ihrem Kopf ausführen?

Also, Verwendung sscanfkommt nicht in Frage ... Aber keine Sorge:

#define P s--||printf(
q=94,s,c,t,a;main(){char i[999],*p=i,*e=p;gets(i);for(;c=*p++,t=q^94|c^45?c%26==16?c%16/3:c/46:1,s=(a="30PCqspP#!C@ #cS` #!cpp#q"[s*5+t])/16-3,a&1&&(p[-1]=0),t||(P"*0"),P"/x"),P"/x*%s",e),P"*ln(%s)",e),s=0),a&2&&(e=p),c;putchar(q=c));}

Laufende Beispiele (Eingabe ein stdin; Ausgabe geht an stdout):

4 * x ^ 3-2

4*x^3/x*3-2*0

Dieses Format ist viel besser als nur 12*x^2, denn auf diese Weise kann Ihr Lehrer sicher sein, dass Sie die Antwort selbst berechnet und nicht durch Kopieren von jemand anderem betrogen haben!

x + 2 ^ x

x/x+2^x*ln(2)

Die Ausgabe weist ein leichtes Domainproblem auf x=0, ist aber fast überall korrekt !

Als Referenz ist hier eine ungolfed, lesbare (von bloßen Sterblichen) Version. Es verwendet eine Zustandsmaschine mit 5 Zuständen und 5 Kategorien von Eingabezeichen.

void deriv(char* input)
{
    char* p = input; // current position
    char* exp = p; // base or exponent
    char q = '^'; // previous character

    // State machine has 5 states; here are examples of input:
    // state 0: 123
    // state 1: 123*
    // state 2: 123*x
    // state 3: 123*x^456
    // state 4: 123^x
    int state = 0;

    // Control bits for state machine:
    // bit 0: special action: stop recording base or exponent
    // bit 1: special action: start recording base or exponent
    // bits 4-7: if first column, specify how to calculate the derivative:
    //              3 - multiply the constant term by 0
    //              4 - divide x by x
    //              5 - divide x^n by x and multiply by n
    //              6 - multiply n^x by ln(n)
    // bits 4-7: if not first column, specify the next state
    //              (plus 3, to make the character printable)
    const char* control =
        "\x33\x30\x50\x43\x71"
        "\x73\x70\x50\x23\x21"
        "\x43\x40\x20\x23\x63"
        "\x53\x60\x20\x23\x21"
        "\x63\x70\x70\x23\x71";

    for (;;) {
        int c = *p++;

        // Convert a char to a category:
        // category 0: // - +
        // category 3: // *
        // category 2: // x
        // category 4: // ^
        // category 1: // numbers: 0...9 and decimal point
        int category;
        int action;    

        if (q == '^' && c == '-')
            category = 1; // unary minus is a part of a number
        else
            category = c%26==16?c%16/3:c/46; // just does it

        // Load new state and action to do
        action = control[state * 5 + category];

        if (action & 1)
            p[-1] = 0;
        state = (action >> 4) - 3;
        if (category == 0)
        {
            if (state == 0)
                printf("*0");
            if (state == 1)
                printf("/x");
            if (state == 2)
                printf("/x*%s", exp);
            if (state == 3)
                printf("*ln(%s)", exp);
            state = 0;
        }
        if (action & 2)
            exp = p;

        if (c == 0 || c == '\n') // either of these can mark end of input
            break;

        putchar(c);
        q = c;
    }
}

PS Achten Sie auf diese getsFunktion: Sie weist eine Sicherheitslücke auf, durch die Ihr Lehrer ein Rootkit in Ihrem Kopf ausführen kann, indem er zu lange Eingaben macht ...


3

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

Nicht sehr golfed und kann derzeit nicht mehrere Begriffe behandeln (man kann es nur ein paar Mal läuft, nicht wahr?), Aber es kann behandeln n^x, x^nund nals Eingabe.


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

str.func(str,...)== str:func(...), deswegen haben die Strings doch das Metatable bekommen ...
mniip

@mniip: Ich lerne immer noch Lua. Danke für den Tipp.
Kyle Kanos

1
Da der OP nur nach dem Code "er kann im Kopf rechnen" sucht, würde ich mich nicht darum kümmern, eine Funktion zu definieren und llocal zu deklarieren . Erwarten Sie einfach, dass die Eingabe in gespeichert wird, aund sagen Sie, dass die Ausgabe in gespeichert wird l.
Martin Ender

Sie können Klammern in weglassen. a:find("x")Beachten Sie auch, dass dies 1thennur in Lua 5.2
Mittwoch,

@mniip: Whoa, das ist ziemlich cool, das ()ist optional. Das 1thenProblem wurde behoben, da ich nicht über 5.2 verfüge (keine CPU-Updates durchführen, bis die Dissertation abgeschlossen ist, da ich nichts vermasseln möchte).
Kyle Kanos

3

ECMAScript 6, 127 Bytes

Hier ist mein Regex-Versuch (unter Verwendung eines einzelnen Regex und einer Logik im Ersetzungs-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))

Dies erwartet, dass die Eingabezeichenfolge in gespeichert wird, iund gibt einfach das Ergebnis zurück. Probieren Sie es in einer ECMAScript 6-kompatiblen Konsole (wie Firefox) aus.


2

sed, 110

Ganz wörtlich: "Sie müssen überhaupt nicht vereinfacht oder genau wie oben dargestellt formatiert werden, solange klar ist, was in der Antwort steht."

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

Die Byteanzahl enthält 1 für das rFlag.

Ungolfed, mit Kommentaren:

# 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

Probelauf:

$ 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

Ich wette, das könnte weiter golfen werden. es ist mein erster versuch an sed. Spaß!


1

Rubin, 152

... oder 150, wenn Sie nicht drucken müssen ... oder 147, wenn Sie auch mit einem Array einverstanden sind, das Sie selbst verbinden müssen.

renn mit 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
}*''

Mein Hauptproblem bei diesem ist die Anzahl der Zeichen, die für die richtige Aufteilung benötigt werden. Der einzige andere Weg, den ich mir vorstellen konnte, war, split(/(?<!\^)([-+])/)was gibt +und -was ihre eigenen Ergebnisse sind. Irgendwelche Tipps für eine bessere Lösung?

Gibt es auch einen kürzeren Weg, um zurückzukehren, swenn es nicht leer ist, aber ansonsten zurückzukehren y? Habe ich benutzt s[0]?y:s? In JS würde ich nur tun s||y, aber ""in Ruby ist es wahr.


Würde eine vorwärtsgerichtete Behauptung Hilfe, etwa so: split(/(?<!\^)(?=[-+])/)?
DLosc
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.