Moltiplicazione della matrice simbolica


26

Esistono molti modi diversi per spiegare la moltiplicazione delle matrici. Continuerò con una singola figura poiché credo che la maggior parte delle persone qui ne abbia familiarità (e la figura è molto descrittiva). Se desideri informazioni più dettagliate, ti suggerisco di visitare l' articolo di Wikipedia o la spiegazione su WolframMathWorld .

Semplice spiegazione:

Supponiamo di avere due matrici, A e B , dove A è 3 per 2 e B è 2 per 3. Se si esegue la moltiplicazione delle matrici su queste su matrici, AB o BA, si otterranno i risultati seguenti:

inserisci qui la descrizione dell'immagine

Sfida:

Implementa la moltiplicazione della matrice simbolica nella tua lingua. Devi prendere due matrici come input, in cui ogni elemento nelle matrici è rappresentato da un carattere ASCII non di spazi bianchi (punti codice 33-126). È necessario produrre il prodotto di queste matrici.

Regole relative all'output:

Un prodotto composto da due voci non deve contenere simboli in mezzo. E ' ab, senza a*b, a·b, times(a,b)o qualcosa di simile. Non lo aaè a^2.

La somma dei termini dovrebbe avere uno spazio (codice ASCII punto 32) in mezzo. E ' a b, non è a+b, plus(a,b)o qualcosa di simile.

La logica di queste due regole è: Tutti i caratteri non bianchi sono ammessi come simboli nelle matrici, quindi usarli come simboli matematici sarebbe disordinato. Quindi, quello che potresti normalmente scrivere come a*b+c*dsarà ab cd.

Puoi scegliere l'ordine dei termini. ab cd, dc abE cd basono matematicamente parlando lo stesso, in modo da poter scegliere l'ordine anche qui. L'ordine non deve essere coerente finché è matematicamente corretto.

Regole relative alla formattazione della matrice:

