Construire une matrice compagnon


15

Vous avez un certain nombre de polynômes qui sont seuls, alors faites-en des compagnons (qui ne menaceront pas de poignarder)!

Pour un polynôme de degré n, il existe une matrice de cuben by n compagnon . Vous devez créer une fonction qui accepte une liste de coefficients pour un polynôme dans l'ordre croissant ( ) ou décroissant ( ) (mais pas les deux) et générer la matrice associée. a + bx +cx^2 + …ax^n + bx^(n-1) + cx^(n-2)+…

pour un polynôme c0 + c1x + c2x^2 + ... + cn-1x^(n-1) + x^n, sa matrice compagnon est

     (0, 0, 0, ..., -c0  ),
     (1, 0, 0, ..., -c1  ),
     (0, 1, 0, ..., -c2  ),
     (...................),
     (0, 0, ..., 1, -cn-1)

notez que le coefficient de x^nest 1. Pour toute autre valeur, divisez tous les autres coefficients par x^n. De plus, les 1 sont décalés de la diagonale.

Si le langage que vous utilisez contient déjà une fonction ou un module qui fait cela, vous ne pouvez pas l'utiliser - vous devez écrire le vôtre.

Par exemple, si vous en aviez 4x^2 – 7x + 12, les coefficients dans l'ordre croissant sont (12, -7, 4)et dans l'ordre décroissant (4, -7, 12). La fonction ou le programme doit sortir [(0, -3.0), (1, 1.75)]pour l'un ou l'autre ordre. Spécifiez la commande acceptée par votre code. Le polynôme minimum doit être quadratique. Les coefficients sont limités aux nombres réels.

Vous trouverez ci-dessous des exemples - votre sortie n'a pas à correspondre à la jolie mise en forme, mais elle doit sortir les lignes (dans le ()) de la matrice dans l'ordre.

Ordre croissant:

input:
    [3., 7., -5., 4., 1.]
output:
    [(0, 0, 0, -3.),
     (1, 0, 0, -7.),
     (0, 1, 0,  5.),
     (0, 0, 1, -4.)]

input:
    [-4., -7., 13.]
output:
    [(0, 0.30769231),
     (1, 0.53846154)]

input:
    [23., 1., 92., 8., -45., 88., 88.]
output:
    [(0, 0, 0, 0, 0, -0.26136364),
     (1, 0, 0, 0, 0, -0.01136364),
     (0, 1, 0, 0, 0, -1.04545455),
     (0, 0, 1, 0, 0, -0.09090909),
     (0, 0, 0, 1, 0,  0.51136364),
     (0, 0, 0, 0, 1, -1.        )]

Ordre décroissant:

input:
    [1., 4., -5., 7., 3.]
output:
    [(0, 0, 0, -3.),
     (1, 0, 0, -7.),
     (0, 1, 0,  5.),
     (0, 0, 1, -4.)]

input:
    [13., -7., -4.]
output:
    [(0, 0.30769231),
     (1, 0.53846154)]

input:
    [88., 88., -45., 8., 92.,1., 23.]
output:
    [(0, 0, 0, 0, 0, -0.26136364),
     (1, 0, 0, 0, 0, -0.01136364),
     (0, 1, 0, 0, 0, -1.04545455),
     (0, 0, 1, 0, 0, -0.09090909),
     (0, 0, 0, 1, 0,  0.51136364),
     (0, 0, 0, 0, 1, -1.        )]

Dennis gagne avec 20 octets!


2
Les coefficients sont réels (pas complexes), non?
Luis Mendo

1
Les programmes sont-ils valides ou fonctionnent-ils uniquement? (Gardez à l'esprit que restreindre le concours aux fonctions interdit les langages intéressants sans fonctions.)
lirtosiast

1
Quel est le polynôme de degré minimum dont nous devons tenir compte?
Alex A.

Réponses:


3

CJam, 23 20 octets

{)W*f/_,,_ff=1f>\.+}

Il s'agit d'une fonction qui extrait l'entrée (ordre croissant) de la pile et pousse la sortie en retour.

Essayez-le en ligne dans l' interpréteur CJam .

