이산 컨벌루션 또는 다항식 곱셈


19

비어 있지 않은 두 개의 정수 목록이 주어지면 제출물이 두 개의 이산 컨벌루션 을 계산하고 반환해야합니다 . 흥미롭게도리스트 요소를 다항식의 계수로 간주하면 두리스트의 컨볼 루션은 두 다항식의 곱의 계수를 나타냅니다.

정의

리스트 감안 A=[a(0),a(1),a(2),...,a(n)]하고 B=[b(0),b(1),b(2),...,b(m)](설정 a(k)=0 for k<0 and k>nb(k)=0 for k<0 and k>m다음의 두 컨벌루션하는)로 정의되는 A*B=[c(0),c(1),...,c(m+n)]c(k) = sum [ a(x)*b(y) for all integers x y such that x+y=k]

규칙

  • 귀하의 언어에 편리한 입력 및 출력 형식이 허용됩니다.
  • 컨볼 루션 내장, 컨볼 루션 행렬 생성, 상관 관계 및 다항식 곱셈은 허용되지 않습니다.

[1,1]*[1] = [1,1]
[1,1]*[1,1] = [1,2,1]
[1,1]*[1,2,1] = [1,3,3,1]
[1,1]*[1,3,3,1] = [1,4,6,4,1]
[1,1]*[1,4,6,4,1] = [1,5,10,10,5,1]

[1,-1]*[1,1,1,1,1] = [1,0,0,0,0,-1]
[80085,1337]*[-24319,406] = [-1947587115,7,542822]

3
이 스펙은 길이 n, m의 입력은 길이 n + m-1의 출력을 생성해야하지만 이것은 테스트 케이스에 대해 유지되지 않으며, 유지하지 [1,1]*[] = []못할 수도 있습니다 []*[] = ?. 빈 목록에 컨볼 루션이 잘 정의되어 있지 않습니다. 입력 목록이 비어 있지 않다고 보장해야한다고 생각합니다.
Anders Kaseorg

1
@AndersKaseorg 당신이 맞아요, 내가 바꿀 게요.
flawr

답변:


14

J, 10 8 바이트