Una matrice può essere immessa in qualsiasi formato desiderato, tranne una singola stringa senza delimitatori tra le righe (questo perché l'output sarebbe completamente incasinato). Entrambe le matrici devono essere immesse nello stesso formato. Tutti gli esempi seguenti sono modi validi per inserire e produrre una matrice.

"ab;cd"     <- This will look awful, but it's still accepted.

"a,b\nc,d"

[[a,b],[c,d]] 

[a, b]
[c, d]

Sono consapevole che ciò consente molti formati che sembreranno disordinati, ma la sfida riguarda la moltiplicazione delle matrici, non la formattazione dell'output.

Regole generali:

  • Puoi assumere un input valido. La moltiplicazione delle matrici sarà sempre possibile con le dimensioni indicate.
  • Ci saranno solo due matrici.
  • Si può presumere che le matrici non siano vuote
  • Le funzioni integrate sono accettate (ma probabilmente un po 'ingombranti a causa dei requisiti di formattazione).
  • Naturalmente è possibile utilizzare caratteri di escape nell'input, se necessario ( \'anziché ').
  • Qualsiasi metodo di input e output standard è OK .

Casi test:

Le due matrici di input sono mostrate con una linea vuota in mezzo. L'output viene mostrato dopo Output:. Quando ci sono due matrici di output, è solo per mostrare altri output che sarebbero accettati.

Caso di test n. 1

Inputs:
[a]

[b]

Output:
[ab]
[ba]      <- Also OK

Caso di test n. 2

Inputs:
[a, b]
[1, 4] 
[y, {]

[%, 4, 1] 
[a, b, c]

Output:    
[a% ba, a4 bb, a1 bc] 
[1% 4a, 14 4b, 11 4c] 
[y% {a, y4 {b, y1 {c]

Caso di test n. 3:

Inputs:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 1, 2, 3]
[4, 5, 6, 7]

[a]
[b]
[c]
[d]

Output:
[1a 2b 3c 4d]
[5a 6b 7c 8d]
[9a 1b 2c 3d]
[4a 5b 6c 7d]

[d4 c3 b2 a1]      <-- Also OK
[d8 c7 b6 a5]
[1b 9a c2 3d]
[a4 b5 d7 6c]

Se la tua risposta alle regole sulla necessità ab cdinvece di a*b+c*dè: dovresti evitare ingombranti formati di input / output , quindi vorrei notare che i formati di input e output sono molto flessibili. Il fatto che non sia possibile utilizzare *e +per prodotti e somme potrebbe rendere più difficile l'utilizzo di un semplice built-in, ma non considero quella cosa negativa.


Per una funzione, è accettabile prendere due array 2D di stringhe e restituire un array 2D di stringhe?
Dennis,

Sì, nessun problema. Ma le dimensioni devono corrispondere, non è possibile trasporre il secondo input. Aveva senso?
Stewie Griffin,

Lo ha fatto, grazie per il chiarimento. Un'ultima domanda: potrei anche prendere una matrice 2D di caratteri come input e restituire una matrice 2D di stringhe?
Dennis,

@Dennis, ho scritto: "Entrambe le matrici devono essere immesse nello stesso formato". Ho dimenticato di menzionare la matrice di output lì, quindi la terrò così. Gli input devono essere nello stesso formato ma potresti avere un formato di output diverso. (Non mi piace molto quella soluzione, ma non voglio cambiare roba ora, penso che ci sia già una risposta che ha diversi formati di input e output)
Stewie Griffin,

Se intendi la risposta di Ruby, ho controllato e quello funziona altrettanto bene con le stringhe anziché con i caratteri.
Dennis,

Risposte:


9

Haskell , 62 61 byte

e=[]:e
a!b=[unwords.zipWith(++)r<$>foldr(zipWith(:))e b|r<-a]

Provalo online! Esempio di utilizzo:

Prelude> [["a","b"],["c","e"]] ! [["f","g"],["h","i"]]
[["af bh","ag bi"],["cf eh","cg ei"]]

Ho trovato un modo per ottenere una transposefunzione in un byte più breve rispetto all'uso dell'importazione:

import Data.List;transpose
e=[]:e;foldr(zipWith(:))e

Vecchia versione con importazione: (62 byte)

import Data.List
a!b=[unwords.zipWith(++)r<$>transpose b|r<-a]

Provalo online!

Questo è abbastanza simile alla mia risposta alla moltiplicazione di matrice non simbolica : a!b=[sum.zipWith(*)r<$>transpose b|r<-a]sostituendo la moltiplicazione (*)con concatenazione di stringhe (++)e sumcon la unwordsquale concatena un elenco di stringhe con uno spazio in mezzo. L'importazione è necessaria per la transposefunzione, quindi tutto sommato la trasposizione della seconda matrice utilizza fino alla metà dei byte ...


Vecchia versione senza importazione: (64 byte)

a![]=[];a!b=(unwords.zipWith(++)[h|h:_<-b]<$>a):a![s:t|_:s:t<-b]

Provalo online!

Con l'importazione e la transposefunzione che occupano così tanti byte, ho provato a risolvere l'attività senza importazione. Finora questo approccio si è rivelato più lungo di due byte, ma potrebbe essere più golfabile. Modifica: l'altro approccio in alto ora batte l'importazione!

La comprensione dell'elenco [s:t|_:s:t<-b]ottiene le code non vuote delle liste b, usando solo [t|_:t<-b]per ottenere le code sarebbe più corto di 4 byte (anche battendo la versione di importazione) ma aggiungere una riga vuota come ["","",""]alla matrice che suppongo non sia consentita.


6

Mathematica, 36 byte

Inner[#<>#2&,##,StringRiffle@*List]&

Innerè una generalizzazione di Mathematica Dot(cioè il solito prodotto matrice / vettoriale). Generalizza il prodotto punto consentendo di fornire due funzioni fe g, che verranno utilizzate al posto della normale moltiplicazione e aggiunta, rispettivamente. Stiamo sostituendo la moltiplicazione con #<>#2&(che unisce i due caratteri in una singola stringa) e l'aggiunta con StringRiffle@*List, che per prima cosa racchiude tutti i riepiloghi in un elenco, quindi StringRiffleli unisce con gli spazi.

Si potrebbe potenzialmente utilizzare l' Dotoperatore .e quindi trasformare il risultato, ma il problema è che cose del genere "a"*"a"si trasformerebbero immediatamente in "a"^2(lo stesso per le somme), il che sarebbe fastidioso rimetterlo a posto.


6

Rubino, 61 byte

->a,b{a.map{|x|b.transpose.map{|y|x.zip(y).map(&:join)*' '}}}

Esecuzione di esempio:

main(0):007> ->a,b{a.map{|x|b.transpose.map{|y|x.zip(y).map(&:join)*' '}}}[[[?a, ?b], [?1, ?4], [?y, ?{]], [[?%, ?4, ?1], [?a, ?b, ?c]]]
=> [["a% ba", "a4 bb", "a1 bc"], ["1% 4a", "14 4b", "11 4c"], ["y% {a", "y4 {b", "y1 {c"]]
->a,b{
a.map{|x|            # for each row of a
b.transpose.map{|y|  # and for each column of b
x.zip(y)             # match up corresponding elements
.map(&:join)         # join each pair together
*' '                 # join the entire thing on space
}}}

4

Clojure, 53 byte

#(for[a %](for[b(apply map vector %2)](map str a b)))

In esecuzione con argomenti [["a" "b"]["c" "e"]]e [["f" "g"]["h" "i"]]ritorni ((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei"))). Questo è in realtà più breve della versione numerica .


3

Dyalog APL , 10 byte

Accetta le matrici di caratteri come argomenti sinistro e destro. Restituisce la matrice di elenchi di caratteri. (APL rappresenta le stringhe come elenchi di caratteri.)

{∊⍺' '⍵}.,

ProvaAPL online!

Il prodotto interno normale è in APL +.×, ma l'aggiunta e la moltiplicazione possono essere qualsiasi funzione, in particolare:

L'aggiunta è stata sostituita da
{ una funzione anonima:
 l'
⍺ ' ' ⍵ elenco appiattito costituito dall'argomento sinistro, uno spazio e l'argomento destro
}

La moltiplicazione è stata sostituita dalla concatenazione, ,


2

Gelatina , 7 byte

Z;"þK€€

Questo è un collegamento diadico che prende B e A come argomenti (in quell'ordine) e restituisce AB . L'input e l'output sono in forma di array 2D di stringhe, che in realtà sono array 3D di caratteri. Un ulteriore byte può essere salvato prendendo matrici 2D di caratteri come input. Non sono sicuro che sia permesso.

Provalo online!

È un po 'difficile determinare cosa fa Jelly sotto il cofano quando sono coinvolte le stringhe, poiché fa molto splattening prima della stampa. Ecco come Jelly rappresenta l'input e l'output internamente.

Come funziona

Z;"þK€€  Dyadic link. Left argument: B. Right argument: A

Z        Zip/transpose B.
 ;"þ     Table vectorized concatenation; for each row in B' and each row in A,
         concatenate the corresponding strings.
    K€€  Join the arrays that correspond to the rows of A by spaces.

2

Prolog,> 256 byte

Sto usando {_ | _} che è un findall / 3, _ [_, _] che è un po 'di arg / 3 e somma (_) che è un po' aggregato. Possono essere usati tutti dentro è / 2:

*(X, Y, Z) :- functor(Y, matrice, _), L is len(X[1]), L =:= len(Y), !,
   M is len(X), N is len(Y[1]),
   Z is { { sum({ X[J,K] * Y[K,I] | between(1,L,K) })
                                  | between(1,N,I) }
                                  | between(1,M,J) }.

Insieme alle definizioni extra per i predicati sopra menzionati e il non standard è / 2 che può restituire più di numeri, è sicuro> 256 byte.


1

JavaScript (ES6), 65 byte

(a,b)=>a.map(c=>b[0].map((_,j)=>c.map((e,i)=>e+b[i][j]).join` `))

Accetta input come due matrici 2D di caratteri e restituisce una matrice 2D di stringhe. Aggiungi 10 byte per supportare l'input come due array 1D di stringhe.


1

Pyth, 14 byte

clQmj;sMCd*QCE

Un programma che accetta input di due elenchi di caratteri bidimensionali separati da una nuova riga e stampa un elenco bidimensionale di stringhe.

Suite di test

Come funziona

[Spiegazione che verrà dopo]


1

Pip , 17 byte

{Y Zb{a._JsMy}Ma}

Questa è una funzione che accetta due elenchi nidificati di stringhe (a carattere singolo) e restituisce un elenco nidificato di stringhe. Provalo online! (con due casi di test).

Spiegazione

Gli argomenti di una {}funzione delimitata vengono assegnati alle variabili locali aa e. Il primo argomento di una funzione lambda è rappresentato da _.

{               }  Define a function:
   Zb              Zip rows of b, transposing it
 Y                 Yank into global variable y for access in nested function
     {       }Ma   To the rows of a, map this function:
           My       To the rows of y (i.e. columns of b), map this function:
      a._           Concatenate, itemwise, the current row of a and row of y
         Js         Join the resulting list on space
                   The result of the outer map operation is returned
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.