Existem muitas maneiras diferentes de explicar a multiplicação de matrizes. Vou ficar com uma única figura, pois acredito que a maioria das pessoas aqui está familiarizada com ela (e a figura é muito descritiva). Se você quiser informações mais detalhadas, sugiro que visite o artigo da Wikipedia ou a explicação sobre o WolframMathWorld .
Explicação simples:
Suponha que você tenha duas matrizes, A e B , onde A é 3 por 2 e B é 2 por 3. Se você executar a multiplicação de matrizes nessas matrizes, AB ou BA, obterá os resultados abaixo:
Desafio:
Implemente a multiplicação matricial simbólica no seu idioma. Você deve usar duas matrizes como entrada, em que cada elemento nas matrizes é representado por um caractere ASCII que não é um espaço em branco (pontos de código 33-126). Você deve produzir o produto dessas matrizes.
Regras relativas à saída:
Um produto de duas entradas não deve ter nenhum símbolo no meio. É ab
, não a*b
, a·b
, times(a,b)
ou algo similar. É aa
, não a^2
.
A soma dos termos deve ter um espaço (ponto 32 do código ASCII) no meio. É a b
, não a+b
, plus(a,b)
ou algo semelhante.
A lógica para essas duas regras é: todos os caracteres de espaço não em branco são permitidos como símbolos nas matrizes, portanto, usá-los como símbolos matemáticos seria uma bagunça. Então, o que você normalmente poderia escrever como a*b+c*d
será ab cd
.
Você pode escolher a ordem dos termos. ab cd
, dc ab
e cd ba
matematicamente estão falando o mesmo, então você também pode escolher o pedido aqui. O pedido não precisa ser consistente, desde que seja matematicamente correto.
Regras relativas à formatação da matriz:
Uma matriz pode ser inserida no formato que você quiser, exceto uma única sequência sem delimitadores entre linhas (isso ocorre porque a saída seria completamente confusa). Ambas as matrizes devem ser inseridas no mesmo formato. Todos os exemplos abaixo são formas válidas de inserir e produzir uma matriz.
"ab;cd" <- This will look awful, but it's still accepted.
"a,b\nc,d"
[[a,b],[c,d]]
[a, b]
[c, d]
Estou ciente de que isso permite muitos formatos que parecerão confusos, mas o desafio é multiplicar matrizes, não formatar a saída.
Regras gerais:
- Você pode assumir uma entrada válida. A multiplicação de matrizes sempre será possível com as dimensões especificadas.
- Haverá apenas duas matrizes.
- Você pode assumir que as matrizes não estão vazias
- Funções internas são aceitas (mas provavelmente um pouco complicadas devido aos requisitos de formatação).
- Obviamente, você pode usar caracteres de escape na entrada, se necessário (em
\'
vez de'
). - Qualquer método padrão de entrada e saída está OK .
Casos de teste:
As duas matrizes de entrada são mostradas com uma linha vazia no meio. A saída é mostrada depois Output:
. Quando existem duas matrizes de saída, é apenas para mostrar outras saídas que seriam aceitas.
Caso de teste nº 1
Inputs:
[a]
[b]
Output:
[ab]
[ba] <- Also OK
Caso de teste 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 de teste 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 a sua resposta às regras sobre exigir em ab cd
vez de a*b+c*d
for: você deve evitar formatos de entrada / saída complicados , gostaria de observar que os formatos de entrada e saída são muito flexíveis. O fato de você não poder usar *
e +
para produtos e somas pode dificultar o uso de um simples embutido, mas não considero isso negativo.
fonte
Respostas:
Haskell ,
6261 bytesExperimente online! Exemplo de uso:
Eu encontrei uma maneira de obter uma
transpose
função em um byte menor do que usando a importação:Versão antiga com importação: (62 bytes)
Experimente online!
Isso é bastante semelhante à minha resposta à multiplicação matricial não simbólica :
a!b=[sum.zipWith(*)r<$>transpose b|r<-a]
substituindo a multiplicação(*)
pela concatenação de strings(++)
esum
com aunwords
qual concatenamos uma lista de strings com um espaço no meio. A importação é necessária para atranspose
função, portanto, em toda a transposição da segunda matriz, consome metade dos bytes ...Versão antiga sem importação: (64 bytes)
Experimente online!
Com a importação e a
transpose
função ocupando muitos bytes, tentei resolver a tarefa sem importar. Até agora, essa abordagem acabou sendo dois bytes mais longa, mas poderia ser mais fácil de jogar. Edit: A outra abordagem no topo agora supera a importação!A compreensão da lista
[s:t|_:s:t<-b]
obtém as caudas não vazias das listasb
, usar apenas[t|_:t<-b]
para obter as caudas seria 4 bytes mais curto (até superando a versão de importação), mas acrescenta uma linha vazia como["","",""]
a matriz que, suponho, não é permitida.fonte
Mathematica, 36 bytes
Inner
é uma generalização do MathematicaDot
(isto é, o produto matriz / vetor usual). Ele generaliza o produto escalar, permitindo que você forneça duas funçõesf
eg
, que serão usadas no lugar da multiplicação e adição usuais, respectivamente. Estamos substituindo a multiplicação por#<>#2&
(que une os dois caracteres em uma única sequência de caracteres) e a adição porStringRiffle@*List
, que primeiro agrupa todos os summands em uma lista e osStringRiffle
une a espaços.Pode-se potencialmente usar o
Dot
operador.
e depois transformar o resultado, mas o problema é que coisas como essas"a"*"a"
seriam imediatamente transformadas em"a"^2
(o mesmo para somas), o que seria irritante para separar novamente.fonte
Ruby, 61 bytes
Exemplo de execução:
fonte
Clojure, 53 bytes
Correndo com argumentos
[["a" "b"]["c" "e"]]
e[["f" "g"]["h" "i"]]
retornos((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei")))
. Na verdade, é mais curto que a versão numérica .fonte
Dyalog APL , 10 bytes
Toma matrizes de caracteres como argumentos esquerdo e direito. Retorna a matriz de listas de caracteres. (APL representa cadeias de caracteres como listas de caracteres.)
TryAPL online!
O produto interno normal está no APL
+.×
, mas a adição e multiplicação podem ter quaisquer funções, em particular:A adição foi substituída por
{
uma função anônima:∊
a⍺ ' ' ⍵
lista nivelada que consiste no argumento esquerdo, um espaço e o argumento correto⍵
}
A multiplicação foi substituída pela concatenação,
,
fonte
Geléia , 7 bytes
Este é um link diádico que recebe B e A como argumentos (nessa ordem) e retorna AB . Entrada e saída estão na forma de matrizes 2D de seqüências de caracteres, que são na verdade matrizes 3D de caracteres. Um byte adicional pode ser salvo usando matrizes 2D de caracteres como entrada. Não tenho certeza se isso é permitido.
Experimente online!
É um pouco difícil determinar o que a Jelly faz sob o capô quando as cordas estão envolvidas, pois faz muito barulho antes da impressão. É assim que o Jelly representa entrada e saída internamente.
Como funciona
fonte
Prolog,> 256 bytes
Eu estou usando {_ | _} que é um findall / 3, _ [_, _] que é um pouco de arg / 3 e soma (_) que é uma agregação. Todos eles podem ser usados dentro de / 2:
Juntamente com as definições extras para os predicados mencionados acima e o não padrão é / 2 que pode retornar mais que números, é certo que> 256 bytes.
fonte
JavaScript (ES6), 65 bytes
Recebe a entrada como duas matrizes 2D de caracteres e retorna uma matriz 2D de seqüências de caracteres. Adicione 10 bytes para suportar a entrada como duas matrizes 1D de cadeias.
fonte
Pitão, 14 bytes
Um programa que recebe entrada de duas listas bidimensionais de caracteres separadas por nova linha e imprime uma lista bidimensional de seqüências de caracteres.
Suíte de teste
Como funciona
[Explicação que vem depois]
fonte
Pip , 17 bytes
Essa é uma função que pega duas listas aninhadas de seqüências de caracteres (um caractere) e retorna uma lista aninhada de seqüências de caracteres. Experimente online! (com dois casos de teste).
Explicação
Argumentos para uma
{}
função delimitada são atribuídos às variáveis locaisa
parae
. O primeiro argumento de uma função lambda é representado por_
.fonte