List Convolution and Multiplying Polynomials
We can use List.map and consecutives to implement a process called
list convolution, which can be used to implement polynomial
multiplication.1
let list_conv
(f : 'a list -> 'b list -> 'c)
(l : 'a list)
(r : 'b list) : 'c list =
List.map (f l) (consecutives (List.length l) r)
In essence, the list l is "lined up" with r in all possible ways,
and f is applied to l and the sublist of r it is lined up with.
For example, list_conv f [1;2] [3;4;5;6] is equivalent to [f [1;2]
[3;4] ; f [1;2] [4;5] ; f [1;2] [5;6]].
A polynomial is represented as an int list where the i-th
element is the coefficient of \(x^i\). For example, \(p(x) = 1 + 2x +
5x^2 + 4x^4\) is represented by [1;2;5;0;4].
The function for multiplying polynomials is filled in below for you using list convolution.2
let poly_mult (p : int list) (q : int list) : int list =
let padding = List.init (List.length p - 1) (fun _ -> 0) in
let padded_q = padding @ q @ padding in
list_conv poly_mult_helper p padded_q
Your task is to implement the function
val poly_mult_helper : int list -> int list -> int
to determine what function to convolve with.
Examples
let _ = assert (poly_mult [1;2;3] [4;5] = [4;13;22;15])
let _ = assert (poly_mult [4;5] [1;2;3] = [4;13;22;15])
(* ( 1 + 2x + 3x^2 ) ( 4 + 5x ) = 4 + 13x + 22x^2 + 15x^3 *)
Footnotes:
Challenge worth nothing: If you know what list convolution is, try first to implement it yourself (it's okay if you already peaked at the solution, it's still a good exercise).
Challenge worth nothing: Same as before, try to implement polynomial multiplication from scratch using list convolution.