多項式の積分根を見つける


19

チャレンジ

課題は、入力としてn次多項式の係数を取り、方程式が成立するx の積分値を返すプログラムを作成することです。係数は、電力の減少または増加の順に入力として提供されます。すべての係数は整数であると想定できます

入出力

入力は、累乗の降順または昇順の方程式の係数になります。方程式の次数、つまりxの最大パワーは、入力の要素の総数よりも常に1少なくなります。

例えば:

[1,2,3,4,5] -> represents x^4 + 2x^3 + 3x^2 + 4x + 5 = 0 (degree = 4, as there are 5 elements)
[4,0,0,3] -> represents 4x^3 + 3 = 0 (degree = 3, as there are 3+1 = 4 elements)

出力は、与えられた式を満たすxの個別の積分値のみである必要があります。すべての入力係数は整数であり、入力多項式はゼロ多項式ではありません。与えられた方程式の解がない場合、出力は未定義です。

方程式に繰り返し根がある場合、その特定の根を一度だけ表示します。値は任意の順序で出力できます。また、入力に少なくとも2つの数字が含まれると想定します。

[1,5,6] -> (-3,-2)
[10,-42,8] -> (4)
[1,-2,0] -> (0,2)
[1, 1, -39, -121, -10, 168] -> (-4, -3, -2, 1, 7)
[1, 0, -13, 0, 36] -> (-3, -2, 2, 3)
[1,-5] -> (5)
[1,2,3] -> -

2番目の例の方程式にもルート0.2がありますが、0.2は整数ではないため表示されません。

得点

これはなので、最短のコード(バイト単位)が勝ちです!


7
注:近くに投票する前に、この質問であることを考慮してくださいではないの重複、この1。この問題に対する少なくとも1つのアプローチを考えることができますが、これは他の課題に対して簡単に修正することはできません(ただし、何を言っているのかはわかりませんが、それはあなた次第です; P)。
エリックアウトゴルファー

言語の整数範囲内でのみルートを返す必要があると仮定できますか?または、言語の整数型の範囲を増やしても、アルゴリズムは機能しますが、動作は同じままです。
Οurous

1
あなたの言語がそれらをサポートしている場合、ネイティブ多項式タイプも使用できますか?
-flawr

1
ソリューションが受け入れられない場合、プログラムは永久に実行されますか?
ジャックM

1
それは物事をシンプルに保つためです。
マニッシュクン

回答:


6

MATL13 12バイト

|stE:-GyZQ~)

オンラインでお試しください!

これは、整数係数の場合、任意のルートの絶対値が厳密に係数の絶対値の合計よりも小さいという事実を使用してます。

説明

[1 5 6]例として入力を検討してください。

|    % Implicit input. Absolute value
     % STACK: [1 5 6]
s    % Sum
     % STACK: 12
t    % Duplicate
     % STACK: 12, 12
E    % Multiply by 2
     % STACK: 12, 24
:    % Range
     % STACK: 12, [1 2 ... 23 24]
-    % Subtract, elemet-wise
     % STACK: [11 10 ... -11 -12]
G    % Push input again
     % STACK: [11 10 ... -11 -12], [1 5 6]
y    % Duplicate from below
     % STACK: [11 10 ... -11 -12], [1 5 6], [11 10 ... -11 -12]
ZQ   % Polyval: values of polynomial at specified inputs
     % STACK: [11 10 ... -11 -12], [182 156 ... 72 90]
~    % Logical negation: turns nonzero into zero
     % STACK: [11 10 ... -11 -12], [0 0 ... 0] (contains 1 for roots)
)    % Index: uses second input as a mask for the first. Implicit display
     % STACK: [-3 -2]

3
Roucheの定理の代替として、Rational Roots Theoremは、使用した範囲を正当化するのに十分です。有理根定理により、すべての整数根は、絶対値が係数の絶対値の最大値によって制限され、合計よりも厳密な制限があります。または、「最後の」非ゼロ係数の絶対値、つまり、非ゼロ係数を持つxの最小の累乗の係数によって、さらに厳密になります。(おそらく、RRTはほとんどの人にとってRoucheよりも馴染みがあるため、バイトを保存するのに役立ちません。単なる代替の証拠です。):)
mathmandan

1
@mathmandanそのアプローチは3バイト長くなります:ここ試してみてください、私は1つまたは2つのトリックを見逃したと確信していますが
ジュゼッペ

