never executed always true always false
    1 {-# LANGUAGE RankNTypes #-}
    2 {-|
    3 Module:      Y2018.D02
    4 Description: Advent of Code Day 01 Solutions.
    5 License:     MIT
    6 Maintainer:  @tylerjl
    7 
    8 Solutions to the day 02 set of problems for <adventofcode.com>.
    9 -}
   10 module Y2018.D02
   11   ( boxID
   12   , checksum
   13   ) where
   14 
   15 import Data.List (group, sort)
   16 
   17 boxID :: String -> Maybe String
   18 boxID = findBox . lines
   19 -- boxID = findBox . filter (\s -> has 2 s || has 3 s) . lines
   20 
   21 findBox :: forall b. Eq b => [[b]] -> Maybe [b]
   22 findBox (box:boxes) = case matchingBoxes box boxes of
   23                         [] -> findBox boxes
   24                         (match:_) -> Just $ fst $ unzip match
   25 findBox [] = Nothing
   26 
   27 matchingBoxes :: forall a. Eq a => [a] -> [[a]] -> [[(a, a)]]
   28 matchingBoxes box boxes = map (filter pair) $ filter ((==) 1 . length . unmatched) $ map (zip box) boxes
   29   where unmatched = filter (not . pair)
   30         pair (a, b) = a == b
   31 
   32 checksum :: String -> Int
   33 checksum boxes = product $ map length [(doubles boxes'), (triples boxes')]
   34   where boxes' = lines boxes
   35 
   36 doubles :: [String] -> [String]
   37 doubles = filter (has 2)
   38 
   39 triples :: [String] -> [String]
   40 triples = filter (has 3)
   41 
   42 has :: Ord a => Int -> [a] -> Bool
   43 has n = any ((==) n . length) . group . sort