Tìm Rễ tích phân của đa thức


19

Thử thách

Thách thức là viết một chương trình lấy các hệ số của bất kỳ phương trình đa thức bậc n nào làm đầu vào và trả về các giá trị tích phân của x mà phương trình giữ đúng. Các hệ số sẽ được cung cấp làm đầu vào theo thứ tự giảm hoặc tăng công suất. Bạn có thể giả sử tất cả các hệ số là số nguyên .

Đầu vào và đầu ra

Đầu vào sẽ là các hệ số của phương trình theo thứ tự công suất giảm hoặc tăng. Độ của phương trình, nghĩa là công suất cực đại của x, luôn nhỏ hơn 1 so với tổng không có phần tử nào trong đầu vào.

Ví dụ:

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

Đầu ra của bạn chỉ nên là các giá trị tích phân riêng của x thỏa mãn phương trình đã cho. Tất cả các hệ số đầu vào là số nguyên và đa thức đầu vào sẽ không phải là đa thức bằng không . Nếu không có giải pháp cho phương trình đã cho, thì đầu ra không xác định.

Nếu một phương trình có gốc lặp lại, chỉ hiển thị gốc cụ thể đó một lần. Bạn có thể xuất các giá trị theo bất kỳ thứ tự nào. Ngoài ra, giả sử rằng đầu vào sẽ chứa ít nhất 2 số.

Ví dụ

[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] -> -

Lưu ý rằng phương trình trong ví dụ thứ hai cũng có gốc 0,2, nhưng nó không được hiển thị vì 0,2 không phải là số nguyên.

Chấm điểm

Đây là , vì vậy mã ngắn nhất (tính bằng byte) sẽ thắng!


7
Lưu ý: Trước khi bỏ phiếu để đóng, vui lòng xem xét rằng câu hỏi này không phải là một bản sao của câu hỏi này . Tôi có thể nghĩ ra ít nhất một cách tiếp cận cho vấn đề này sẽ không thể sửa đổi một cách tầm thường cho thử thách khác (mặc dù tôi không nói gì; điều đó còn lại với bạn; P).
Erik the Outgolfer

Chúng ta có thể giả sử rằng chúng ta chỉ cần trả về các gốc bên trong giới hạn số nguyên của ngôn ngữ của chúng ta không? Hoặc thuật toán nên hoạt động ngay cả khi phạm vi loại số nguyên ngôn ngữ được tăng lên, nhưng hành vi vẫn giữ nguyên.
Οurous

1
Chúng tôi cũng có thể sử dụng loại đa thức riêng nếu ngôn ngữ của bạn hỗ trợ các loại đó?
flawr

1
Là các chương trình chạy mãi mãi nếu không có giải pháp được chấp nhận?
Jack M

1
Đó là để giữ cho mọi thứ đơn giản.
Manish Kundu

Câu trả lời:


6

MATL , 13 12 byte

|stE:-GyZQ~)

Hãy thử trực tuyến!

Điều này sử dụng thực tế là, đối với các hệ số nguyên, giá trị tuyệt đối của bất kỳ gốc nào đều nhỏ hơn tổng giá trị tuyệt đối của các hệ số.

Giải trình

Hãy xem xét đầu vào [1 5 6]là một ví dụ.

|    % 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
Thay thế cho Định lý Rouche, Định lý Rễ Rational cũng sẽ đủ để biện minh cho ràng buộc mà bạn đã sử dụng. Theo Định lý Rễ Rational, tất cả các gốc số nguyên được giới hạn ở giá trị tuyệt đối bằng giá trị tuyệt đối của các hệ số, ràng buộc chặt chẽ hơn tổng. Hoặc thậm chí chặt chẽ hơn, bằng giá trị tuyệt đối của hệ số khác không "cuối cùng" - tức là hệ số công suất nhỏ nhất của x có hệ số khác không. (Có lẽ không giúp lưu bất kỳ byte nào, chỉ là một bằng chứng thay thế vì RRT có lẽ quen thuộc hơn Rouche đối với hầu hết mọi người.) :)
mathmandan

