多项式的符号微分


20

象征性的区别1:去了Coefishin'

任务

编写一个程序,将x的多项式从stdin(1 <deg(p)<128)引入并进行微分。输入多项式将是以下形式的字符串:

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

其中每个项的系数是整数(-128 <a <128)。每个术语由一个空格,一个+和另一个空格分隔;线性和常数项如上所示(即no x^0x^1)。项将按照递增的顺序出现,并且那些零系数的幂被省略。所有系数为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"

计分

分数是程序的长度(以字节为单位),如果您使用内置或代数符号库,则将其乘以三。


我不敢相信我们在这里还没有遇到这个挑战!
flawr

5
@flawr 我们做了。(尽管其中一个还需要其他功能,并且对输出格式没有严格的规定。)
Martin Ender 2015年

@flawr我也这么想...但是我没有找到Martin的链接文章搜索。呃,好吧。
hYPotenuser

Answers:


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>

这与an匹配x,后跟一个空格,即x线性项的(如果存在),并将其删除。我们可以确定在它后面有一个空格,因为多项式的次数总是至少为2。

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

这将系数与指数相乘。这与1系数中的一个匹配,并通过前瞻将其替换为整个对应的指数。

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

通过匹配尾随1(由超前确保),可以减少所有剩余的指数。如果有可能匹配^11(和单词边界),我们将其删除,以确保正确显示线性项。

对于压缩,我们注意到大多数情况不会相互影响。(\^1)?如果在第三种情况下的前瞻性是正确的,则不会匹配,因此我们可以将这两个条件放在一起作为

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

现在我们已经有了第二种情况所需的前瞻性,并且其他情况在匹配时永远都不可能成立x,因此我们可以简单地1将a 推广为\w

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

第一种情况实际上与其他情况没有任何共同之处,因此我们将其分开。


9

CJam,43 41字节

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

感谢@ 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

Perl,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'

感谢Denis -1b


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," + "))

这将创建一个lambda函数,该函数接受一个字符串并返回一个字符串。这些内在函数模仿了评估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

JavaScript 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

Python 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使用该函数而不是使用lambda是因为我可以将指数减1分配给e,然后再使用四次。主要烦人的事情是必须在字符串和整数之间来回转换,尽管Python 2的反引号运算符对此有所帮助。

然后,我们将输入分成多个项,并调用d其中的每个项"x",从而消除常数项。结果重新结合在一起并打印。


2

CJam,62 57 55 49字节

好吧,在我什至注意到站点已备份之前,Dennis对此感到羞耻。但是无论如何,这是我的创造:

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

最新版本使用@Dennis建议的快捷方式保存了一些字节(使用变量,并在空格处而不是处分割+)。

在线尝试


1
保存在变量中比在else块中弹出要短。例如,_({'^a\}{;}?比延长1个字节:T({T'^a\}&
丹尼斯

1
如果您在空格处而不是加号处进行拆分,则~在其余的else块中不需要,也可以消除该空格。
丹尼斯

@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

Python 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

0

Python 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

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

不幸的是,DLosc重命名split方法并在特定功能中执行区分的技巧并没有缩短我的代码...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.