Reputation: 85
I have 2 lists, x and y, I must calculate the product of
(xi^2 - yi^2 + 2*xi*yi)
with xi
from x
and yi
from y
List x = [2,4,5,6,8] xi = 2/3/...
List y = [7,3,4,59,0] yi = 7/3/4...
It's a bit tricky because I can use only functions without the product
function without recursion and list comprehension.
prod :: [Int] -> [Int] -> Int
I would write the product function myself:
product :: [Integer] -> Integer
product [] = 1
product i f = foldl (*) 1 [i..f]
But I don't know how to apply it to the both strings.
Upvotes: 1
Views: 1137
Reputation: 425
Allow me to reuse the excelent answer of @WillemVanOnsem in a more step-by-step aproach:
First, you must join the two list somehow. zip :: [a] -> [b] -> [(a,b)] is a handy function for doing this, from two list it returns a list of pairs.
zip [2,4,5,6,8] [7,3,4,59,0]
> [(2,7),(4,3),(5,4),(6,59),(8,0)]
Now, you must do your work with the pairs. Lets define de function you must apply to a pair:
squareB :: (Integer,Integer) -> Integer
squareB (x,y) = x^2 - y^2 + 2*x*y
Lets use map for aplying the square of a binomial function to each pair:
multiplicands:: [Integer] -> [Integer] -> [Integer]
multiplicands xs1 xs2 = map squareB (zip xs1 xs2)
For example:
multiplicands [2,4,5,6,8] [7,3,4,59,0]
>[-17,31,49,-2737,64]
Now, lets fold them from the left using (*) with base case 1, ie: (((1 * x1) * x2) .... xn):
solution :: [Integer] -> [Integer] -> Integer
solution xs1 xs2 = foldl (*) 1 (multiplicands xs1 xs2)
Lets check this function:
solution [2,4,5,6,8] [7,3,4,59,0]
> 452336326
with Willems' function:
twoListProduct [2,4,5,6,8] [7,3,4,59,0]
> 4523363264
Upvotes: 1
Reputation: 26161
You may also do as follows;
quadratics :: Num a => Int -> [a] -> [a] -> a
quadratics i ns ms = ((\(f,s) -> f*f + 2*f*s - s*s) . head . drop i . zip ns) ms
*Main> quadratics 0 [2,4,5,6,8] [7,3,4,59,0]
-17
*Main> quadratics 3 [2,4,5,6,8] [7,3,4,59,0]
-2737
Upvotes: 0
Reputation: 476547
Well you can define a product yourself with foldl :: (b -> a -> b) -> b -> [a] -> [b]
like:
ownProduct :: Num b => [b] -> b
ownProduct = foldl (*) 1
Because a foldl
starts with the initial value (1
) and applies that value to the first element of the list. The result of that operation is applied to the function again but now with the second element of that list and so on until we reach the end. So foldl (*) 1 [x1,x2,...,xn]
is equal to (((1*x1)*x2)*...)*xn
.
Furthermore you can use a zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
function to convert two streams (one of a
s and one of b
s) into a stream of c
by applying the function element-wise.
So you can implement it like:
twoListProduct :: Num b => [b] -> [b] -> b
twoListProduct x y = foldl (*) 1 $ zipWith helper x y
where helper xi yi = xi*xi - yi*yi + 2*xi*yi
Upvotes: 2