기호 행렬 곱셈


26

행렬 곱셈을 설명하는 방법에는 여러 가지가 있습니다. 나는 대부분의 사람들이 그것에 익숙하다고 생각하기 때문에 하나의 그림을 고수 할 것입니다 (그리고 그림은 매우 묘사 적입니다). 더 자세한 정보를 원하시면 Wikipedia-article 또는 WolframMathWorld에 대한 설명을 방문하십시오 .

간단한 설명 :

두 행렬이 있다고 가정 와 B를 어디에서, A는 3 별 2이고, B는 2로-3입니다. AB 또는 BA 행렬에 행렬 곱셈을 수행하면 다음과 같은 결과를 얻을 수 있습니다.

여기에 이미지 설명을 입력하십시오

도전:

귀하의 언어로 기호 행렬 곱셈을 구현하십시오 . 행렬의 각 요소는 공백이 아닌 ASCII 문자로 표시됩니다 (코드 포인트 33-126). 이 행렬의 곱을 출력해야합니다.

출력에 관한 규칙 :

두 항목의 제품 사이에 기호가 없어야합니다. 그건 ab아니, a*b, a·b, times(a,b)비슷하거나 뭔가. 그것은이다 aa,하지 a^2.

항의 합계는 사이에 공백 (ASCII 코드 포인트 32)이 있어야합니다. 그건 a b아닌 a+b, plus(a,b)유사하거나 뭔가.

이 두 규칙의 이론적 근거는 다음과 같습니다. 공백이 아닌 모든 문자는 행렬에서 기호로 사용할 수 있으므로 수학 기호로 사용하는 것이 어려울 수 있습니다. 따라서 일반적으로 쓸 수 a*b+c*d있는 것은 ab cd입니다.

용어의 순서를 선택할 수 있습니다. ab cd, dc ab그리고 cd ba당신이 너무 여기에 순서를 선택할 수 있도록 수학적으로, 같은 말하기된다. 순서가 수학적으로 정확하다면 일관성이있을 필요는 없습니다.

행렬 형식과 관련된 규칙 :

행 사이에 구분자가없는 단일 문자열을 제외하고 원하는 형식으로 행렬을 입력 할 수 있습니다 (출력이 완전히 엉망이기 때문입니다). 두 행렬 모두 같은 형식으로 입력해야합니다. 아래의 모든 예제는 행렬을 입력하고 출력하는 유효한 방법입니다.

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

"a,b\nc,d"

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

[a, b]
[c, d]

나는 이것이 복잡한 것처럼 보이는 많은 형식을 허용한다는 것을 알고 있지만 문제는 출력 형식을 지정하지 않고 행렬을 곱하는 것입니다.

일반적인 규칙:

  • 유효한 입력을 가정 할 수 있습니다. 주어진 차원에서 행렬 곱셈은 항상 가능합니다.
  • 두 개의 행렬 만 있습니다.
  • 행렬이 비어 있지 않다고 가정 할 수 있습니다.
  • 내장 함수가 허용되지만 형식 요구 사항으로 인해 약간 번거로울 수 있습니다.
  • 물론 필요한 경우 입력 \'대신 이스케이프 문자를 사용할 수 있습니다 ( 대신 ').
  • 모든 표준 입력 및 출력 방법은 정상 입니다.

테스트 사례 :

두 입력 행렬은 사이에 빈 줄로 표시됩니다. 출력은 다음에 표시 Output:됩니다. 두 개의 출력 행렬이있는 경우 허용되는 다른 출력 만 표시합니다.

테스트 사례 # 1

Inputs:
[a]

[b]

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

테스트 사례 # 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]

테스트 사례 # 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]

요구에 대한 규칙에 응답하는 경우 ab cd대신이 a*b+c*d있다 : 당신은 성가신 입력 / 출력 형식을 피해야한다 , 그때는 입력 및 출력 형식은 매우 유연합니다 싶습니다. 사실은 당신이 사용할 수없는 *+제품과 합계 것이 어려워 내장 된 간단한을 사용할 수 있도록 수도 있지만 내가 부정적인 일을 생각하지 않는다.


함수의 경우 두 개의 2D 문자열 배열을 가져 와서 2D 문자열 배열을 허용합니까?
Dennis

예, 문제 없습니다. 그러나 치수가 일치해야하며 두 번째 입력을 바꿀 수 없습니다. 말이 되나요?
Stewie Griffin

명확하게 해주셔서 감사합니다. 마지막 질문 : 2D 문자 배열을 입력으로 사용하여 2D 문자열 배열을 반환 할 수 있습니까?
Dennis

@Dennis는 다음과 같이 썼습니다. "모두 매트릭스는 같은 형식으로 입력해야합니다." 나는 거기에 출력 행렬을 언급하는 것을 잊었으므로 그냥 이렇게 유지하겠습니다. 입력은 동일한 형식이어야하지만 다른 출력 형식을 가질 수 있습니다. (나는 그 솔루션을 정말로 좋아하지 않지만, 지금 물건을 바꾸고 싶지 않다, 나는 이미 다른 입력 및 출력 형식을 가진 하나의 대답이 있다고 생각한다)
Stewie Griffin

Ruby 답변을 의미한다면, 나는 확인했고 문자 대신 문자열과 잘 작동합니다.
Dennis

답변:


9

하스켈 , 62 61 바이트

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

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

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

