乘以两个整数多项式


14

您的任务是采用两个单变量整数多项式表达式,并将它们乘以其未经简化的第一项主要从左到右展开(对于二项式,则为 AKA FOIL)。请勿组合类似的字词或对结果重新排序。为了更清楚地了解扩展,请按顺序将第一个表达式中的第一个项乘以第二个表达式中的每个项,然后继续在第一个表达式中进行操作,直到所有项都已与所有其他项相乘。表达式将以简化的LaTeX变体形式给出。

每个表达式将是一个由一系列术语组成的序列,这些序列由+(每边正好有一个空格)隔开。每个术语将符合以下正则表达式:(PCRE表示法)

-?\d+x\^\d+

用简单的英语来说,该术语是一个可选的前导,-后跟一个或多个数字,后跟x一个非负整数幂(带有^

完整表达式的示例:

6x^3 + 1337x^2 + -4x^1 + 2x^0

当插入乳胶,将得到6x3+1337x2+4x1+2x0

输出也应符合此格式。

由于方括号不会以此格式包围指数,因此LaTeX实际上会错误地呈现多位数的指数。(例如,4x^3 + -2x^14 + 54x^28 + -4x^5呈现为4x3+2x14+54x28+4x5)你并不需要考虑到这一点,你不应该包括括号中的输出。

示例测试用例

5x^4
3x^23

15x^27

6x^2 + 7x^1 + -2x^0
1x^2 + -2x^3

6x^4 + -12x^5 + 7x^3 + -14x^4 + -2x^2 + 4x^3

3x^1 + 5x^2 + 2x^4 + 3x^0
3x^0

9x^1 + 15x^2 + 6x^4 + 9x^0

4x^3 + -2x^14 + 54x^28 + -4x^5
-0x^7

0x^10 + 0x^21 + 0x^35 + 0x^12

4x^3 + -2x^4 + 0x^255 + -4x^5
-3x^4 + 2x^2

-12x^7 + 8x^5 + 6x^8 + -4x^6 + 0x^259 + 0x^257 + 12x^9 + -8x^7

规则与假设

  • 您可以假定所有输入都符合此确切格式。针对此挑战,未定义其他格式的行为。
    • 应该注意的是,只要以符合上述格式的字符串形式读入两个多项式,则任何采用两个多项式的方法都是有效的。
  • 多项式的顺序很重要,这取决于产品扩展的预期顺序。
  • 您必须支持输入系数介于128127之间,输入指数最大为255
    • 之间输出系数的16,25616,384和指数高达510因此必须得到支持。
  • 您可以假设每个输入多项式包含的项不超过16个
    • 因此,您必须(至少)在输出中最多支持256个术语
  • 系数为零的项应保留原样,并正确组合指数
  • 输入中允许使用负零,但在语义上与正零是无法区分的。始终输出正零。不要忽略零项。

高尔夫快乐!祝好运!



2
@LuisfelipeDejesusMunoz我想不是。解析是挑战的一个组成部分,OP表示:“应该注意的是,采用两个多项式的任何方法都是有效的,只要将两个多项式都以符合上述格式的字符串形式读入即可。 ”(加了强调)
朱塞佩

Answers:


4

[R 159个 153 148字节的

function(P,Q,a=h(P),b=h(Q))paste0(b[1,]%o%a[1,],"x^",outer(b,a,"+")[2,,2,],collapse=" + ")
h=function(s,`/`=strsplit)sapply(el(s/" . ")/"x.",strtoi)

在线尝试!

我真的很想使用outer,因此肯定可以找到一种更有效的方法。


4

Haskell131122字节

(%)=drop
f s=do(a,t)<-reads s;(i,u)<-reads$2%t;(a,i):f(3%u)
p!q=3%do(a,i)<-f p;(b,j)<-f q;" + "++shows(a*b)"x^"++show(i+j)

在线尝试!

f从字符串中解析多项式,!将它们中的两个相乘并格式化结果。

H.PWiz保存了9个字节。谢谢!

不打高尔夫球

type Monomial = (Int, Int) -- a^i
type Polynomial = [Monomial]

parse :: String -> Polynomial
parse s = do (a, s')  <- reads s
             (i, s'') <- reads (drop 2 s')
             (a, i) : parse (drop 3 s'')

(!) :: String -> String -> String
p!q = drop 3 (concat terms)
  where terms    = [term (a*b) (i+j) | (a,i) <- p', (b,j) <- q']
        term a i = concat [" + ", show a, "x^", show i]
        p'       = parse p
        q'       = parse q



2

Ruby102100 98字节

->a,b{a.scan(w=/(.*?)x.(\d+)/).map{|x|b.scan(w).map{|y|(eval"[%s*(z=%s;%s),z+%s]"%y+=x)*"x^"}}*?+}

在线尝试!

怎么样?

第一步:从两个多项式中获取所有数字:scan以字符串对数组的形式返回数字。然后,对两个列表进行笛卡尔乘积运算。现在,我们有了所有需要的数字,但顺序仍然错误。

例如:如果我们乘3x^4-5x^2,我们得到的数字为[["3","4"],["-5","2"]],第一个想法就是ZIP和扁平此列表中,然后把数字填进被当做表达式[3*-5, 4+2]。实际上,我们不需要对数字进行重新排序,我们可以使用一个临时变量在表达式内部进行处理:表达式变为[3*(z=4,-5),z+2]

对这些表达式求值后,我们得到系数和指数,我们需要使用 "x^",然后使用进行所有项的连接"+"


2

哈斯克尔, 124121字节

import Data.Lists
f!x=map f.splitOn x
z=read!"x^"!"+"
a#b=drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)

注意:TIO缺乏Data.Lists,所以我导入Data.Lists.SplitData.List在线尝试!

编辑:-3个字节,感谢@Lynn。


这实际上是123个字节!f!x=map f.splitOn x然后z=read!"x^"!"+"保存一个字节;最后一行drop 3$do[u,v]<-z a;[p,q]<-z b;" + "++shows(u*p)"x^"++show(v+q)节省了另外两个。120字节
Lynn

1
@Lynn:TIO版本导入Data.List而不是Data.Lists,所以它是+1字节。
nimi



1

Python 2,193字节

import re
f=re.finditer
lambda a,b:' + '.join(' + '.join(`int(m.group(1))*int(n.group(1))`+'x^'+`int(m.group(2))+int(n.group(2))`for n in f('(-?\d+)x\^(\d+)',b))for m in f('(-?\d+)x\^(\d+)',a))

在线尝试!

旁注:第一次参加标准高尔夫挑战赛,对不起,如果尝试失败了哈哈


3
欢迎来到PPCG!我不是Python程序员,但可能还有一些改进的空间。也许您可以在Python 打高尔夫球技巧<所有语言>打高尔夫球技巧中找到帮助!希望您喜欢在这里度过的时光:-)
朱塞佩


1
一些快速高尔夫的161字节。尽管查看其他python答案,re.finditer但这可能不是最短的方法
Jo King

1

视网膜,110字节

\S\S+(?=.*\n(.+))
 $1#$&
|" + "L$v` (-?)(\d+)x.(\d+).*?#(-?)(\d+)x.(\d+)
$1$4$.($2*$5*)x^$.($3*_$6*
--|-(0)
$1

在线尝试!说明:

\S\S+(?=.*\n(.+))
 $1#$&

在第一个输入中的每个术语前加上a #,第二个输入的副本和一个空格。这意味着第二个输入的副本中的所有术语均以空格开头,而第一个输入的所有术语均不带空格。

|" + "L$v` (-?)(\d+)x.(\d+).*?#(-?)(\d+)x.(\d+)
$1$4$.($2*$5*)x^$.($3*_$6*

使第二个输入中的所有术语副本与第一个输入中的相应术语匹配。连接任何-符号,乘以系数,然后加上索引。最后,将所有结果替换项与字符串连接在一起 + 

--|-(0)
$1

删除任何对-并转换-00


1

SNOBOL4(CSNOBOL4) 192个 176字节

	P =INPUT
	Q =INPUT
	D =SPAN(-1234567890)
P	P D . K ARB D . W REM . P	:F(O)
	B =Q
B	B D . C ARB D . E REM . B	:F(P)
	O =O ' + ' K * C 'x^' W + E	:(B)
O	O ' + ' REM . OUTPUT
END

在线尝试!

	P =INPUT				;* read P
	Q =INPUT				;* read Q
	D =SPAN(-1234567890)			;* save PATTERN for Digits (or a - sign); equivalent to [0-9\\-]+
P	P D . K ARB D . W REM . P	:F(O)	;* save the Koefficient and the poWer, saving the REMainder as P, or if no match, goto O
	B =Q					;* set B = Q
B	B D . C ARB D . E REM . B	:F(P)	;* save the Coefficient and the powEr, saving the REMainder as B, or if no match, goto P
	O =O ' + ' K * C 'x^' W + E	:(B)	;* accumulate the output
O	O ' + ' REM . OUTPUT			;* match ' + ' and OUTPUT the REMainder
END




1

果冻,28个字节

ṣ”+ṣ”xV$€)p/ZPSƭ€j⁾x^Ʋ€j“ + 

在线尝试!

完整程序。将两个多项式作为两个字符串的列表。

说明(扩展形式)

ṣ”+ṣ”xV$€µ€p/ZPSƭ€j⁾x^Ʋ€j“ + ” Arguments: x
         µ                     Monadic chain.
          €                    Map the monadic link over the argument.
                               Note that this will "pop" the previous chain, so
                               it will really act as a link rather than a
                               sub-chain.
ṣ”+                             ṣ, right = '+'.
                                Split the left argument on each occurrence of
                                the right.
                                Note that strings in Jelly are lists of
                                single-character Python strings.
        €                       Map the monadic link over the argument.
       $                         Make a non-niladic monadic chain of at least
                                 two links.
   ṣ”x                            ṣ, right = 'x'.
                                  Split the left argument on each occurrence of
                                  the right.
      V                           Evaluate the argument as a niladic link.
            /                  Reduce the dyadic link over the argument.
           p                    Cartesian product of left and right arguments.
                       €       Map the monadic link over the argument.
                      Ʋ         Make a non-niladic monadic chain of at least
                                four links.
             Z                   Transpose the argument.
                 €               Map the monadic link over the argument.
                ƭ                 At the first call, call the first link. At the
                                  second call, call the second link. Rinse and
                                  repeat.
              P                    Product: ;1×/$
               S                   Sum: ;0+/$
                  j⁾x^           j, right = "x^".
                                 Put the right argument between the left one's
                                 elements and concatenate the result.
                        j“ + ” j, right = " + ".
                               Put the right argument between the left one's
                               elements and concatenate the result.

混叠

)与相同µ€。暗示
尾随,可以省略。

算法

假设我们有以下输入:

["6x^2 + 7x^1 + -2x^0", "1x^2 + -2x^3"]

第一个过程是解析,应用于两个多项式的每一个。让我们处理第一个"6x^2 + 7x^1 + -2x^0"

第一步是用分割字符串'+',以分隔术语。结果是:

["6x^2 ", " 7x^1 ", " -2x^0"]

下一步是将每个字符串除以'x',以将系数与指数分开。结果是这样的:

[["6", "^2 "], [" 7", "^1 "], [" -2", "^0"]]

当前,这些字符串中似乎有很多垃圾,但实际上这些垃圾并不重要。这些字符串都将被评估为尼拉迪奇果冻链接。琐碎地,空格并不重要,因为它们不在数字的数字之间。因此,我们可以对以下内容进行评估,但仍获得相同的结果:

[["6", "^2"], ["7", "^1"], ["-2", "^0"]]

^来看多一点令人不安,但它们实际上并不无论做任何事情!好吧,这^是按位XOR原子,但是niladic链的作用类似于monadic链接,只是第一个链接实际上是参数,而不是参数(如果是niladic)。如果不是,则链接的参数为0。该指数有^S作为他们的第一个字符,而^不是译注,这样的说法被认为是0。字符串的其余部分(即数字)是的正确参数^。因此,例如,^20 异或 2=2。明显,0 异或 ñ=ñ。所有指数都是整数,所以我们很好。因此,对此进行评估而不是以上内容不会更改结果:

[["6", "2"], ["7", "1"], ["-2", "0"]]

开始了:

[[6, 2], [7, 1], [-2, 0]]

此步骤还将转换"-0"0

由于我们要解析两个输入,因此解析后的结果将是这样:

[[[6, 2], [7, 1], [-2, 0]], [[1, 2], [-2, 3]]]

解析到此完成。下一个过程是乘法。

我们首先采用以下两个列表的笛卡尔乘积:

[[[6, 2], [1, 2]], [[6, 2], [-2, 3]], [[7, 1], [1, 2]], [[7, 1], [-2, 3]], [[-2, 0], [1, 2]], [[-2, 0], [-2, 3]]]

制作了许多对,每个对按顺序从左侧列表中的一个元素到右侧的一个。这也恰好是输出的预期顺序。这个挑战确实要求我们应用乘法分布,因为在此之后我们不要求进一步处理结果。

每对中的对表示我们要相乘的项,第一个元素是系数,第二个元素是指数。要乘以项,我们乘以系数,然后将指数相加(一种XCbXd=一种bXCXd=一种bXCXd=一种bXC+d)。我们该怎么做?让我们处理第二对[[6, 2], [-2, 3]]

我们首先换位:

[[6, -2], [2, 3]]

然后,我们取第一对的乘积和第二对的和:

[-12, 5]

代码的相关部分PSƭ€实际上并没有为每对术语重置其计数器,但是由于它们是成对的,因此不需要。

处理所有成对的术语,我们有:

[[6, 4], [-12, 5], [7, 3], [-14, 4], [-2, 2], [4, 3]]

在这里,乘法完成了,因为我们不必合并类似的术语。最终过程是Prettyfying。

我们首先加入"x^"

[[6, 'x', '^', 4], [-12, 'x', '^', 5], [7, 'x', '^', 3], [-14, 'x', '^', 4], [-2, 'x', '^', 2], [4, 'x', '^', 3]]

然后我们加入列表" + "

[6, 'x', '^', 4, ' ', '+', ' ', -12, 'x', '^', 5, ' ', '+', ' ', 7, 'x', '^', 3, ' ', '+', ' ', -14, 'x', '^', 4, ' ', '+', ' ', -2, 'x', '^', 2, ' ', '+', ' ', 4, 'x', '^', 3]

请注意,列表中仍然有数字,因此它并不是真正的字符串。但是,Jelly有一个名为“字符串化”的过程,该过程在程序执行结束时立即运行以打印出结果。对于深度为1的列表,它实际上只是将每个元素转换为其字符串表示形式并将字符串连接在一起,因此我们得到了所需的输出:

6x^4 + -12x^5 + 7x^3 + -14x^4 + -2x^2 + 4x^3

1

JavaScript,112110字节

我发现了两个长度相同的选择。使用currying语法进行调用:f(A)(B)

A=>B=>(P=x=>x.split`+`.map(x=>x.split`x^`))(A).flatMap(a=>P(B).map(b=>a[0]*b[0]+'x^'+(a[1]- -b[1]))).join` + `

A=>B=>(P=x=>x.split`+`.map(x=>x.split`x^`))(A).flatMap(([c,e])=>P(B).map(([C,E])=>c*C+'x^'+(e- -E))).join` + `

-2字节(Luis):删除split定界符周围的空格。


JavaScript,112字节

使用String.prototype.matchAll

A=>B=>(P=x=>[...x.matchAll(/(\S+)x.(\S+)/g)])(A).flatMap(a=>P(B).map(b=>a[1]*b[1]+'x^'+(a[2]- -b[2]))).join` + `


1
split' + ' => split'+'保存2个字节
Luis felipe De耶稣Munoz,


@EmbodimentofIgnorance我的错,我误读了Luis的评论。我以为是关于join
阿纳尔德
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.