@Giuseppe両方に感謝します。たぶんX>t_w&:GyZQ~)、それでも13バイト
ルイス・メンドー

1
...しかし、範囲のより短い代替案を見つけました
ルイスメンドー

5

10 9バイト

Zgarbのおかげで-1バイト

uSȯf¬`Bṁṡ

オンラインでお試しください!

説明

       ṁṡ   Concatenate together the symmetric ranges of each coefficient
            (It is guaranteed that the integer roots lie in the range [-n..n],
                        where n is the coefficient with the largest magnitude)
 Sȯf        Find all the values in that range which
    ¬       are zero
     `B     when plugged through the polynomial
            (Base conversion acts as polynomial evaluation)
u           De-duplicate the roots

後で重複排除する場合のṁṡ代わりに行うことができますoṡ►a
ズガルブ

@Zgarbとても素敵!おかげで
H.PWiz

5

Haskell、54バイト

f l|t<-sum$abs<$>l=[i|i<-[-t..t],foldl1((+).(i*))l==0]

オンラインでお試しください!

ブルートフォースと合成部門。

UniHaskellでゴルフをしていない-XUnicodeSyntax

import UniHaskell

roots     Num a  [a]  [a]
roots xs = [r | r  -bound  bound, foldl1 ((+)  (r ×)) xs  0]
             where bound = sum $ abs § xs

代替ソリューション、44バイト

nimiの功績。

f l=[i|i<-[minBound..],foldl1((+).(i*))l==0]

範囲内のすべての数字をチェックするため、オンラインで試してみてくださいInt


繰り返し処理i[minBound..]て、すべてをドロップできtます。f明示的なIntリストを使用して呼び出しますf [1::Int,5,6]。もちろん、これは妥当な時間で終了しません。
nimi

@nimiなぜそれが止まるのでしょうか?無限ループしませんか?
完全に人間の

いいえ、Bounded種類がで停止maxBound例えば、print [minBound::Bool ..]
nimi

4

Python 2 + numpy、95 93 91 103 93 91 82バイト

-ovsに
感謝-2バイトルーツの上限/下限をLuis Mendoに
感謝-10バイトにMr.Xcoderに感謝

from numpy import*
def f(r):s=sum(fabs(r));q=arange(-s,s);print q[polyval(r,q)==0]

オンラインでお試しください!



@LuisMendoはい。
ロッド

3
私たちの現在のコンセンサスは、チャレンジで特に明記されていない限り、プログラムは常に終了する必要があるということです。
-Zgarb

@Zgarbが修正されました!
ロッド

使用するには、numpy.polyvalかなりの数のバイトを節約する
氏Xcoder

4

Wolfram言語(Mathematica)50 47 42 25 27バイト

