Update: with an unexpected application to Project Euler #109!
import Control.Applicative (liftA2)
import Data.List (sort, nub, sortBy, maximum)
import Data.Ord (comparing)
import System.Environment (getArgs)
data Dart n = Single n | Double n | Triple n | Bull | None deriving Show
main = mapM_ print . out . read . head =<< getArgs
out n = check . sort' . map (map dart) $ sortBy (comparing maximum) sums
where
check ns = if null ns then [None] else head ns
sort' = sortBy (comparing $ sum . map ease)
sums = nub $ filter ((== n) . sum) combos
---------------------------------------------------------------------------
combos = concat $ zipWith combosOf [1..3] $ repeat segments
segments = concat $ replicate 3 $ sort $ 50 : liftA2 (*) [1..3] [1..20]
dart n
| n == 50 = Bull
| n `elem` s = Single n
| n `elem` d = Double (n `div` 2)
| n `elem` t = Triple (n `div` 3)
where
[s,d,t] = liftA2 (map . (*)) [1..3] [[1..20]]
ease (Single _) = 1
ease (Bull) = 2
ease (Double _) = 3
ease (Triple _) = 4
combosOf 0 _ = [[]]
combosOf _ [] = []
combosOf k (x:xs) = map (x:) (combosOf (k-1) xs) ++ combosOf k xs