미적분학으로 도와주세요!


52

나는 프로그래밍을 좋아하고 모든 언어를 알고 있지만 수학을 잘합니다. 불행히도, 우리 학교는 컴퓨터 학생들이 1 년의 미적분학을 치러야한다고 요구합니다. 다음 주에 테스트가 진행 중이며 파생 상품에 대한 공식을 모릅니다.

수식을 찾도록 도와주세요. 치트 시트- 4*x^3-2입력으로 표현과 같은 표현을 취하고 미분을 출력 하는 프로그램 (가능한 한 짧게 선생님이 알지 못하도록 프로그램)이 필요합니다 . (어쨌든 내 머리에서 모든 계산을 수행하기 때문에 입력 및 출력이 명령 줄 인수, STDIN, STDOUT 또는 기타를 사용하는지 상관하지 않습니다.)

이 테스트는 다음 유형의 기능을 다룹니다.

  • -3또는 같은 상수8.5
  • x^0.5또는 같은 전원 기능x^-7
  • 0.5^x또는 같은 지수 함수 7^x(기본은 항상 양수 임)
  • 3*x^5or 와 같은 함수를 곱한 상수-0.1*0.3^x
  • 여러 기능의 합과 차이 -5*x^2+10-3^x

선생님은 위와 같이 항상 같은 방식으로 질문을 구성합니다. 또한 분수, pi 또는 e 와 같은 숫자 또는 실제로 큰 숫자 (1,000보다 큰 숫자)를 사용하지 않습니다 . 그는 괄호를 사용하지 않으며 항상 별표 ( *)를 사용하여 곱셈을 표시 합니다. 사용되는 유일한 변수는 항상 x 입니다.

반면에, 선생님은 답변에 대해 관대합니다. 답이 무엇을 말하는지 분명한 한, 그것들은 전혀 단순화되거나 위에 표시된대로 정확하게 포맷 될 필요가 없습니다.

모든 언어를 사용할 수 있지만 파생 상품을 직접 파악할 수는 없습니다. 따라서 프로그램이 내장 함수를 사용하여 방정식을 다루거나 미분을 계산하면 사용할 수 없습니다.

테스트 중에는 치트 시트에있는 프로그램 이외의 다른 파일이나 인터넷에 액세스 할 수 없습니다.

참고 :이 시나리오는 전적으로 허구입니다. 실제 생활에서 부정 행위와 다른 사람의 부정 행위를 돕는 것은 잘못이며 절대로 수행해서는 안됩니다.


3
그것이 x항상 차별화되는 변수 라고 기대할 수 있습니까 ?
Kyle Kanos 2016 년

2
답을 단순화해야합니까? 같은 용어를 추가해야합니까?
Rainbolt

1
실제로 골프 를 타면 scrblnrd3.github.io/Javascript-CAS의 미적분 프로젝트 가 빛날
때가 된

1
우리는 Parens가 없다고 가정해야합니까?
찰스

2
나는이 질문들 대부분을 편집 할 때 답했다 . 과학적 표기법이나 제품 규칙은 없습니다.
Ypnypn

답변:


8

텅스텐은 136 134 109 [아래 그의 논평 칼레 덕분]

제품 및 체인 규칙에 대한 제한된 지원.

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}

예:

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]

이것은 "내장 함수를 사용하여 방정식을 처리하거나 미분을 계산"하지 않습니다. 패턴 일치 만 포함됩니다 *.

[* 글쎄 ... 기술적으로 통역사도 입력에서 일종의 AST를 파싱하고 빌드합니다]


언 골프 드 :

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
}

이것은 다른 버전 입니다. 당신은 작성하지 않아도 Power, Times등하지만 당신 golfed 버전을 향상시킬 것이다 얼마나 IDK,하지만 당신은 적어도 하나가 Times당신이 데프 수 있도록 거기에. 일부 문자를 저장하십시오. 또한 ungolfed 버전에서는이라고 표시되어 d[expr_]:= v/...있습니다.

1
@Calle "IDK로 얼마나 많은 골프 버전을 향상시킬 수 있을까요?"-25 바이트! 건배!
Saran

26

-121122

(+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

테스트:

$ 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

내가 정규식을 배우는 또 다른 이유는 ...
Kyle Kanos

3
@KyleKanos하지 마십시오. 정규식은 나쁘고 정규식은 훌륭합니다.
mniip

Meh, 나를 이길. 나쁘지 않다! (PS : 정규 표현식이 아름답습니다)
Martin Ender

8
나는 여기서 무슨 일이 일어나고 있는지 전혀 모른다. +1
qwr

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

7

하스켈 38 문자

함수 d는 함수를 받아서 함수를 반환합니다. 그것은 power series 형식으로 입력되고 같은 방식으로 출력됩니다 (어떤 유형이든).

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

예를 들어, 입력 x->x^2하면을 얻습니다 x->2*x.

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

그리고 지수 함수.

λ <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
그러나 OP는 수학을 모른다! 그의 지수 입력을 거듭 제곱으로 표현할 수 있을까요?
Saran

그는 분명히 표기법을 알고 있습니다. 그는 미분 연산을 수행하는 방법을 모른다.
PyRulez 2016 년

5
이 처리 할 수 ​​있습니까 2^x?
Kyle Kanos

5
이 마법은 무엇입니까?
Christofer Ohlsson

7
4*x^3-2OP에서 요구하는대로 "입력으로 식 (예 :)을 취하는 위치"를 알 수 없습니다 .
Gabe

5

프롤로그 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).