transpose가져 오기를 사용하는 것보다 1 바이트 더 짧은 함수 를 얻는 방법을 찾았습니다 .

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

가져 오기가 포함 된 이전 버전 : (62 바이트)

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

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

이것은 내 대답은 매우 유사 비 상징적 인 행렬 곱셈 : a!b=[sum.zipWith(*)r<$>transpose b|r<-a], 곱셈 대체 (*)문자열 연결로를 (++)sum함께 unwords하는 사이에 공백 문자열 목록을 연결합니다. 가져 오기는 transpose함수에 필요 하므로 두 번째 행렬의 모든 조옮김에서 모두 바이트의 절반을 사용합니다 ...


가져 오기가없는 이전 버전 : (64 바이트)

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

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

가져 오기 및 transpose함수가 너무 많은 바이트를 차지하면서 가져 오기없이 작업을 해결하려고했습니다. 지금까지이 방법은 2 바이트 더 길어진 것으로 나타 났지만 더 골프화 할 수 있습니다. 편집 : 상단의 다른 접근 방식은 이제 수입을 능가합니다!

목록 이해 [s:t|_:s:t<-b]는를 b사용하여 목록의 비어 있지 않은 꼬리를 가져옵니다.[t|_:t<-b] (심지어 가져 오기 버전을 구타) 그러나 같은 빈 행을 추가 4 짧은 바이트 꼬리가 될 것 얻기 위해 ["","",""]내가 할 수 없습니다 가정 매트릭스합니다.


6

수학, 36 바이트

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

InnerMathematica Dot(일반 매트릭스 / 벡터 제품) 의 일반화입니다 . 그것은 일반적인 곱셈과 덧셈 대신에 사용될 두 개의 함수 f와 를 제공함으로써 내적을 일반화합니다 g. 곱셈을 #<>#2&(두 문자를 단일 문자열로 결합)로 StringRiffle@*List바꾸고을 추가하여 먼저 모든 소환 자를 목록으로 StringRiffle묶은 다음 공백으로 결합합니다.

잠재적으로 Dot연산자를 사용하여 .결과를 변환 할 수는 있지만 문제는 "a"*"a"즉시 "a"^2(합과 동일) 변환되어 다시 선택하기가 성 가실 것입니다.


6

루비, 61 바이트

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

샘플 실행 :

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

클로저, 53 바이트

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

인수로 실행 [["a" "b"]["c" "e"]]하고를 [["f" "g"]["h" "i"]]반환합니다 ((("af" "bh") ("ag" "bi")) (("cf" "eh") ("cg" "ei"))). 실제로는 숫자 버전 보다 짧습니다 .


3

Dyalog APL , 10 바이트

문자 행렬을 왼쪽 및 오른쪽 인수로 사용합니다. 문자 목록의 행렬을 반환합니다. (APL은 문자열을 문자 목록으로 나타냅니다.)

{∊⍺' '⍵}.,

TryAPL 온라인!

일반적인 내부 제품은 APL +.×이지만 더하기 및 곱하기는 특히 다음과 같은 기능 일 수 있습니다.

 왼쪽 인수, 공백 및 오른쪽 인수로 구성된  병합 목록이
{ 익명 함수 로 대체되었습니다 .

⍺ ' ' ⍵
}

곱셈은 ​​연결로 대체되었습니다. ,


2

젤리 , 7 바이트

Z;"þK€€

이것은 BA 를 인수로 (순서대로) 가져와 AB를 반환 하는 2 차원 링크입니다 . 입력 및 출력은 2D 문자열 배열 형식이며 실제로 3D 문자 배열입니다. 2D 문자 배열을 사용하여 추가 바이트를 절약 할 수 있습니다 입력 . 그것이 허용되는지 확실하지 않습니다.

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

문자열이 관련 될 때 Jelly가 후드 아래에서 수행하는 작업을 결정하는 것은 약간 어렵습니다. 인쇄하기 전에 많은 분할 작업을 수행하기 때문입니다. 이것은 젤리가 입력과 출력을 내부적으로 나타내는 방법입니다.

작동 원리

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

프롤로그,> 256 바이트

{_ | find_ / 3 인 _}, arg / 3 인 _ [_, _], 집계 인 sum (_) 그것들은 모두 is / 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) }.

위에서 언급 한 술어에 대한 추가 정의 및 숫자보다 많은 수를 리턴 할 수있는 비표준 is / 2 와 함께, > 256 바이트입니다.


1

자바 스크립트 (ES6), 65 바이트

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

입력을 두 개의 2D 문자 배열로 취하고 2D 문자열 배열을 반환합니다. 두 개의 1D 문자열 배열로 입력을 지원하려면 10 바이트를 추가하십시오.


1

Pyth, 14 바이트

clQmj;sMCd*QCE

줄 바꾸기로 구분 된 2 차원 문자 목록을 입력하고 2 차원 문자열 목록을 인쇄하는 프로그램입니다.

테스트 스위트

작동 원리

[나중에 설명]


1

, 17 바이트

{Y Zb{a._JsMy}Ma}

이것은 (한 문자) 문자열의 두 개의 중첩 된 목록을 가져오고 중첩 된 문자열 목록을 반환하는 함수입니다. 온라인으로 사용해보십시오!(두 가지 테스트 사례 포함).

설명

{}구분 된 함수 에 대한 인수 는에 로컬 변수 a에 할당 됩니다 e. 람다 함수의 첫 번째 인수는로 표시됩니다 _.

{               }  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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.