[Haskell-cafe] xkcd #287 "NP-Complete"

Albert Y. C. Lai trebla at vex.net
Mon Jul 9 18:25:48 EDT 2007


http://xkcd.com/c287.html

import Data.Array
import Control.Monad

-- exactly n v
-- items in v that sum to exactly n
-- returns list of solutions, each solution list of items
exactly :: (Real a) => a -> Array Int a -> [[a]]
exactly 0 v = return []
exactly n v = do
   i <- indices v
   guard (v!i <= n)
   liftM (v!i :) (exactly (n - v!i) (v `without` i))
-- for solutions that use items multiple times,
-- change (v `without` i) to v

-- v `without` i
-- new array like v except one shorter with v!i missing
without :: Array Int a -> Int -> Array Int a
without v i = ixmap (lo, hi-1) f v
     where (lo, hi) = bounds v
           f j | j >= i = j+1
               | otherwise = j

play = exactly 1505 menu
menu = listArray (1,6) [215, 275, 335, 355, 420, 580]

test = exactly 10 (listArray (1,5) [1,1,2,3,4])

It disappoints me that there is no solution if each item is used at most 
once. However, do change the code to allow multiple uses, then there are 
many solutions.


More information about the Haskell-Cafe mailing list