Ir al contenido principal

Mínimo producto escalar

El producto escalar de los vectores [a1,a2,...,an] y [b1,b2,..., bn] es

a1·b1 + a2·b2 + ··· + an·bn.

Definir la función

menorProductoEscalar :: (Ord a, Num a) => [a] -> [a] -> a

tal que (menorProductoEscalar xs ys) es el mínimo de los productos escalares de las permutaciones de xs y de las permutaciones de ys. Por ejemplo,

menorProductoEscalar [3,2,5]  [1,4,6]         == 29
menorProductoEscalar [3,2,5]  [1,4,-6]        == -19
menorProductoEscalar [0..9]   [0..9]          == 120
menorProductoEscalar [0..99]  [0..99]         == 161700
menorProductoEscalar [0..999] [0..999]        == 166167000
menorProductoEscalar3 [0..9999] [0..9999]     == 166616670000
menorProductoEscalar3 [0..99999] [0..99999]   == 166661666700000
menorProductoEscalar3 [0..999999] [0..999999] == 166666166667000000

Soluciones

import Data.List (sort, permutations)
import Test.QuickCheck

-- 1ª solución
menorProductoEscalar :: (Ord a, Num a) => [a] -> [a] -> a
menorProductoEscalar xs ys =
  minimum [sum (zipWith (*) pxs pys) | pxs <- permutations xs,
                                       pys <- permutations ys]

-- 2ª solución
menorProductoEscalar2 :: (Ord a, Num a) => [a] -> [a] -> a
menorProductoEscalar2 xs ys =
  minimum [sum (zipWith (*) pxs ys) | pxs <- permutations xs]

-- 3ª solución
menorProductoEscalar3 :: (Ord a, Num a) => [a] -> [a] -> a
menorProductoEscalar3 xs ys =
  sum (zipWith (*) (sort xs) (reverse (sort ys)))

-- Equivalencia
-- ============

-- La propiedad es
prop_menorProductoEscalar :: [Integer] -> [Integer] -> Bool
prop_menorProductoEscalar xs ys =
  menorProductoEscalar3 xs' ys' == menorProductoEscalar  xs' ys' &&
  menorProductoEscalar3 xs' ys' == menorProductoEscalar2 xs' ys'
  where n   = min (length xs) (length ys)
        xs' = take n xs
        ys' = take n ys

-- La comprobación es
--    λ> quickCheckWith (stdArgs {maxSize=7}) prop_menorProductoEscalar
--    +++ OK, passed 100 tests.

-- Comparación de eficiencia
-- =========================

-- La comparación es
--    λ> menorProductoEscalar1 [0..5] [0..5]
--    20
--    (3.24 secs, 977385528 bytes)
--    λ> menorProductoEscalar2 [0..5] [0..5]
--    20
--    (0.01 secs, 4185776 bytes)
--
--    λ> menorProductoEscalar2 [0..9] [0..9]
--    120
--    (23.86 secs, 9342872784 bytes)
--    λ> menorProductoEscalar3 [0..9] [0..9]
--    120
--    (0.01 secs, 2580824 bytes)
--
--    λ> menorProductoEscalar3 [0..10^6] [0..10^6]
--    166666666666500000
--    (2.46 secs, 473,338,912 bytes)