{}⋃Select[x/.Solve[#~FromDigits~x==0],IntegerQ]&

オンラインでお試しください!

更新:ルイスメンドーの事実を使用して、さらに3バイトをゴルフ

Pick[r=Range[s=-Tr@Abs@#,-s],#~FromDigits~r,0]&

範囲に余裕がある場合、@ Not a treeの提案ごとにこの5バイトを減らすことができます。

Pick[r=Range[s=-#.#,-s],#~FromDigits~r,0]&

これを投稿した後、OPは「ネイティブ多項式」を許可するようにコメントしたので、入力として多項式を受け入れる25バイトのソリューションがあります。これは、デフォルトでMathematicaが整数に対して多項式を因数分解し、有理根が次のような形式で現れるためです。m*x+bがそのてパターンマッチに失敗するためです。

Cases[Factor@#,b_+x:>-b]&

@alephalphaが指摘したように、ゼロがルートである場合、これは失敗するので、修正するためにOptionalシンボルを使用できます:

Cases[Factor@#,b_:0+x:>-b]&

これは細かいMathematica 11.0.1を解析しますが失敗し、周りに追加の括弧が必要になります b_:0、バージョン11.2。これは、最大27バイトのバックアップに加えて、バージョン11.0.1以降にさらに2バイトかかります。ここに「修正」が置かれたようです

オンラインでお試しください!


1
私はあなたが#.#代わりに使用できると思いますTr@Abs@#:それはより悪い限界ですがより少ないバイトです。
木ではありません

1
OPは、もしあればあなたの言語のネイティブ多項式タイプを使用できるとコメントで述べました。Mathematicaをよく知らないのですが、あると思います...バイトを節約できますか?
いいえ、私の本当の名前は


1
@alephalpha、修正済み。
ケリーロウダー


3

Wolfram言語(Mathematica)33 26 31バイト

コメントでケリー・ロウダーが指摘したエラーを修正しました。

x/.{}⋃Solve[#==0,x,Integers]&

オンラインでお試しください!

以前の誤った解決策:

整数解がない場合、出力は空のリストではなく未定義です。これにより、数バイトを削除できます。

x/.Solve[#==0,x,Integers]&

オンラインでお試しください!

整数解が存在しない場合、関数はを返しますx

以前:

x/.Solve[#==0,x,Integers]/.x->{}&

オンラインでお試しください!


これは、ルートを繰り返すため1,2,1で現在述べられているように失敗し、OPはそれらが別個でなければならないと言った。あなたはそれUnionを修正する必要 があります。
ケリーロウダー

@KellyLowder:ああ、私はそれを見逃した。しかし、それから、それは与えられたテストケースにもありませんでした。
celtschk

@KellyLowder:修正しました。このためにダウン票を投じた場合、元に戻してください。
celtschk

@cellschk、そうです。
ケリーロウダー

文書化されていない機能を使用して29バイトSolve:変数のリストは省略できます。
ローマ

3

R61 59バイト

私の(間違った)アプローチを指摘してくれた@mathmandanに感謝します。

function(p)(x=-(t=p[!!p][1]):t)[!outer(x,seq(p)-1,"^")%*%p]

オンラインでお試しください!

入力を、昇順の係数のリスト、つまりでc(-1,0,1)表し-1+0x+1x^2ます。

有理根定理を使用すると、47バイトの場合、次のアプローチはほとんど機能します。

function(p)(x=-p:p)[!outer(x,seq(p)-1,"^")%*%p]

オンラインでお試しください!

-p:pの最初の要素だけを使用して(警告付き)対称範囲を生成しpa_0有理根定理により、のすべての有理根は、除算と除算(プラスまたはマイナス)Pの形式p/qでなければなりません。したがって、ちょうど使用するために十分である任意の場合と同様に、、。しかし、とき、そのように任意のpa_0qa_na_0|a_0|>0q|p/q|<=a_0a_0==0の整数分周0ので、これは失敗します。

ただし、mathmandanは、実際には、この場合、これは一定の要因をx^k除外できることを意味し、k最大と仮定すると、

P(x) = x^k(a_k + a_{k+1}x + ... a_n x^{n-k}) = x^k * Q(x)

私たちは、その後に合理的なルート定理を適用しQ(x)、そしてなどa_kの極大性により、ゼロ以外であることが保証されka_k整数の根行きの整頓を提供しQ、そしての根はPの根でありますQ私たちは、すべての整数を持つことになりますので、ゼロと一緒にPこのメソッドを適用することによるルート。

これは、多項式の最初の非ゼロ係数を見つけ、境界としてt=p[!!p][1]ナイーブの代わりにそれを使用することと同等p[1]です。また、範囲-t:t常にゼロが含まれるため、Pこの範囲に適用すると、実際にゼロである場合でもルートとしてゼロが得られます。

なし:

function(polynom) {
 bound <- polynom[polynom != 0][1]             #first nonzero value of polynom
 range <- -bound:bound                         #generates [-bound, ..., bound]
 powers <- outer(range,seq_along(p) - 1, "^")  #matrix where each row is [n^0,n^1,n^2,...,n^deg(p)]
 polyVals <- powers %*% polynom                #value of the polynomial @ each point in range
 return(range[polyVals == 0])                  #filter for zeros and return
}


(私はあなたがmax絶対値の代わりに使用できると思いますsum;これはバイト数を変更しませんが、パフォーマンスを改善するはずです。)とにかく、はい、短いバージョンは動作しませんa_0==0。Rに最初の(べきの昇順で)非ゼロ係数を検索し、代わりにそれを使用する短い方法はありますか?これは、多くのXの最初のできるだけアウトファクタリングに相当するであろう(もちろん、あなたは出力に覚えておく必要があるだろう0と思われるいくつかのバイトを要することになる、また。)
mathmandan

@mathmandan maxはより効率的ですが0、範囲-t:tt最初の非ゼロ係数)によって生成されるので出力について心配する必要がないので、2番目のポイントまで、2バイトを節約します!
ジュゼッペ

わあ、素晴らしい!(そして美しい説明も。)
mathmandan

2

ゼリー、8 バイト

ASŒRḅ@Ðḟ

オンラインでお試しください!またはテストスイートとして!

どうやって?

ASŒRḅ@Ðḟ|| 完全なプログラム(モナドリンク)。

AS || 絶対値を合計します。
  ŒR|| そして、負の値から対称包含範囲を作成します。
       Ðḟ|| そして、真実の価値をもたらすものを捨てます...
     ḅ@ || それらを多項式に差し込むとき(基底変換を使用)。

ルイスの回答に基づいています代替案


(許可された)逆順を取り、実行することについて私が欠けているものはありÆr+.Ḟますか?
ジョナサンアラン

numpyでのPythonの回答もそうではないので、私は少し混乱しています。
ジョナサンアラン

@JonathanAllan私が予想したように、あなたのは失敗し[1,2,3]ます。
Mr Xcoder

「与えられた方程式の解がない場合、出力は未定義です」
ジョナサンアラン

@JonathanAllanしかし、それ失敗[10,-42,8]ますか?
Mr Xcoder



2

C(GCC) 127の 126 123バイト

x,X,j,m,p;f(A,l)int*A;{for(m=j=0;j<l;m+=abs(A[j++]));for(x=~m;X=x++<m;p||printf("%d,",x))for(p=j=0;j<l;X*=x)p+=A[l-++j]*X;}

オンラインでお試しください!


説明

C(gcc)、517バイト

x,X,j,m,p;                      // global integer variables
f(A,l)int*A;{                   // define function, takes in integer array pointer and length
 for(m=j=0;j<l;m+=abs(A[j++])); // loop through array, sum up absolute values
  for(x=~m;X=x++<m;             // loop through all values x in [-m, m], prime X
   p||printf("%d,",x))          // at loop's end, print x value if polynomial value is zero
    for(p=j=0;j<l;X*=x)         // loop through coefficients
     p+=A[l-++j]*X;}            // build polynomial

オンラインでお試しください!


l+~j++にゴルフすることができますl-++j
ケビンCruijssen

@KevinCruijssenどうもありがとう。
ジョナサン

@ceilingcatありがとうございます。
ジョナサンフレッチ

1

Java 8、141 140バイト

a->{int l=a.length,s=0,i,r,f,p;for(int n:a)s+=n<0?-n:n;for(r=~s;r++<s;System.out.print(p==0?r+",":""))for(p=i=0,f=1;i<l;f*=r)p+=a[l-++i]*f;}

@RodのPython 2の回答(82バイトバージョン)に触発された

楽しいチャレンジ!多項式について調査し、他の人がどのようにそれを行っているかを見て、私は確かに多くのことを学びました。

説明:

オンラインでお試しください。

a->{                   // Method with integer-array parameter and no return-type
  int l=a.length,      //  The length of the input-array
      s=0,             //  Sum-integer, starting at 0
      i,               //  Index integer
      r,               //  Range-integer
      f,               //  Factor-integer
      p;               //  Polynomial-integer
  for(int n:a)         //  Loop over the input-array
    s+=n<0?-n:n;       //   And sum their absolute values
  for(r=~s;r++<s;      //  Loop `r` from `-s` up to `s` (inclusive) (where `s` is the sum)
      System.out.print(p==0?r+",":""))
                       //    After every iteration: print the current `r` if `p` is 0
    for(p=i=0,         //   Reset `p` to 0
        f=1;           //   and `f` to 1
        i<l;           //   Loop over the input-array again, this time with index (`i`)
        f*=r)          //     After every iteration: multiply `f` with the current `r`
      p+=              //    Sum the Polynomial-integer `p` with:
         a[l-++i]      //     The value of the input at index `l-i-1`,
                 *f;}  //     multiplied with the current factor `f`



0

JavaScript(ES6)、97バイト

a=>[...Array((n=Math.max(...a.map(Math.abs)))-~n)].map(_=>n--).filter(i=>!a.reduce((x,y)=>x*i+y))

パワーの降順で係数を取り、降順で結果を出力します。



弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.