Comment ça fonctionne

)   e# Pop the last element from the input array.
W*  e# Multiply it by -1.
f/  e# Divide the remaining array elements by this product.
_,  e# Push a copy of the array and compute its length (L).
,_  e# Push [0 ... L-1] twice.
ff= e# For each I in [0 ... L-1]:
    e#   For each J in [0 ... L-1]:
    e#     Push (I==J).
    e# This pushes the L x L identity matrix.
1f> e# Discard the first element of each row, i.e., the first column.
\   e# Swap the result with the modified input.
.+  e# Vectorized append; append the input as a new column.

3

CJam, 32 31 28 octets

0q~)f/f-_,(_,\0a*1+fm<~]W%z

Essayez-le en ligne

Cela prend l'entrée dans l'ordre croissant, en utilisant le format de liste CJam. Exemple d'entrée:

[-4.0 -7.0 13.0]

Explication:

0     Push a 0 for later sign inversion.
q~    Get and interpret input.
)     Pop off last value.
f/    Divide all other values by it.
f-    Invert sign of values.
_,    Get count of values, which corresponds to n.
(     Decrement by 1.
_,    Create list of offsets [0 1 ... n-1] for later.
\     Swap n-1 back to top.
0a*   Create list of n-1 zeros.
1+    Append a 1. This is the second-but-last column [0 0 ... 0 1].
fm<   Apply rotation with all offsets [0 1 ... n-1] to column.
~     Unwrap the list of 0/1 columns.
]     Wrap all columns
W%    Invert their order from last-to-first to first-to last.
z     Transpose to get final matrix.
`     Convert to string for output.

3

APL, 40 30 octets

{(-n↑⍵÷⊃⊖⍵),⍨⍉1↓⍉∘.=⍨⍳n←1-⍨≢⍵}

Accepte les entrées dans l'ordre croissant.

Explication:

{
                        n←1-⍨≢⍵    ⍝ Define n = length(input)-1
                   ∘.=⍨⍳           ⍝ Create an n×n identity matrix
               ⍉1↓⍉                ⍝ Drop the leftmost column
            ,⍨                     ⍝ Append on the right:
  (-n↑⍵                            ⍝ n negated coefficients,
       ÷⊃⊖⍵)                       ⍝ divided by the n+1st
}

Essayez-le en ligne


3

Julia, 43 octets

c->rot180([-c[2:(n=end)]/c[] eye(n-1,n-2)])

Cela utilise l'ordre décroissant pour l'entrée. Il construit la matrice tournée à 180 degrés, afin de permettre une utilisation plus efficace de "l'oeil", puis fait pivoter la matrice dans la bonne orientation.


2

Julia, 64 44 octets

c->(k=c[n=end];[eye(n-=1)[:,2:n] -c[1:n]/k])

Accepte un vecteur des coefficients dans l'ordre croissant.

Non golfé:

function f(c::Array)
    # Simultaneously define k = the last element of c and
    # n = the length of c
    k = c[n = end]

    # Decrement n, create an n×n identity matrix, and exclude the
    # first column. Horizontally append the negated coefficients.
    [eye(n-=1)[:,2:n] -c[1:n]/k]
end

Essayez-le en ligne

20 octets enregistrés grâce à Glen O!


2

R, 71 59 octets

Prend les entrées dans l'ordre croissant.

function(x)cbind(diag(n<-length(x)-1)[,2:n],-x[1:n]/x[n+1])

Non golfé:

f <- function(x) {
    # Get the length of the input
    n <- length(x)-1

    # Create an identity matrix and exclude the first column
    i <- diag(n)[, 2:n]

    # Horizontally append the negated coefficients divided
    # by the last one
    cbind(i, -x[1:n]/x[n+1])
}

1

Matlab, 66 octets

function y=f(c)
n=numel(c);y=[[0*(3:n);eye(n-2)] -c(1:n-1)'/c(n)];

Il utilise l'ordre croissant pour l'entrée, au format [3., 7., -5., 4., 1.]ou [3. 7. -5. 4. 1.].

Essayez-le en ligne (dans Octave).

Exemple (dans Matlab):

>> f([23., 1., 92., 8., -45., 88., 88.])
ans =
                   0                   0                   0                   0                   0  -0.261363636363636
   1.000000000000000                   0                   0                   0                   0  -0.011363636363636
                   0   1.000000000000000                   0                   0                   0  -1.045454545454545
                   0                   0   1.000000000000000                   0                   0  -0.090909090909091
                   0                   0                   0   1.000000000000000                   0   0.511363636363636
                   0                   0                   0                   0   1.000000000000000  -1.000000000000000

Si un programme est valide (au lieu d'une fonction), avec stdin et stdout:

Matlab, 59 octets

c=input('');n=numel(c);[[0*(3:n);eye(n-2)] -c(1:n-1)'/c(n)]

Je pense que vous pouvez le fairen=numel(c=input(''));
lirtosiast

@ThomasKwa Merci! Cependant, ce n'est pas une syntaxe valide dans Matlab. n=numel(input(''))serait valide, mais je dois réutiliser cplus tard
Luis Mendo

Pardon; cela a fonctionné dans Octave où je l'ai testé.
lirtosiast

1

Octave, 45 44 octets

En supposant que cc'est un vecteur colonne avec le coefficient de la puissance la plus élevée de xà la fin.

@(c)[eye(n=rows(c)-1)(:,2:n),-c(1:n)/c(end)]

Ancienne version:

@(c)[eye(n=numel(c)-1)(:,2:n),-c(1:n)/c(end)]

Haut cinq, Julia!


1

Python 2, 141 octets

Ma propre tentative:

def C(p):
 c,r=p.pop(0),range;d=[-i/c for i in p];n=len(d);m=[[0]*n for i in r(n)]
 for i in r(n-1):m[i][i+1]=1
 m[-1]=d[::-1];return zip(*m)

Prend une liste des coefficients dans l'ordre décroissant et construit d'abord la transposition de la matrice compagnon - connue pour poignarder et être bavarde. Le retour utilise zip pour produire la transposition de cette transposition pour obtenir la matrice réelle.

>>> C([1., 4., -5., 7., 3.])
[(0, 0, 0, -3.0), (1, 0, 0, -7.0), (0, 1, 0, 5.0), (0, 0, 1, -4.0)]

1

JavaScript (ES6) 85

Ordre croissant.

Testez l'exécution de l'extrait ci-dessous dans n'importe quel navigateur compatible EcmaScript 6.

f=c=>alert(c.map((v,i)=>c.map((x,j)=>++j-i?j-c.length?0:-v/m:1),m=c.pop()).join(`
`))

// test
// redefine alert to write into the snippet body
alert=x=>O.innerHTML+=x+'\n'

function test() {
  v=I.value.match(/\d+/g)
  I.value=v+''
  alert(v)
  f(v)
}  

test()
<input value='23.,1.,92.,8.,-45.,88.,88.' id=I><button onclick="test()">-></button>
<pre id=O></pre>


0

TI-BASIC, 50 octets

Ans→X
List▶matr(ΔList(Ans-cumSum(Ans)),[A]
dim(Ans
augment(augment(0randM(Ans-2,1),identity(Ans-2))ᵀ,[A]∟X(Ans)⁻¹

Prend les entrées dans l'ordre croissant. Notez que cela ne fonctionnera pas pour les polynômes de degré <2, car TI-BASIC ne prend pas en charge les matrices ou listes vides. En attendant une décision de l'OP, je peux résoudre ce problème au prix de quelques octets.

Tout d'abord, nous stockons la liste dans ∟Xpour utiliser le dernier élément plus tard; ensuite, nous calculons ΔList(Ans-cumSum(Ans)), qui est juste la liste inversée avec le dernier élément coupé, et le convertissons en un vecteur de colonne. Puisque List▶matr(ne modifie pas Ans, nous pouvons utiliser la ligne suivante pour prendre la dimension de la liste, que nous utilisons trois fois. TI-BASIC n'a pas de concaténation verticale, nous devons donc prendre des transposés et concaténer horizontalement. Dans la dernière ligne, [A]/∟X(Anscela ne fonctionnerait pas car les matrices peuvent être multipliées par des scalaires mais pas divisées.

Un côté: pour générer le vecteur ligne de zéros, nous profitons de la randM(commande rarement utile . randM(crée une matrice aléatoire, mais ses entrées sont toujours des entiers aléatoires compris entre -9 et 9 (!), il n'est donc vraiment utile que de créer des matrices nulles.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.