다항식의 상징적 미분


20

상징적 분화 1 : 사라지다

태스크

stdin (1 <deg (p) <128) 에서 x 의 다항식을 취하여 차별화 하는 프로그램을 작성 하십시오. 입력 다항식은 다음 형식의 문자열입니다.

"a + bx + cx^2 + dx^3 +" ...

여기서 각 항의 계수는 정수입니다 (-128 <a <128). 각 용어는 하나의 공백, + 및 다른 공백으로 구분됩니다. 선형 및 상수 항은 위와 같이 나타납니다 (예 : no x^0또는 x^1). 항은 증가하는 순서대로 나타나며 계수 0 인 제곱 은 생략됩니다. 계수 1 또는 -1을 가진 모든 항은 해당 계수를 명시 적으로 표시합니다.

결과물은 정확히 같은 형식이어야합니다. 출력의 계수는 127 * 127 == 16129만큼 클 수 있습니다.

"3 + 1x + 2x^2" ==> "1 + 4x"
"1 + 2x + -3x^2 + 17x^17 + -1x^107" ==> "2 + -6x + 289x^16 + -107x^106"
"17x + 1x^2" ==> "17 + 2x"

채점

내장 대수 또는 기호 대수를 수행하는 라이브러리를 사용하는 경우 점수는 프로그램 길이 (바이트)이며 3을 곱한 값입니다.


우리가 아직이 도전을 겪지 않았다는 것을 믿을 수 없습니다!
flawr

5
@flawr 우리는 일종의 않았다. (하지만 다른 기능이 필요했지만 출력 형식에 대한 엄격한 규칙은 없었습니다.)
Martin Ender

@flawr 나는 똑같은 생각을했지만 ... Martin의 링크 된 게시물 검색을 찾지 못했습니다. 아 잘
hYPotenuser

답변:


15

망막 , 53 43 42 41 40 35 바이트

^[^x]+ |(\^1)?\w(?=1*x.(1+)| |$)
$2

계산을 위해 각 줄은 별도의 파일로 이동하지만 -s플래그 와 함께 Retina를 호출하여 위의 파일을 단일 파일로 실행할 수 있습니다 .

이것은 입력 문자열의 숫자가 단항으로 주어질 것으로 예상하고 동일한 형식으로 출력을 산출합니다. 예 :

1 + 11x + -111x^11 + 11x^111 + -1x^11111
-->
11 + -111111x + 111111x^11 + -11111x^1111

대신에

1 + 2x + -3x^2 + 2x^3 + -1x^5
-->
2 + -6x + 6x^2 + -5x^4

설명

이 코드는 단일 정규식 대체를 설명하며 기본적으로 4 개의 대체가 하나로 압축됩니다. 분기 중 하나만 그룹을 채울 수 $2있으므로 다른 세 가지 중 하나 라도 일치하면 문자열에서 일치하는 항목이 삭제됩니다. 따라서 우리는 네 가지 경우를 개별적으로 볼 수 있습니다.

^[^x]+<space>
<empty>

문자열의 처음부터 공백없이 닿을 수 있다면 x첫 번째 항은 상수 항이며이를 삭제합니다. 의 탐욕으로 인해 +, 이것은 또한 일정 기간 이후의 플러스와 두 번째 공백과 일치합니다. 상수 항이 없으면이 부분은 절대 일치하지 않습니다.

x(?= )
<empty>

이는 x뒤에 공백 x이있는 선형 용어 (있는 경우) 와 일치하여 제거합니다. 다항식의 차수가 항상 2 이상이므로 그 뒤에 공백이 있는지 확인할 수 있습니다.

1(?=1*x.(1+))
$1

계수에 지수를 곱합니다. 이것은 1계수에서 단일 을 일치 시키고 lookahead를 통해 해당하는 전체 지수로 대체합니다.

(\^1)?1(?= |$)
<empty>

이렇게하면 후행을 일치시켜 1(예측에 의해 보장됨) 나머지 지수를 모두 줄 입니다. 일치 ^11하는 단어 (및 단어 경계)가 가능하면 선형 용어를 올바르게 표시하는 대신이를 제거합니다.

압축의 경우 대부분의 조건이 서로 영향을 미치지 않습니다. (\^1)?세 번째 경우의 예견이 참이면 일치하지 않으므로이 두 가지를 함께

(\^1)?1(?=1*x.(1+)| |$)
$2

이제 우리는 이미 두 번째 경우에 필요한 내다을 가지고 일치 할 때 다른 사람은 사실 없다 x우리는 단순히 일반화 할 수 있도록, 1A와를 \w:

(\^1)?\w(?=1*x.(1+)| |$)
$2

첫 번째 사례는 다른 사례와 공통점이 없기 때문에 별도로 유지합니다.


9

CJam, 43 41 바이트