지원 사업자 : 이진 +, 이진 -, 이진 *, 이진 ^, 단항 -. 단항 +은 지원되지 않습니다.

샘플 실행 :

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

프롤로그가 ^-순서대로 실행되면 혼동됩니다 . 공백 사이에 삽입해야 ^하고 -올바르게 표현을 구문 분석 할 수.

선생님이 방정식의 혼란에 신경 쓰지 않기를 바랍니다.

미친 시간 :

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

선생님, 내가 아는 것 같아요! 초자연적 인 능력을 가진 사람이 머리 속에서 도서관 패턴 매칭 기능을 수행하는 학생들을 감지하는 것은 아닌가요?

따라서 사용 sscanf은 의문의 여지가 없지만 걱정하지 마십시오.

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

실행 예제 (입력 on stdin; 출력은 stdout) :

4 * x ^ 3-2

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

이 형식은 12*x^2선생님 보다 당신이 답을 스스로 계산하고 다른 사람으로부터 복사하여 속임수를 쓰지 않았 음을 확신 할 수 있기 때문에이 형식은 단지보다 낫습니다 !

x + 2 ^ x

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

에 약간의 도메인 문제가 x=0있지만 거의 모든 곳 에서 정확합니다 !

참고로, 여기는 골치 아픈 읽을 수있는 (단순한 필사자) 버전입니다. 5 개의 상태와 5 개의 입력 문자 범주가있는 상태 머신을 사용합니다.

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

추신 gets: 그 기능을 조심하십시오 : 그것은 너무 긴 입력을 제공하여 교사가 당신의 마음에 루트킷을 실행할 수있는 보안 취약점이 있습니다 ...


3

루아 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

매우 golfed되지 않음 현재 (당신이 바로?, 그것을 몇 번 실행할 수 있습니다) 여러 조건을 처리 할 수 있지만 처리 할 수있는 n^x, x^n그리고 n입력으로.


언 골프 ...

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(...), 그것이 문자열이 결국 메타 테이블을 얻는 이유입니다.
mniip

@ mniip : 여전히 루아를 배우고 있습니다. 팁 고마워.
Kyle Kanos

1
OP는 "그의 머리에서 계산할 수있는"코드 만 찾고 있기 때문에 함수를 정의하고 l로컬을 선언하는 데 신경 쓰지 않습니다 . 입력이 저장되고 a출력이에 저장 될 것이라고 기대하십시오 l.
Martin Ender

당신은 괄호를 생략 할 수 a:find("x")도 있습니다, 1then5.2 루아에서 작동
mniip

@ mniip : 우와, 그건 정말 멋진 ()선택입니다. 은 1then내가 (논문 후에 내가 엉망 아무것도 최대 싶지 않아 C / B 완료 될 때까지 모든 CPU 업데이트를 수행하지 않음) 5.2을 가지고 있지 않는 한 단지 수정되었습니다.
Kyle Kanos

3

ECMAScript 6, 127 바이트

다음은 정규식 시도입니다 (대체 콜백에 단일 정규식과 일부 논리 사용).

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

이것은 입력 문자열이 저장 될 것으로 예상 i하고 단순히 결과를 반환합니다. ECMAScript 6 호환 콘솔 (예 : Firefox)에서 사용해보십시오.


2

sed, 110

문자 그대로 "답변이 무엇을 말하는지 분명한 한, 그것들을 전혀 단순화하거나 위에 표시된대로 정확하게 포맷 할 필요는 없습니다":

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

바이트 수에는 r플래그에 1이 포함됩니다 .

코멘트가없는 언 골프 드 :

# 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

샘플 실행 :

$ 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

나는 이것이 더 골프를 칠 수 있다고 확신한다. 의 첫 번째 시도 sed입니다. 장난!


1

루비, 152

... 또는 인쇄 할 필요가없는 경우 150 또는 직접 참여해야하는 배열에 문제가없는 경우 147

와 실행 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}*''

언 골프 :

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

이 문제에 대한 나의 주요 문제는 적절한 분할에 필요한 문자 수입니다. 내가 생각할 수있는 유일한 다른 방법이었다 split(/(?<!\^)([-+])/)있는이 제공 +하고 -자신의 결과로. 더 나은 솔루션에 대한 힌트가 있습니까?

또한 s비어 있지 않으면 반환 하는 더 짧은 방법이 y있습니까? 그렇지 않으면 반환 합니까? 내가 사용 s[0]?y:s했습니까? JS에서는 그냥 할 s||y것이지만 ""Ruby에서는 진실합니다.


예견 주장이 도움이 split(/(?<!\^)(?=[-+])/)되겠습니까?
DLosc 2018 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.