Bir Polinomun İntegral Köklerini Bulun


19

Meydan okuma

Zorluk, herhangi bir n-dereceli polinom denkleminin katsayılarını girdi olarak alan ve denklemin doğru olduğu x'in integral değerlerini döndüren bir program yazmaktır . Katsayılar azalan veya artan güç sırasıyla girdi olarak verilecektir. Tüm katsayıların tamsayı olduğunu varsayabilirsiniz .

Giriş ve çıkış

Girdi, azalan veya artan güç düzenindeki denklem katsayıları olacaktır. Denklemin derecesi, yani x'in maksimum gücü her zaman girişteki toplam eleman sayısından 1 daha azdır.

Örneğin:

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

Çıktınız , verilen denklemi karşılayan yalnızca x'in ayrılmaz integral değerleri olmalıdır . Bütün girdi katsayıları tamsayıdır ve girdi polinomu sıfır polinom olmayacaktır . Verilen denklem için bir çözüm yoksa, çıktı tanımsızdır.

Bir denklemin tekrarlanan kökleri varsa, ilgili kökü yalnızca bir kez görüntüleyin. Değerleri istediğiniz sırayla çıktılayabilirsiniz. Ayrıca, girdinin en az 2 sayı içereceğini varsayın.

Örnekler

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

İkinci örnekteki denklemin de 0.2 köküne sahip olduğunu, ancak 0.2'nin bir tamsayı olmadığı için görüntülenmediğini unutmayın.

puanlama

Bu , yani en kısa kod (bayt cinsinden) kazanır!


7
Not: yaklaşırken oylama öncesinde, bu soru olduğunu düşünün lütfen değil yinelenen bu bir . Bu soruna, diğer zorluk için önemsiz bir şekilde değiştirilemeyecek en az bir yaklaşım düşünebilirim (ne demememe rağmen; bu size kalmış; P).
Outgolfer Erik

Kökleri yalnızca dilimizin tamsayı sınırları içinde döndürmemiz gerektiğini varsayabilir miyiz? Veya algoritma, diller tamsayı türü aralığı artırılsa bile çalışmalı, ancak davranış aynı kaldı.
18

1
Diliniz bunları destekliyorsa yerel bir polinom türü de kullanabilir miyiz?
Kusur

1
Herhangi bir çözüm kabul edilmezse sonsuza dek çalışan programlar var mı?
Jack M

1
Bu işleri basit tutmaktır.
Manish Kundu

Yanıtlar:


6

MATL , 13 12 bayt

|stE:-GyZQ~)

Çevrimiçi deneyin!

Bu , tamsayı katsayıları için herhangi bir kökün mutlak değerinin, katsayıların mutlak değerlerinin toplamından kesinlikle daha az olduğu gerçeğini kullanır .

açıklama

Girişi [1 5 6]örnek olarak ele alalım.

|    % 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 Teoremine alternatif olarak, Rasyonel Kökler Teoremi de kullandığınız sınırı haklı çıkarmak için yeterli olacaktır. Rasyonel Kökler Teoremi ile tüm tamsayı kökleri, katsayıların mutlak değerlerinin maksimum değeriyle, toplamdan daha sıkı bir şekilde bağlanır. Ya da "son" sıfır olmayan katsayının mutlak değeri ile daha da sıkı - yani sıfır olmayan bir katsayısı olan x'in en küçük gücünün katsayısı. (Muhtemelen herhangi bir baytın kurtarılmasına yardımcı olmuyor, sadece alternatif bir kanıt çünkü RRT muhtemelen çoğu
insan için Rouche'dan

1
@mathmandan bu yaklaşım üç bayt daha uzun: Burada bir deneyin , bir iki numarayı kaçırdığımdan eminim
Giuseppe

@Giuseppe İkisine de teşekkürler. Belki X>t_w&:GyZQ~), ama yine de 13 bayt
Luis Mendo

1
... ama menzil için daha kısa bir alternatif buldum
Luis Mendo

5

Kabuk , 10 9 bayt

Zgarb sayesinde -1 bayt