Qleu'^/';*'+/{~:E[*'x['^E(]]E<}/]1>" + "*

하나의 버그를 지적하고 2 바이트를 골라내는 @ jimmy23013에게 감사드립니다!

CJam 통역사 에서 온라인으로 사용해보십시오 .

작동 원리

Q           e# Leave an empty array on the bottom of the stack.
l           e# Read a line from STDIN.
eu'^/';*    e# Convert to uppercase and replace carets with semicolons.
'+/         e# Split at plus signs.

{           e# For each resulting chunk:
  ~         e#   Evaluate it. "X" pushes 1 and ";" discards.
            e#   For example, "3X" pushes (3 1) and "3X;2" (3 2).
   :E       e#   Save the rightmost integer (usually the exponent) in E.
   [        e#
     *      e#   Multiply both integers.
            e#   For a constant term c, this repeats the empty string (Q) c times.
     'x     e#   Push the character 'x'.
     ['^E(] e#   Push ['^' E-1].
   ]        e#
   E<       e#  Keep at most E elements of this array.
            e#  If E == 1, 'x' and ['^' E-1] are discarded.
            e#  If E == 2, ['^' E-1] is discarded.
            e#  If E >= 3, nothing is discarded.
}/          e#

]           e# Wrap the entire stack in an array.
1>          e# Discard its first element.
            e# If the first term was constant, this discards [""]. ["" 'x']
            e# or ["" 'x' ['^' E-1]], depending on the constant.
            e# In all other cases, it discards the untouched empty array (Q).
" + "*      e# Join all kept array elements, separating by " + ".

5

펄, 64 63 바이트

62b 코드 + 1 명령 줄 (-p)

현재로서는 놀랄 일이 아니지만 계속해서 줄이려고 노력할 것입니다.

s/(\d+)x.(\d+)/$1*$2."x^".($2-1)/eg;s/\^1\b|^\d+ . |x(?!\^)//g

사용 예 :

echo "1 + 2x + 3x^2" | perl -pe 's/(\d+)x.(\d+)/$1*$2."x^".($2-1)/eg;s/\^1\b|^\d+ . |x(?!\^)//g'

-1b 감사합니다 Denis


5

줄리아, 220 바이트

정규 표현식이 없습니다!

y->(A=Any[];for i=parse(y).args[2:end] T=typeof(i);T<:Int&&continue;T==Symbol?push!(A,1):(a=i.args;c=a[2];typeof(a[3])!=Expr?push!(A,c):(x=a[3].args[3];push!(A,string(c*x,"x",x>2?string("^",ex-1):""))))end;join(A," + "))

문자열을 받아들이고 문자열을 반환하는 람다 함수를 만듭니다. 내부 코드는 Julia 코드가 평가 될 때 발생하는 동작을 모방합니다. 문자열은 기호, 표현식 및 호출로 구문 분석됩니다. 실제로 전체 Julia 상징적 미분 함수를 작성하여 Julia의 일부로 제출하려고 할 수 있습니다.

언 골프 + 설명 :

function polyderiv{T<:AbstractString}(y::T)

    # Start by parsing the string into an expression
    p = parse(y)

    # Define an output vector to hold each differentiated term
    A = Any[]

    # Loop through the elements of p, skipping the operand
    for i in p.args[2:end]

        T = typeof(i)

        # Each element will be an integer, symbol, or expression.
        # Integers are constants and thus integrate to 0. Symbols
        # represent x alone, i.e. "x" with no coefficient or
        # exponent, so they integrate to 1. The difficulty here
        # stems from parsing out the expressions.

        # Omit zero derivatives
        T <: Int && continue

        if T == Symbol
            # This term will integrate to 1
            push!(A, 1)
        else
            # Get the vector of parsed out expression components.
            # The first will be a symbol indicating the operand,
            # e.g. :+, :*, or :^. The second element is the
            # coefficient.
            a = i.args

            # Coefficient
            c = a[2]

            # If the third element is an expression, we have an
            # exponent, otherwise we simply have cx, where c is
            # the coefficient.
            if typeof(a[3]) != Expr
                push!(A, c)
            else
                # Exponent
                x = a[3].args[3]

                # String representation of the differentiated term
                s = string(c*x, "x", x > 2 ? string("^", x-1) : "")

                push!(A, s)
            end
        end
    end

    # Return the elements of A joined into a string
    join(A, " + ")
end

3

C, 204 162 바이트

#define g getchar()^10
h,e;main(c){for(;!h&&scanf("%dx%n^%d",&c,&h,&e);h=g?g?e?printf(" + "):0,0:1:1)e=e?e:h?1:0,e?printf(e>2?"%dx^%d":e>1?"%dx":"%d",c*e,e-1):0;}

기본적으로 각 용어를 구문 분석하고 차별화 된 용어를 순서대로 인쇄합니다. 매우 간단합니다.


2

자바 스크립트 ES6, 108 바이트

f=s=>s.replace(/([-\d]+)(x)?\^?(\d+)?( \+ )?/g,(m,c,x,e,p)=>x?(c*e||c)+(--e?x+(e>1?'^'+e:''):'')+(p||''):'')

ES5 스 니펫 :

// ES5 version, the only difference is no use of arrow functions.
function f(s) {
  return s.replace(/([-\d]+)(x)?\^?(\d+)?( \+ )?/g, function(m,c,x,e,p) {
    return x ? (c*e||c) + (--e?x+(e>1?'^'+e:''):'') + (p||'') : '';
  });
}

[
  '3 + 1x + 2x^2',
  '1 + 2x + -3x^2 + 17x^17 + -1x^107',
  '17x + 1x^2'
].forEach(function(preset) {
  var presetOption = new Option(preset, preset);
  presetSelect.appendChild(presetOption);
});

function loadPreset() {
  var value = presetSelect.value;
  polynomialInput.value = value;
  polynomialInput.disabled = !!value;
  showDifferential();
}

function showDifferential() {
  var value = polynomialInput.value;
  output.innerHTML = value ? f(value) : '';
}
code {
  display: block;
  margin: 1em 0;
}
<label for="presetSelect">Preset:</label>
<select id="presetSelect" onChange="loadPreset()">
  <option value="">None</option>
</select>
<input type="text" id="polynomialInput"/>
<button id="go" onclick="showDifferential()">Differentiate!</button>
<hr />
<code id="output">
</code>


2

파이썬 2, 166 바이트

이봐,이게 생각보다 길어 보인다

S=str.split
def d(t):e="^"in t and int(S(t,"^")[1])-1;return`int(S(t,"x")[0])*(e+1)`+"x"[:e]+"^%d"%e*(e>1)
print" + ".join(d(t)for t in S(raw_input()," + ")if"x"in t)

이 함수 d는 상수가 아닌 용어 t를 사용하여 미분 값을 반환합니다. 내가 def람다 대신 함수를 사용하는 이유 는 지수 빼기 1에을 할당 할 수 있기 때문에 e다른 4 번 사용됩니다. 파이썬 2의 백틱 연산자가 도움이되지만 주요 성가신 것은 문자열과 int 사이에서 캐스트해야한다는 것입니다.

그런 다음 입력을 용어로 나누고 그 안에 d있는 각 항목을 호출 "x"하여 상수 용어를 제거합니다. 결과가 다시 결합되어 인쇄됩니다.


2

CJam, 62 57 55 49 바이트

글쎄, 데니스는 사이트가 백업되었다는 것을 알기 전에 이것을 부끄러워했습니다. 그러나 여기 내 창조물이 있습니다.

lS/{'x/:T,({T~1>:T{~T~*'xT~(:T({'^T}&}&" + "}&}/;

최신 버전은 @Dennis가 제안한 바로 가기를 사용하여 몇 바이트를 절약합니다 (변수 사용 및 대신 공간 분할 +).

온라인으로 사용해보십시오


1
변수에 저장하면 else 블록에서 팝하는 것보다 짧습니다. 예를 들어, _({'^a\}{;}?보다 1 바이트 더 깁니다 :T({T'^a\}&.
Dennis

1
더하기 부호 대신 공백으로 분할 ~하면 나머지 else 블록에서 필요하지 않으며 해당 블록도 제거 할 수 있습니다.
Dennis

@Dennis 감사합니다. 원래 더하기 부호를 제거하고 싶었지만의 존재를 테스트 할 때 제거됩니다 x. 내가있는 동안 더 많은 개선점을 발견했습니다. 대부분 변수에 값이 있으므로 실제로 필요한 위치를 호출하여 스택 조작을 절약 할 수 있습니다. 또한 a출력 생성을 초기에 최적화 할 때 삭제되어야 하는 길 을 잃었습니다 .
Reto Koradi

1

Pyth, 62 바이트

jJ" + "m::j"x^",*Fdted"x.1$"\x"x.0"kftTmvMcd"x^"c:z"x ""x^1 "J

정규식 대체를 사용하는 아주 못생긴 솔루션.


1

파이썬 3, 176 바이트

s=input().split(' + ')
y='x'in s[0]
L=map(lambda x:map(int,x.split('x^')),s[2-y:])
print(' + '.join([s[1-y][:-1]]+['x^'.join(map(str,[a*b,b-1])).rstrip('^1')for a,b in L]))

실제로 주요 성가심은 문자열과 정수를 변환해야합니다. 또한 상수 항이 필요한 경우 코드는 153 바이트입니다.


첫 번째 대답은 DLosc을 꺾기 위해 총격을 가한 것이었고 거기에 도달하지 못했습니다.
El'endia Starman 5

0

파이썬 2, 229 바이트

import os
print' + '.join([i,i[:-2]][i[-2:]=='^1'].replace('x^0','')for i in[`a*b`+'x^'+`b-1`for a,b in[map(int,a.split('x^'))for a in[[[i+'x^0',i+'^1'][i[-1]=='x'],i]['^'in i]for i in os.read(0,9**9).split(' + ')]]]if i[0]!='0')

0

파이썬 2, 174 바이트

print' + '.join(['%d%s%s'%(b[0]*b[1],'x'*(b[1]>1),'^%d'%(b[1]-1)*(b[1]>2))for b in[map(int,a.split('x^')if 'x^'in a else[a[:-1],1])for a in input().split(' + ')if 'x'in a]])

불행히도 split 메소드의 이름을 바꾸고 특정 함수에서 차별화를 수행하는 DLosc의 트릭은 내 코드를 단축시키지 않습니다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.