1
@mathmandan cách tiếp cận đó dài hơn ba byte: Hãy thử ở đây , mặc dù tôi chắc chắn rằng tôi đã bỏ lỡ một hoặc hai mẹo
Giuseppe

@Giuseppe Cảm ơn cả hai. Có thể X>t_w&:GyZQ~), nhưng vẫn còn 13 byte
Luis Mendo

1
... nhưng tôi đã tìm thấy một sự thay thế ngắn hơn cho phạm vi
Luis Mendo

5

Husk , 10 9 byte

-1 byte nhờ Zgarb

uSȯf¬`Bṁṡ

Hãy thử trực tuyến!

Giải trình

       ṁṡ   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

Bạn có thể làm ṁṡthay vì oṡ►anếu bạn lặp lại sau này.
Zgarb

@Zgarb Rất đẹp! Cảm ơn
H.PWiz

5

Haskell , 54 byte

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

Hãy thử trực tuyến!

Lực lượng vũ phu và phân chia tổng hợp.

Ung dung với UniHaskell-XUnicodeSyntax

import UniHaskell

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

Giải pháp thay thế, 44 byte

Tín dụng cho nimi.

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

Chúc may mắn với việc thử trực tuyến , vì điều này kiểm tra mọi số trong Intphạm vi.


Bạn có thể lặp iqua [minBound..]và thả toàn bộ tđiều. Gọi fvới Intdanh sách rõ ràng , ví dụ f [1::Int,5,6]. Tất nhiên điều này không hoàn thành trong thời gian hợp lý.
nimi

@nimi Tại sao điều đó sẽ dừng lại? Nó sẽ không lặp vô hạn?
hoàn toàn là

Không, Boundedcác loại dừng lại ở maxBound, ví dụ print [minBound::Bool ..].
nimi

4

Python 2 + numpy, 95 93 91 103 93 91 82 byte

-2 byte nhờ vào ovs
nhờ Luis Mendo cho giới hạn trên / dưới của rễ
-10 byte nhờ ông Xcoder

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

Hãy thử trực tuyến!



@LuisMendo có.
Rod

3
Sự đồng thuận hiện tại của chúng tôi dường như là các chương trình phải luôn chấm dứt, trừ khi có thách thức khác.
Zgarb

@Zgarb đấy, cố định!
Rod

Sử dụng numpy.polyvaltiết kiệm khá nhiều byte
Ông Xcoder

4

Ngôn ngữ Wolfram (Mathicala) , 50 47 42 25 27 byte

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

Hãy thử trực tuyến!

Cập nhật: sử dụng thực tế của Luis Mendo, đánh gôn thêm 3 byte

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

Bắt đầu chậm hơn với giới hạn, chúng ta có thể giảm thêm 5 byte cho mỗi đề xuất của một cây:

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

Sau khi đăng bài này, OP đã nhận xét cho phép "đa thức nguyên gốc", vì vậy đây là giải pháp 25 byte chấp nhận đa thức làm đầu vào. Điều này hoạt động bởi vì theo mặc định, Mathicala đưa ra các đa thức trên các số nguyên và bất kỳ gốc hợp lý nào hiển thị dưới dạng như thế đều m*x+bkhông khớp mẫu.

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

Như @alephalpha đã chỉ ra điều này sẽ thất bại trong trường hợp số 0 là gốc, vì vậy để khắc phục rằng chúng ta có thể sử dụng Optionalký hiệu:

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

Điều này phân tích cú pháp Mathicala 11.0.1 tốt nhưng không thành công và yêu cầu thêm một dấu ngoặc đơn b_:0trong phiên bản 11.2. Điều này chiếm lại tới 27 byte, cộng thêm hai byte sau phiên bản 11.0.1. Có vẻ như một "sửa chữa" đã được đưa vào đây

Hãy thử trực tuyến!


1
Tôi nghĩ bạn có thể sử dụng #.#thay vì Tr@Abs@#: đó là một ràng buộc tồi tệ hơn nhưng ít byte hơn.
Không phải là một cái cây vào

1
OP đã nói trong một bình luận rằng bạn có thể sử dụng loại đa thức nguyên gốc của ngôn ngữ nếu có. Tôi không biết rõ về Mathicala nhưng tôi tưởng tượng có một ... Điều đó có tiết kiệm được byte không?
Không không hiển thị tên thật của tôi


1
@alephalpha, cố định.
Kelly Lowder


3

Ngôn ngữ Wolfram (Mathicala) , 33 26 31 byte

Đã sửa lỗi được ghi nhận bởi Kelly Lowder trong các bình luận.

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

Hãy thử trực tuyến!

Giải pháp không chính xác trước đây:

Tôi chỉ nhận thấy rằng đối với không có giải pháp số nguyên, đầu ra không được xác định thay vì danh sách trống; cho phép loại bỏ một vài byte.

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

Hãy thử trực tuyến!

Bây giờ nếu không có giải pháp số nguyên tồn tại, hàm trả về x.

Trước đây:

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

Hãy thử trực tuyến!


Điều này thất bại như đã nêu với 1,2,1 vì nó lặp lại gốc và OP nói rằng chúng phải khác biệt. Bạn cần Unionkhắc phục điều đó.
Kelly Lowder

@KellyLowder: Ah, tôi đã bỏ lỡ điều đó. Nhưng sau đó, nó cũng bị thiếu trong các trường hợp thử nghiệm nhất định.
celtschk

@KellyLowder: Bây giờ tôi đã sửa nó. Trong trường hợp bạn bị hạ cấp vì điều này, bạn có thể vui lòng hoàn nguyên nó không?
celtschk

@cellschk, vâng xong rồi.
Kelly Lowder

29 byte bằng cách sử dụng một tính năng không có giấy tờ của Solve: danh sách các biến có thể được bỏ qua.
La Mã

3

R , 61 59 byte

Cảm ơn đặc biệt đến @mathmandan vì đã chỉ ra cách tiếp cận (không chính xác) của tôi có thể được lưu lại và chơi gôn!

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

Hãy thử trực tuyến!

Đưa đầu vào dưới dạng danh sách các hệ số theo thứ tự tăng dần , nghĩa làc(-1,0,1) đại diện -1+0x+1x^2.

Sử dụng định lý gốc hợp lý, cách tiếp cận sau đây gần như hoạt động, với 47 byte:

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

Hãy thử trực tuyến!

-p:ptạo ra một phạm vi đối xứng (có cảnh báo) chỉ sử dụng phần tử đầu tiên của p, a_0. Bởi Rational gốc lý , tất cả rễ hợp lý Pphải có dạng p/qnơi pchia a_0qphân chia a_n(cộng hoặc trừ). Do đó, sử dụng chỉ a_0là đủ cho |a_0|>0, như đối với bất kỳ q, |p/q|<=a_0. Tuy nhiên, khi a_0==0, khi đó, bất kỳ số nguyên nào cũng chia 0, và do đó, điều này không thành công.

Tuy nhiên, mathmandan chỉ ra rằng thực sự, trong trường hợp này, điều này có nghĩa là có một yếu tố liên tục x^kcó thể được đưa ra, và, giả sử klà tối đa, chúng ta thấy rằng

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

Sau đó, chúng tôi áp dụng Định lý gốc hợp lý cho Q(x), và như a_kđược bảo đảm là khác không bởi tính tối đa của k, a_kcung cấp một ràng buộc gọn gàng cho các gốc số nguyên Qvà gốc của Plà gốc củaQ cùng với 0, vì vậy chúng tôi sẽ có tất cả các số nguyên rễ của Pbằng cách áp dụng phương pháp này.

Điều này tương đương với việc tìm ra hệ số khác không đầu tiên của đa thức t=p[!!p][1]và sử dụng nó thay vì ngây thơ p[1]như giới hạn. Hơn nữa, vì phạm vi-t:t luôn chứa số 0, nên áp dụng Pcho phạm vi này vẫn sẽ cung cấp cho chúng tôi số 0 dưới dạng gốc, nếu thực sự là như vậy.

vô dụng:

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
}


(Tôi nghĩ rằng bạn có thể sử dụng các maxgiá trị tuyệt đối thay vì sum; điều này sẽ không thay đổi số byte, nhưng nó phải cải thiện hiệu suất.) Dù sao, vâng, đáng tiếc phiên bản ngắn hơn không hoạt động a_0==0. Có một số cách ngắn trong R để tìm kiếm hệ số khác không đầu tiên (có quyền hạn tăng dần) và sử dụng thay thế? Điều này sẽ tương ứng với việc bao thanh toán càng nhiều x càng tốt trước tiên (tất nhiên, sau đó bạn cũng phải nhớ đầu ra 0, điều này có lẽ sẽ tốn một số byte.)
mathmandan

@mathmandan maxsẽ hiệu quả hơn, nhưng đến điểm thứ hai của bạn, vì tôi không phải lo lắng về việc xuất ra 0vì nó được tạo bởi phạm vi -t:t(trong đó thệ số khác không đầu tiên), nó tiết kiệm được 2 byte!
Giuseppe

Ồ rất tốt! (Và một lời giải thích tuyệt vời nữa.)
mathmandan

2

Thạch , 8 byte

ASŒRḅ@Ðḟ

Hãy thử trực tuyến! hoặc như một bộ thử nghiệm!

Làm sao?

ASR @ Đḟ || Chương trình đầy đủ (liên kết đơn âm).

NHƯ | | Tính tổng các giá trị tuyệt đối.
  ŒR | | Và tạo phạm vi bao gồm đối xứng từ giá trị âm của nó.
       | | | Và loại bỏ những thứ mang lại giá trị trung thực ...
     ḅ @ | | Khi cắm chúng vào đa thức (sử dụng hội tụ cơ sở).

Dựa trên câu trả lời của Luis . Một sự thay thế .


Có điều gì tôi đang thiếu về việc thực hiện thứ tự ngược (được phép) và làm Ær+.Ḟkhông?
Jonathan Allan

Tôi hơi bối rối vì câu trả lời Python với numpy cũng không làm như vậy, và tôi nghĩ rằng tôi đã bỏ lỡ một số trường hợp cạnh.
Jonathan Allan

@Jonathan ALLan Như tôi dự đoán, bạn thất bại vì [1,2,3].
Ông Xcoder

"Nếu không có giải pháp cho phương trình đã cho, thì đầu ra không xác định"
Jonathan Allan

@JonathanAllan Nhưng nó không thất bại cho [10,-42,8], phải không?
Ông Xcoder

2

Octave , 59 49 byte

@(p)(x=-(t=p(~~p)(end)):sign(t):t)(!polyval(p,x))

Hãy thử trực tuyến!

Đây là một cổng của câu trả lời R của tôi . Sự khác biệt duy nhất là tôi phải sử dụng rõ ràng sign(t)endtạo ra phạm vi, và nó polyvalphải tính toán đa thức.

Đưa đầu vào dưới dạng một vectơ hàng của các hệ số theo thứ tự giảm dần.



2

C (gcc) , 127 126 123 byte

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

Hãy thử trực tuyến!


Giải trình

C (gcc) , 517 byte

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

Hãy thử trực tuyến!


l+~j++có thể được đánh gôn tớil-++j
Kevin Cruijssen

@KevinCruijssen Cảm ơn rất nhiều.
Jonathan Frech

@ceilingcat Cảm ơn bạn.
Jonathan Frech

1

Java 8, 141 140 byte

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

Lấy cảm hứng từ câu trả lời Python 2 @Rod (phiên bản 82 byte của anh ấy) .

Thử thách thú vị! Tôi chắc chắn đã học được rất nhiều về nó khi điều tra về đa thức và xem một số người khác ở đây đã làm điều đó như thế nào.

Giải trình:

Hãy thử trực tuyến.

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 byte

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

Có hệ số theo thứ tự công suất giảm dần và kết quả đầu ra giảm dần.



Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.