selectTarget :: Int -> [Int] -> [([Int], [Int])]
selectTarget target xs = go target xs []
  where
    go target _  _ | target < 0 = []
    go 0      xs rest           = [([], xs ++ rest)]
    go _      [] _              = []
    go target l@(x:xs) rest =
        let takeNone = go target xs (x : rest)
            takeOne  = map (first ((:) x)) (go (target - x) xs rest)
        in  takeNone ++ takeOne

-- Fun with StateT to compute all possible partitions
-- firstGroups' xs = flip evalStateT xs $ do
--   let target = sum xs `quot` 4
--   g1 <- StateT (selectTarget target)
--   g2 <- StateT (selectTarget target)
--   guard . not $ null g2
--   g3 <- StateT (selectTarget target)
--   guard . not $ null g3
--   return g1
selectTarget :: Int -> [Int] -> [([Int], [Int])]
selectTarget target xs = go target xs []
  where
    go target _  _ | target < 0 = []
    go 0      xs rest           = [([], xs ++ rest)]
    go _      [] _              = []
    go target l@(x:xs) rest =
        let takeNone = go target xs (x : rest)
            takeOne  = map (first ((:) x)) (go (target - x) xs rest)
        in  takeNone ++ takeOne

-- Fun with StateT to compute all possible partitions
-- firstGroups' xs = flip evalStateT xs $ do
--   let target = sum xs `quot` 4
--   g1 <- StateT (selectTarget target)
--   g2 <- StateT (selectTarget target)
--   guard . not $ null g2
--   g3 <- StateT (selectTarget target)
--   guard . not $ null g3
--   return g1
selectTarget target xs = go target xs []
  where
    go target _  _ | target < 0 = []
    go 0      xs rest           = [([], xs ++ rest)]
    go _      [] _              = []
    go target l@(x:xs) rest =
        let takeNone = go target xs (x : rest)
            takeOne  = map (first ((:) x)) (go (target - x) xs rest)
        in  takeNone ++ takeOne

-- Fun with StateT to compute all possible partitions
-- firstGroups' xs = flip evalStateT xs $ do
--   let target = sum xs `quot` 4
--   g1 <- StateT (selectTarget target)
--   g2 <- StateT (selectTarget target)
--   guard . not $ null g2
--   g3 <- StateT (selectTarget target)
--   guard . not $ null g3
--   return g1