다항식의 근본을 구합니다


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 의 고유 정수 값 이어야합니다 . 모든 입력 계수는 정수이며 입력 다항식 은 0 다항식이 아닙니다 . 주어진 방정식에 대한 해가 없으면 출력이 정의되지 않습니다.

방정식에서 근이 반복되면 해당 근을 한 번만 표시하십시오. 임의의 순서로 값을 출력 할 수 있습니다. 또한 입력에 최소 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] -> -

두 번째 예의 방정식에도 루트 0.2가 있지만 0.2가 정수가 아니므로 표시되지 않습니다.

채점

이것은 이므로 가장 짧은 코드 (바이트)가 이깁니다!


7
참고 : 가까운 투표 전에이 문제가 있음을 고려하시기 바랍니다 하지 의 중복 이 하나 . 나는 다른 문제에 대해 사소하게 수정 할 수없는이 문제에 대한 적어도 하나의 접근법을 생각할 수 있습니다 (그러나 나는 무엇을 말하고 있지는 않지만, 그것은 당신에게 맡겨져 있습니다; P).
Outgolfer Erik

언어의 정수 범위 내에서만 근을 반환해야한다고 가정 할 수 있습니까? 또는 언어 정수 유형 범위가 증가하더라도 알고리즘이 작동해야하지만 동작은 동일하게 유지됩니다.
OUurous

1
귀하의 언어가 지원하는 경우 기본 다항식 유형을 사용할 수 있습니까?
flawr

1
해결책이 없으면 영원히 실행되는 프로그램이 있습니까?
잭 M

1
그것은 일을 단순하게 유지하는 것입니다.
Manish Kundu

답변:


6

MATL , 13 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은 또한 사용 된 범위를 정당화하기에 충분합니다. 유리수 정리에 의해, 모든 정수 뿌리는 계수의 절대 값의 최대 값에 의해 절대 값으로 제한되며, 합보다 더 밀접하게 제한됩니다. 또는 0이 아닌 "마지막"비계 수의 절대 값, 즉 0이 아닌 계수를 갖는 x의 가장 작은 거듭 제곱의 계수에 의해 더 엄격 해집니다. (아마도 바이트를 절약하는 데 도움이되지 않습니다. RRT가
Rouche

1
@mathmandan 그 접근 방식은 3 바이트 더 길다 : 여기서 시도해보십시오 . 비록 한두 가지를 놓친 것 같습니다
Giuseppe

@ 주세페 모두 감사합니다. 아마 X>t_w&:GyZQ~), 그러나 여전히 13 바이트
Luis Mendo

1
...하지만 범위에 대한 더 짧은 대안을 찾았습니다
Luis Mendo

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

@ Zgarb 아주 좋은! 감사합니다
H.PWiz

5

하스켈 , 54 바이트

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

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

무차별 대입 및 합성 부문.

와 Ungolfed 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

파이썬 2 + NumPy와, 95 (93) 91 103 93 91 82 바이트

ovs
덕분에 -2 바이트 덕분에 루트 의 상한과 하한에 Luis Mendo 덕분에 Xcoder 덕분에
-10 바이트

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

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



@LuisMendo 예.
Rod

3
우리의 현재 합의 도전 달리 명시하지 않는 한 프로그램이 항상 종료해야 될 것으로 보인다.
Zgarb

@ Zgarb, 고정!
Rod

사용은 numpy.polyval꽤 몇 바이트 저장
씨 Xcoder

4

Wolfram Language (Mathematica) , 50 47 42 25 27 바이트

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

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

업데이트 : Luis Mendo의 사실을 사용하여 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가 지적했듯이 이것은 0이 루트 인 경우 실패하므로 Optional기호를 사용할 수 있도록 수정하십시오.:

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

이것은 훌륭한 Mathematica 11.0.1을 구문 분석하지만 실패하고 b_:0버전 11.2에서 추가 괄호 세트가 필요합니다 . 버전 11.0.1 이후에는 최대 27 바이트와 2 바이트가 더 걸립니다. 여기에 "수정"을 넣은 것 같습니다.

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


1
나는 당신이 #.#대신 사용할 수 있다고 생각합니다 Tr@Abs@#: 그것은 더 나쁜 경계이지만 더 적은 바이트입니다.
나무가 아님

1
OP는 귀하의 언어의 다항식 유형이 존재할 경우이를 사용할 수 있다고 언급했습니다. 나는 Mathematica를 잘 모르지만 하나가 있다고 상상합니다 ... 바이트를 절약 할 수 있습니까?
아니요 내 실제 이름을 표시하지 않았습니다


