Diferansiyel hesapta bana yardım et!


52

Programlamayı çok seviyorum ve her dili tanıyorum, fakat matematik dersini emiyorum. Maalesef, okulum bilgisayar öğrencilerinin bir yıl boyunca ders almasını gerektiriyor. Gelecek hafta bir test var ve türev formüllerinin hiçbirini bilmiyorum!

Lütfen formülleri bulmama yardım et. Bir hile sayfasına ihtiyacım var - bir program (mümkün olduğu kadar kısa ki öğretmenim bunu farketmeyecek 4*x^3-2) girdi olarak çıktısı alan ve türevi çıktılayan bir ifade (benzeri ) alıyor . (Girdi ve çıktının komut satırı argümanları, STDIN, STDOUT veya ne olursa olsun kullanması umurumda değil, çünkü kafamdaki tüm hesaplamaları zaten yapıyorum.)

Test, aşağıdaki fonksiyon tiplerini kapsar:

  • Sabitler, gibi -3veya8.5
  • Güç fonksiyonları, gibi x^0.5veyax^-7
  • Üstel fonksiyonlar, 0.5^xveya gibi 7^x(taban daima pozitif)
  • Bir fonksiyonla çarpılan bir sabit, gibi 3*x^5veya-0.1*0.3^x
  • Çoklu fonksiyonların toplamı ve farkı, -5*x^2+10-3^x

Öğretmenim, sorularını her zaman yukarıda gösterildiği gibi aynı şekilde biçimlendirir. Ayrıca, herhangi bir kesir, pi veya e gibi sayılar ya da gerçekten büyük sayılar (1.000'den büyük) kullanmaz. Asla parantez kullanmaz ve her zaman yıldız işareti ( *) kullanarak çarpımı gösterir . Kullanılan tek değişken her zaman x .

Öte yandan, öğretmenim cevaplar konusunda oldukça esnek. Yanıtın ne dediği açık olduğu sürece, hiçbir şekilde sadeleştirilmeleri veya tam olarak yukarıda gösterildiği gibi biçimlendirilmeleri gerekmez.

Herhangi bir dili kullanabildiğim halde türevleri kendi başıma çözemediğimi unutmayın. Bu nedenle eğer program denklemlerle uğraşmak veya türevleri hesaplamak için yerleşik fonksiyonları kullanıyorsa, onu kullanamayacağım.

Test sırasında, İnternet'e veya program sayfasındaki program dışındaki dosyalara erişemeyeceğim.

Not: Bu senaryo tamamen kurgusaldır. Gerçek hayatta hile yapmak ve başkalarını aldatmak yardımcı olmak yanlıştır ve asla yapılmamalıdır.


3
Bunun xher zaman farklılaşan değişkeni bekleyebilir miyiz ?
Kyle Kanos

2
Cevap basitleştirilmeli mi? Benzer terimler eklememiz gerekiyor mu?
Rainbolt

1
Sanırım scrblnrd3.github.io/Javascript-CAS'taki calculus projemin golf oynaması halinde parlama
vakti

1
Parens olmadığını varsaymalı mıyız?
Charles

2
Bu soruların çoğunu düzenlememde cevapladım . Bilimsel gösterim veya ürün kuralı yoktur.
Ypnypn

Yanıtlar:


8

Wolfram 136 134 109 [Aşağıdaki yorum için Calle teşekkürler]

Ürün ve zincir kurallarına sınırlı destek.

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}

Örnek:

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]

Bunun, "denklemlerle başa çıkmak veya türevleri hesaplamak için yerleşik işlevler" kullanmadığını unutmayın: yalnızca desen eşleştirmesi söz konusudur *.

[* Şey ... teknik olarak tercüman da girişten bir çeşit AST ayrıştırır ve oluşturur]


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
}

Bu başka bir versiyon . Yazmak zorunda değilsiniz Power, Timesvb. IDK golf sürümünüzü ne kadar geliştirecek olsa da, içinde en az bir tane Timesvar. bazı karakterleri kaydedin. Ayrıca ungolfed versiyonunuzda yazıldığını unutmayın d[expr_]:= v/....

1
@Calle "IDK golf versiyonunu ne kadar geliştirecek" - 25 byte! Şerefe!
Saran

26

Perl - 121 122

(İçin +2 -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

Ölçek:

$ 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


3
@KyleKanos Yapma. Regex kötü, regex müthiş.
mniip

Meh, beni döv. Fena değil! (Not: regex güzeldir)
Martin Ender

8
Burada neler olduğu hakkında hiçbir fikrim yok. +1
qwr

4
Açıklama: Sabit -> 0, x -> 1, x ^ n -> n * x ^ (n-1), a ^ x -> ln (a) * a ^ x
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

7

Haskell 38 Karakter

İşlev dbir işlev alır ve bir işlev döndürür. Bir güç serisi biçiminde girilir ve aynı şekilde çıkarılır (bu her neyse bir türdür).

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

Örneğin, eğer girersek x->x^2, alırız x->2*x.

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

Üstel fonksiyon için.

λ <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
Fakat OP hiç bir matematik bilmiyor! Üstel girişini bir güç serisi olarak ifade etmesini bekleyebilir miyiz?
Saran

Belli ki notasyonu biliyor. Sadece türev işleminin nasıl yapıldığını bilmiyor.
PyRulez

5
Bu idare edebilir 2^xmi?
Kyle Kanos

5
Bu hangi büyücülük?
Christofer Ohlsson

7
4*x^3-2OP'nin gerektirdiği şekilde "girdi olarak bir ifade (benzeri )" aldığını " anlamıyorum .
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).