uSȯf¬`Bṁṡ

Çevrimiçi deneyin!

açıklama

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

Daha sonra tekilleştirme yapmak ṁṡyerine bunu yapabilirsiniz oṡ►a.
Zgarb

@Zgarb Çok hoş! Teşekkürler
H.PWiz

5

Haskell , 54 bayt

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

Çevrimiçi deneyin!

Kaba kuvvet ve sentetik bölünme.

İle Ungolfed UniHaskell ve-XUnicodeSyntax

import UniHaskell

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

Alternatif çözüm, 44 bayt

Nimi'ye kredi.

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

Çevrimiçi denemede bol şans , çünkü bu bir aralıktaki her sayıyı kontrol eder Int.


Sen yineleme yapabilirsiniz iüzerinde [minBound..]ve bütün damla tşeyi. fAçık Intlistelerle arayın , örn f [1::Int,5,6]. Tabii ki bu makul bir sürede bitmiyor.
nimi

@nimi Bu neden dursun? Sonsuz döngü olmaz mıydı?
totallyhuman

Hayır, Boundedtürler durur maxBound, örn print [minBound::Bool ..].
nimi

4

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

Ovs
sayesinde -2 bayt , köklerin üst / alt sınırları için Luis Mendo'ya
teşekkürler-Bay Xcoder sayesinde -10 bayt

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

Çevrimiçi deneyin!



@LuisMendo evet.
Çubuk

3
Bizim şimdiki konsensüs meydan aksini belirtmediği sürece programları daima sonlandırmak gerektiğini gibi görünüyor.
Zgarb

@Zgarb orada, sabit!
Çubuk

Kullanmak numpy.polyvalbirkaç bayt kazandırır
Bay Xcoder

4

Wolfram Dili (Mathematica) , 50 47 42 25 27 bayt

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

Çevrimiçi deneyin!

Güncelleme: Luis Mendo'nun gerçeğini kullanarak, 3 bayt daha golf

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

Sınırlarla daha eğlenceli hale geldikçe, bir ağacın önerisi başına bu 5 bayt daha azaltabiliriz:

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

Bunu gönderdikten sonra OP "doğal polinomlara" izin verdiğini yorumladı, bu yüzden polinomu girdi olarak kabul eden 25 baytlık bir çözüm. Bu, varsayılan olarak Mathematica'nın tamsayılar üzerinde polinomları faktörleri ve rasyonel köklerin m*x+b, desen eşleşmesini başarısız kılan bir biçimde gösterilmesi nedeniyle çalışır .

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

@Alephalpha'nın işaret ettiği gibi, sıfırın bir kök olduğu durumda başarısız olur, böylece Optionalsembolü kullanabilmemiz için:

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

Bu, iyi Mathematica 11.0.1'i ayrıştırır, ancak başarısız olur ve b_:0sürüm 11.2'de fazladan bir parantez seti gerektirir . Bu, 27 bayta kadar artı 11.0.1 sürümünden sonra iki tane daha alır. Bu kondu bir "düzeltme" gibi görünüyor buradan

Çevrimiçi deneyin!


1
Bunun #.#yerine kullanabileceğinizi düşünüyorum Tr@Abs@#: daha kötü bir bağ ama daha az bayt.
bir ağaç değil

1
OP bir yorumda, varsa dilinizin yerel polinom türünü kullanabileceğinizi söyledi. Mathematica'yı iyi tanımıyorum ama bir tane olduğunu hayal ediyorum.
Hayır gerçek adımı


1
@ alephalpha, sabit.
Kelly Lowder


3

Wolfram Dili (Mathematica) , 33 26 31 bayt

Kelly Lowder'ın yorumlarda belirttiği bir hata düzeltildi.

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

Çevrimiçi deneyin!

Önceki yanlış çözümler:

Ben hiçbir tamsayı çözümü için, çıktı boş liste yerine tanımsız olduğunu fark ettim; birkaç baytın kaldırılmasına izin verir.

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

Çevrimiçi deneyin!

Şimdi bir tamsayı çözümü yoksa, işlev geri döner x.

Önceden:

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

Çevrimiçi deneyin!


Bu, kökü tekrarladığı için 1,2,1 ile belirtildiği gibi başarısız olur ve OP farklı olmaları gerektiğini söyledi. Bunu Uniondüzeltmen gerek.
Kelly Lowder

@KellyLowder: Ah, bunu özledim. Ancak, verilen test vakalarında da eksikti.
celtschk

@KellyLowder: Şimdi düzelttim. Bu nedenle aşağı düştüğünüz takdirde lütfen geri alabilir misiniz?
celtschk

@cellschk, evet bitti.
Kelly Lowder

Belgelenmemiş bir özelliği kullanarak 29 baytSolve : değişken listesi atlanabilir.
Roman

3

R , 61 59 bayt

Mathmandan'a (yanlış) yaklaşımımı işaret ettiği için özel bir teşekkür kaydedilebilir ve golf oynayabilir!

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

Çevrimiçi deneyin!

Girdileri artan düzende katsayıların bir listesi olarak alır , yani c(-1,0,1)temsil eder -1+0x+1x^2.

Rasyonel kök teoremini kullanarak, aşağıdaki yaklaşım 47 bayt için neredeyse işe yarar:

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

Çevrimiçi deneyin!

-p:pp, öğesinin yalnızca ilk öğesini kullanarak simetrik bir aralık oluşturur (bir uyarı ile) a_0. Tarafından Rasyonel kök teoremi , tüm rasyonel kökleri Pbiçiminde olmalıdır p/qburada pbölme a_0ve qbölme a_n(artı ya da eksi). Bu nedenle, sadece kullanarak a_0için yeterlidir |a_0|>0herhangi gelince q, |p/q|<=a_0. Ancak, ne zaman a_0==0, o zaman herhangi bir tamsayı bölünür 0ve böylece bu başarısız olur.

Bununla birlikte, mathmandan gerçekten, bu durumda, bunun x^kçarpanlarına ayrılabilecek sabit bir faktör olduğu ve kmaksimum olduğu varsayıldığında ,

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

Biz daha sonra Akılcı Kök Teoremini uygulamak Q(x)olarak ve a_kbir maksimallikten sıfırdan farklı olması sağlanır k, a_ktamsayı kökleri gitmekte derli toplu bir sağlar Qve kökleri Pkökleri olan Qhepimizin tamsayı olacak, böylece boyunca sıfır ile kökleri P, bu yöntem uygulanarak elde edilebilir.

Bu, polinomun ilk sıfır olmayan katsayısını bulmak ve sınır olarak t=p[!!p][1]saf yerine kullanmakla eşdeğerdir p[1]. Dahası, aralık -t:ther zaman sıfır içerdiğinden, Pbu aralığa başvurmak gerçekten de kök olarak bize sıfır verir.

ungolfed:

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
}


(Bunun maxyerine mutlak değerleri kullanabileceğinizi düşünüyorum sum; bu bayt sayısını değiştirmez, ancak performansı arttırmalıdır.) Her neyse, evet, kısa versiyonun çalışmadığı için yazık a_0==0. R'de sıfır olmayan ilk katsayıyı (güçleri artan) aramak ve bunun yerine kullanmak için kısa bir yol var mı? Bu, ilk önce mümkün olduğunca çok sayıda x'in faktoringine karşılık gelir (elbette, o zaman çıktı almayı da hatırlamanız gerekir 0, ki bu muhtemelen bazı baytlara mal olur.)
mathmandan

@mathmandan maxdaha verimli olurdu, ancak ikinci noktaya kadar 0, aralık tarafından üretildiğinden -t:t( tilk sıfır olmayan katsayı nerede) çıktı almak için endişelenmem gerektiğinden, 2 bayt tasarruf ediyor!
Giuseppe

Oh çok güzel! (Ve güzel bir açıklama da.)
mathmandan

2

Jöle , 8 bayt

ASŒRḅ@Ðḟ

Çevrimiçi deneyin! ya da test paketi olarak!

Nasıl?

ASŒRḅ @ Ðḟ || Tam program (monadik bağlantı).

AS || Mutlak değerleri toplayın.
  ||R || Ve negatif değerinden simetrik kapsayıcı aralığı oluşturun.
       Ðḟ || Ve doğru bir değer verenleri atın ...
     || @ || Bunları polinomlara takarken (taban dönüştürmeyi kullanır).

Luis'in cevabına dayanarak . Bir alternatif .


(İzin verilen) ters sırayı alma ve yapma konusunda eksik olduğum bir şey var mı Ær+.Ḟ?
Jonathan Allan

Numpy ile Python yanıtı da öyle olmadığından biraz kafam karıştı ve bazı son durumları kaçırdığımı düşünüyorum.
Jonathan Allan

@JonathanAllan Beklediğim gibi, seninki başarısız oluyor [1,2,3].
Bay Xcoder

"Verilen denklem için bir çözüm yoksa, çıktı tanımsızdır"
Jonathan Allan

@JonathanAllan Ama yok başarısız için [10,-42,8]sağ?
Bay Xcoder

2

Oktav , 59 49 bayt

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

Çevrimiçi deneyin!

Bu benim R cevabımın bir limanı . Tek fark, açık bir şekilde kullanmak sign(t)ve endaralığı oluşturmak zorunda olduğum polyvalve polinomu hesaplaması gerektiğidir.

Girdileri azalan sırada katsayıların satır vektörü olarak alır.



2

C (GCC) , 127 126 123 bayt

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

Çevrimiçi deneyin!


açıklama

C (gcc) , 517 bayt

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

Çevrimiçi deneyin!


l+~j++için golfed edilebilirl-++j
Kevin Cruijssen

@KevinCruijssen Çok teşekkürler.
Jonathan Frech

@ ceilingcat Teşekkür ederim.
Jonathan Frech

1

Java 8, 141140 bayt

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

Esinlenerek @Rod 'ın Python 2 cevap (onun 82 bayt versiyonu) .

Eğlenceli bir meydan okuma! Polinomları araştırırken ve burada başkalarının bunu nasıl yaptığını görünce kesinlikle çok şey öğrendim.

Açıklama:

Çevrimiçi deneyin.

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 bayt

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

Azalan güç sırasıyla katsayıları alır ve çıktılar azalan sırada sonuçlanır.



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.