import Data.Map as Map
import Data.Maybe
import Control.Applicative

data Element = A | B | C | D
    deriving (Eq, Ord, Show)

addElement :: Element -> Map Element Int -> Map Element Int
addElement = alter ((<|> Just 1) . fmap (+1))

getScore :: Element -> Map Element Int -> Float
getScore e m = fromMaybe 1.0 $ ((1.0/) . fromIntegral) <$> Map.lookup e m

data BinaryTree a = Empty | Node a (BinaryTree a) (BinaryTree a) deriving Show
type ElementTree = BinaryTree Element
type ScoredElementTree = BinaryTree (Element, Float)

assignScores :: ElementTree -> Map Element Int -> (Map Element Int, ScoredElementTree)
assignScores Empty m = (Map.empty, Empty)
assignScores (Node e t1 t2) m = (m', Node (e, getScore e m) t1' t2')
    where
        (m1, t1') = assignScores t1 m
        (m2, t2') = assignScores t2 m
        m' = addElement e $ unionWith (+) m1 m2

doAssignScores :: ElementTree -> ScoredElementTree
doAssignScores t = t'
    where (m, t') = assignScores t m