[:+//.*/

용법:

ppc =: [:+//.*/    NB. polynomial product coefficients 
80085 1337 ppc _24319 406
_1947587115 7 542822

설명 : 프로그램은 두 개의 목록을 취하고 곱셈 테이블을 만든 다음 양의 대각선에 숫자를 더합니다.


매우 영리한 접근법!
Luis Mendo

괄호를 세지 않아도됩니다. 내부 표현은 변수에 할당 할 수있는 암묵적 동사로 평가됩니다.
Dennis

부사의 훌륭한 예!
마일

6

MATL , 19 바이트

PiYdt"TF2&YStpsw]xx

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

설명

이것은 두 개의 입력으로 블록 대각 행렬을 만들고 첫 번째를 반전시킵니다. 예를 들어 input [1 4 3 5]을 사용 [1 3 2]하면 행렬은

[ 5 3 4 1 0 0 0
  0 0 0 0 1 3 2 ]

회선의 각 항목은 첫 번째 행을 한 위치 오른쪽으로 이동하고 각 열의 곱을 계산하고 모든 결과를 합산하여 얻습니다.

원칙적으로 시프트는 왼쪽에서 0으로 채워야합니다. 동등하게, 매트릭스는 적절한 엔트리에서 0을 포함하기 때문에 순환 쉬프팅이 사용될 수있다.

예를 들어, 첫 번째 결과는 쉬프트 된 매트릭스로부터 얻어진다

[ 0 5 3 4 1 0 0
  0 0 0 0 1 3 2 ]

따라서 1*1 == 1. 두 번째는

[ 0 0 5 3 4 1 0
  0 0 0 0 1 3 2 ]

그리고 4*1+1*3 == 7등입니다. 이것은 입력 길이 와 m+n-1시간 이 수행되어야합니다 . 이 코드는 반복 (일부 바이트 저장)과 함께 루프를 사용 하고 마지막 결과를 버립니다.mnm+n

P          % Take first input (numeric vactor) implicitly and reverse it
i          % Take second input (numeric vactor) 
Yd         % Build diagonal matrix with the two vectors
t          % Duplicate
"          % For each column of the matrix
  TF2&YS   %   Circularly shift first row 1 step to the right
  t        %   Duplicate
  p        %   Product of each column
  s        %   Sum all those products
  w        %   Swap top two elements in stack. The shifted matrix is left on top
]          % End for
xx         % Delete matrix and last result. Implicitly display

4

하스켈, 55 49 바이트

(a:b)#c=zipWith(+)(0:b#c)$map(a*)c++[]#b
_#c=0<$c

연산자를 정의합니다 #.


1
패딩 [0,0..](0<$b)필요한 길이를 정확하게 제공하여 빈 기본 사례를 허용 할 수 있다고 생각합니다 _#b=0<$b.
xnor

@xnor 실제로 6 바이트를 절약합니다.
Anders Kaseorg

마지막으로 귀하의 답변을 이해 했으므로 이것이 매우 영리한 것입니다. 나는 감동!
flawr

3

Matlab / 옥타브, 41 바이트

@(p,q)poly([roots(p);roots(q)])*p(1)*q(1)

이것은 익명 함수를 정의합니다. 호출하려면 변수에 지정하거나을 사용하십시오 ans.

여기에서 시도하십시오 .

설명

이것은 사실을 이용합니다

  • (반복 될 수있는) 근은 다항식을 최고 계수까지 특성화합니다.
  • 두 개의 다항식의 곱은 그 근본이 있습니다.

이 코드는 두 다항식의 근 (function roots)을 계산하여 열 배열로 연결합니다. 그것으로부터 선도 1(함수 poly) 를 갖는 곱 다항식의 계수를 얻는다 . 마지막으로 결과에 두 다항식의 선행 계수를 곱합니다.


3

옥타브 , 48 바이트

@(p,q)ifft(fft([p q*0]).*fft([q p*0]))(1:end-1)

여기에서 시도하십시오 .

설명

이산 컨벌루션은 (이산 시간) 푸리에 변환의 곱에 해당합니다. 따라서 다항식을 곱하는 한 가지 방법은 변환하고 변환 된 시퀀스를 곱한 후 다시 변환하는 것입니다.

경우] 푸리에 변환 이산 (DFT)를 푸리에 변환 대신에 사용되며, 그 결과 인 원형 콘볼 루션 다항식 계수들의 원래의 시퀀스. 코드는이 경로를 따릅니다. 원형 컨벌루션을 표준 컨벌루션과 동일하게 만들기 위해 시퀀스가 ​​0으로 채워지고 결과가 잘립니다.


젠장, 난 여전히 영혼을 fft 금지했지만 좋은 일을!
flawr

@flawr 예, 우리가 그것에 대해 이야기했다고 생각합니다 ...? :-P
Luis Mendo 2016 년

2

05AB1E , 18 17 바이트

암호

0Ev²¹g<Å0«y*NFÁ}+

설명

배후 이론 :

회선을 발견하기 위해,이 예제를 보자 [1, 2, 3], [3, 4, 5]. 다음과 같이 첫 번째 배열의 값을 거꾸로 놓고 세로로 배치합니다.

3
2
1

이제 두 번째 배열을 사다리처럼 배치하고 다음을 곱하십시오.

3 ×       [3  4  5]
2 ×    [3  4  5]
1 × [3  4  5]

결과 :

        9   12   15
    6   8   10
3   4   5

그런 다음 추가하여 다음과 같은 결과를 얻습니다.

        9   12   15
    6   8   10
3   4   5       

3   10  22  22   15

따라서 컨볼 루션은 [3, 10, 22, 22, 15]입니다.

코드 자체 :

우리는을 사용하여 단계로이 단계를 어떻게 할 건데 [1, 2, 3], [3, 4, 5]테스트 케이스로.