Desteklenen operatörler: ikili +, ikili -, ikili *, ikili ^, unary -. Unary'nin +desteklenmediğini unutmayın.

Örnek çalışma:

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 ^-sıraya girdiğinde kafası karışır . Bir boşluk arasına yerleştirilmiş olması gerekir ^ve -doğru ifadesi ayrıştırmak için.

Umarım öğretmenin denklem dağınıklığına aldırış etmez.

Çılgın zaman:

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, sanırım öğretmenini tanıyorum! Kütüphane paterni eşleştirme fonksiyonlarını kafasında yürüten öğrencileri tespit etmek için doğaüstü yeteneği olan biri değil mi?

Yani, sscanfkullanımı söz konusu değil ... Ama endişelenme:

#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));}

Çalışan örnekler (giriş açık stdin; çıkış geçerli stdout):

4 * x ^ 3-2

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

Bu format sadece çok daha iyidir 12*x^2, çünkü bu şekilde öğretmeniniz cevabı kendiniz hesapladığınızdan ve başka birinden kopyalayarak aldatmadığınızdan emin olabilir!

x + 2 ^ x

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

Çıktıda hafif etki alanı sorunu var x=0, ancak hemen hemen her yerde doğru !

Başvuru için, burada bir ungolfed, okunabilir (sadece ölümlüler tarafından) versiyonudur. 5 durumlu ve 5 kategori giriş karakteri olan bir durum makinesi kullanır.

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 Bu getsişleve dikkat edin: öğretmeninizin zihninizde çok uzun bir giriş yaparak aklınızda bir rootkit çalıştırmasına izin verebilecek bir güvenlik açığı vardır ...


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

Çok golfed değil ve şu anda (sadece sağ?, Bunu bir kaç kez çalıştırabilirsiniz) birden çok terim işleyemez, ancak işleyebilir n^x, x^nve ngirdi olarak.


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(...), işte bu yüzden dizeler
metaforik hale getirildi

@mniip: Hala Lua öğreniyorum. Bahşiş için teşekkürler.
Kyle Kanos

1
OP sadece “kafasında hesaplayabilir” kodunu aradığı için, bir işlev tanımlamak ve lyerel olarak ilan etmekle uğraşmazdım. Sadece girişin kaydedilmesini abekleyin ve çıkışın kaydedileceğini söyleyin l.
Martin Ender

Parantezleri atlayabilirsiniz a:find("x"), ayrıca 1thenyalnızca Lua 5.2
mniip

@mniip: Whoa, ()isteğe bağlı olan oldukça havalı . 1thenBen (tez sonra karışıklık şey yukarı istemiyorum b / c tamamlanmadan CPU güncellemelerini yapmıyorum) 5.2 yok gibi sadece giderilmiştir.
Kyle Kanos

3

ECMAScript 6, 127 bayt

İşte regex girişimim (değiştirme sırasındaki tek bir regex ve biraz mantık kullanarak):

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

Bu giriş dizgisinin saklanmasını bekler ive sonucu döndürür. ECMAScript 6 uyumlu bir konsolda deneyin (Firefox'unki gibi).


2

sed, 110

Kelimenin tam anlamıyla alınması “Cevapların ne dediği açıkça belli olduğu sürece, hiçbir şekilde sadeleştirilmeleri veya tam olarak yukarıda gösterildiği gibi biçimlendirilmeleri gerekmez”:

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

Bayt sayısı rbayrak için 1 içerir .

Ungolfed, yorumlarla:

# 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

Örnek çalışma:

$ 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

Bahse girerim bu daha fazla golf oynayabilirdi; bu benim ilk denemem sed. Eğlence!


1

Ruby, 152

... veya 150, yazdırmaya gerek duymuyorsanız ... veya 147, ayrıca kendinize katılmanız gereken bir diziyle de uygunsanız.

koşmak 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
}*''

Bununla ilgili temel sorunum, uygun bölünmenin aldığı karakter sayısı. Düşünebilmemin tek yolu , kendi sonuçlarını split(/(?<!\^)([-+])/)veren +ve -aldıkları şeydi . Daha iyi bir çözüm için herhangi bir ipucu?

Ayrıca, sboş değilse geri dönmek için daha kısa bir yol var mı , yoksa geri dönmek ymi? Kullandım s[0]?y:smı JS'de ben sadece yaparım s||y, ama ""Ruby'de acımasızlık olur.


Bir bakış açısı iddia böyle yardımcı olur split(/(?<!\^)(?=[-+])/)mu?
DLosc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.