1
@alephalpha, 고정.
Kelly Lowder


3

Wolfram Language (Mathematica) , 33 26 31 바이트

주석에서 Kelly Lowder가 지적한 오류를 수정했습니다.

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

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

이전의 잘못된 해결책 :

정수 솔루션이 없으면 빈 목록 대신 출력이 정의되지 않았습니다. 몇 바이트를 제거 할 수 있습니다.

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

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

정수 솔루션이 존재하지 않으면 함수는를 반환합니다 x.

이전 :

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

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


루트를 반복하고 OP가 구별해야한다고 말하면서 현재 1,2,1에서 언급 한대로 실패합니다. Union그 문제를 해결 해야 합니다.
Kelly Lowder

@KellyLowder : 아, 나는 그것을 놓쳤다. 그러나 주어진 테스트 사례에서도 누락되었습니다.
celtschk

@ KellyLowder : 이제 고쳤습니다. 이로 인해 하향 투표 한 경우 되돌려 주시겠습니까?
celtschk

@cellschk, 그렇습니다.
Kelly Lowder

문서화되지 않은 기능을 사용하여 29 바이트Solve : 변수 목록을 생략 할 수 있습니다.
로마

3

R , 61 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의 첫번째 요소를 사용하는 (경고)와 대칭 영역을 생성 p, a_0. 에 의해 하여 Rational 루트 정리 , 모든 합리적인 뿌리는 P형태이어야 p/q경우 p분할 a_0q분할 a_n(+ 또는 -). 따라서, 단지 사용하는 것은 a_0충분하다 |a_0|>0모든에 대해, q, |p/q|<=a_0. 그러나, 그때 a_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)

우리는 그 다음으로는 Rational 루트 정리를 적용 Q(x)로, 그리고 a_k의 maximality에 의해 제로로 보장됩니다 k, a_k의 정수 뿌리 행 단정을 제공 Q, 그리고 뿌리 P의 뿌리이다 Q우리는 모든 정수를 가지게됩니다, 함께 제로로 의 뿌리 P이 방법을 적용하여.

이것은 다항식의 첫 번째 0이 아닌 계수를 찾아 경계로 t=p[!!p][1]순진한 대신 계수를 사용하는 p[1]것과 같습니다. 또한 범위 -t:t에는 항상 0 P이 포함되므로이 범위 에 적용 하면 실제로는 루트로 0이됩니다.

언 골프 :

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:t( t제로가 아닌 첫 번째 계수가 있음)에 의해 생성되므로 출력에 대해 걱정할 필요가 없으므로 2 바이트를 절약합니다!
Giuseppe

오 아주 좋아! (그리고 아름다운 설명도 있습니다.)
mathmandan

2

젤리 , 8 바이트

ASŒRḅ@Ðḟ

온라인으로 사용해보십시오! 또는 시험 스위트로!

어떻게?

ASŒRḅ @ Ðḟ || 전체 프로그램 (모나 딕 링크).

그대로 || 절대 값을 합산하십시오.
  || R || 그리고 음수 값에서 대칭 포함 범위를 만듭니다.
       Ðḟ || 그리고 진실한 가치를 산출하는 것들을 버려라 ...
     ḅ @ || 다항식에 연결할 때 (기본 변환 사용)

Luis의 답변을 기반으로합니다 . 대안 .


(허용) 역순을 취하고 수행하는 데 누락 된 것이 Ær+.Ḟ있습니까?
Jonathan Allan

numpy에 대한 Python 답변도 그렇게하지 않았기 때문에 약간 혼란 스럽습니다.
Jonathan Allan

@JonathanAllan 예상 한대로에 실패했습니다 [1,2,3].
Mr. Xcoder

"주어진 방정식에 대한 해가 없다면 결과는 정의되지 않습니다"
Jonathan Allan

@JonathanAllan 그러나 않습니다 실패 에 대한 [10,-42,8], 맞죠?
Mr. Xcoder

2

옥타브 , 59 49 바이트

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

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

이것은 내 R 답변 의 포트입니다 . 유일한 차이점은 범위 를 명시 적으로 사용 sign(t)하고 end생성해야 polyval하며 다항식을 계산해야 한다는 것 입니다.

입력을 내림차순으로 계수의 행 벡터로 취합니다.



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++에 golfed 할 수있다l-++j
케빈 Cruijssen

@KevinCruijssen 감사합니다.
Jonathan Frech

@ceilingcat 감사합니다.
Jonathan Frech

1

Java 8, 141140 바이트

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.