0Ev²¹g<Å0«y*NFÁ}+

먼저 푸시 0한 다음 E첫 번째 입력 배열을 평가합니다. 를 사용하여 각 요소를 매핑 v합니다.

따라서 각 요소에 대해 두 번째 배열을 ²누른 다음 첫 번째 배열의 길이를 사용하여 ¹g이것을 1만큼 줄입니다 ( <). 이것을 사용 하여 (길이 1 배열-1) 0을 사용하여 0목록으로 변환하고 이것을 목록에 추가합니다. 입력 목록의 첫 번째 항목에 대한 스택은 다음과 같습니다.Å0

[3, 4, 5, 0, 0]

이 배열에 현재 항목을 곱합니다 y*. 그런 다음을 눌러 N현재 항목의 색인을 표시하고 (0으로 색인화 됨)을 사용하여 배열을 오른쪽으로 여러 번 회전시킵니다 FÁ}. 마지막으로이를 초기 값 ( 0)에 추가합니다 . 따라서 기본적으로 수행되는 작업은 다음과 같습니다.

[0, 0, 9, 12, 15] +
[0, 6, 8, 10, 0] +
[3, 4, 5, 0, 0] =

[3, 10, 22, 22, 15]

그런 다음 암시 적으로 인쇄됩니다. CP-1252 인코딩을 사용합니다 . 온라인으로 사용해보십시오! .


2

젤리 , 9 바이트

0;+
×'Ṛç/

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .

작동 원리

×'Ṛç/  Main link. Arguments: p, q (lists)

×'     Spawned multiplication; multiply each item of p with each item of q.
  Ṛ    Reverse the rows of the result.
   ç/  Reduce the rows by the helper link.


0;+    Helper link. Arguments: p, q (lists)

0;     Prepend a 0 to p.
  +    Perform vectorized addition of the result and q.

J‽보다 긴 젤리 정의상 불가능합니다!
Adám

2

껍질 , 5 바이트

mΣ∂Ṫ*

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

참고 : 제로 다항식 / 빈 목록을 제공 할 때 유형 (예 :)을 지정해야합니다 []:LN!

설명

mΣ∂Ṫ*  -- implicit inputs xs ys, for example: [1,-1] [1,1]
   Ṫ*  -- compute the outer product xsᵀ·ys: [[1,1],[-1,-1]]
  ∂    -- diagonals: [[1],[1,-1],[-1]]
mΣ     -- map sum: [1,0,1]

2

Matlab, 33 바이트

@(x,y)sum(spdiags(flip(x').*y),1)

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

입력의 모든 요소 별 곱의 행렬을 만든 다음 대각선을 따라 합산합니다. 그만큼,1단부에 힘이 입력 벡터들 중 하나의 길이가 1을 가질 때 올바른 방향을 따라 합계 MATLAB에.

Octave spdiags에서는 벡터에 대해 작동하지 않으므로 입력 중 하나의 길이가 1 인 경우 오류가 발생합니다. 요소 별 제품의 명시 적 확장을 위해서는 Matlab 2016b 이상이 필요합니다.


좋은 접근 방식 !!
Luis Mendo


1

파이썬, 90 바이트

lambda p,q:[sum((p+k*[0])[i]*(q+k*[0])[k-i]for i in range(k+1))for k in range(len(p+q)-1)]

1

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

(a,b)=>a.map((n,i)=>b.map((m,j)=>r[j+=i]=m*n+(r[j]||0)),r=[])&&r

입력이 비어 있으면 빈 배열을 반환합니다. 다항식 에 대한 나의 대답을 바탕으로 합니다.



1

클로저, 104 바이트

#(vals(apply merge-with +(sorted-map)(for[i(range(count %))j(range(count %2))]{(+ i j)(*(% i)(%2 j))})))

sorted-map값이 올바른 순서로 반환 되도록 보장 하기 위해 병합합니다 . 몇 가지 테스트 사례가 더 있었으면 좋겠다.

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