never executed always true always false
    1 {-|
    2 Module:      Y2015.D23
    3 Description: Advent of Code Day 23 Solutions.
    4 License:     MIT
    5 Maintainer:  @tylerjl
    6 
    7 Solutions to the day 23 set of problems for <adventofcode.com>.
    8 -}
    9 
   10 module Y2015.D23 (exInstructions, exInstructions2) where
   11 
   12 import           Data.Map.Strict (Map)
   13 import qualified Data.Map.Strict as M
   14 
   15 type Registers   = Map Register Int
   16 type Register    = Char
   17 data Instruction = Half      Register
   18                  | Triple    Register
   19                  | Increment Register
   20                  | Jump      Int
   21                  | JIE       Register Int
   22                  | JIO       Register Int
   23                  deriving (Show)
   24 
   25 -- |Solver for part a set of instructions.
   26 exInstructions :: String    -- ^ Raw instruction/register input string.
   27                -> Registers -- ^ Resulting set of register values.
   28 exInstructions = runInsts 0 M.empty . toInstructions
   29 
   30 -- |Solver for part b set of instructions.
   31 exInstructions2 :: String    -- ^ Raw instruction/register input string.
   32                 -> Registers -- ^ Resulting set of register values.
   33 exInstructions2 = runInsts 0 (M.singleton 'a' 1) . toInstructions
   34 
   35 runInsts :: Int -> Registers -> [Instruction] -> Registers
   36 runInsts eip rs is | eip < 0 || eip >= length is = rs
   37                    | otherwise = case is !! eip of
   38   (Half r)      -> runInsts (eip+1) (M.adjust (`div` 2) r   rs) is
   39   (Triple r)    -> runInsts (eip+1) (M.adjust (*3)      r   rs) is
   40   (Increment r) -> runInsts (eip+1) (M.insertWith (+)   r 1 rs) is
   41   (Jump j)      -> runInsts (eip+j) rs is
   42   (JIE r i)     -> runInsts (eip+jumpTest i even   r) rs is
   43   (JIO r i)     -> runInsts (eip+jumpTest i (== 1) r) rs is
   44   where jumpTest offset f reg = if f $ M.findWithDefault 0 reg rs
   45                                 then offset
   46                                 else 1
   47 
   48 toInstructions :: String -> [Instruction]
   49 toInstructions = map (toOperation . words) . lines
   50 
   51 toOperation :: [String] -> Instruction
   52 toOperation ["hlf",[r]]          = Half r
   53 toOperation ["tpl",[r]]          = Triple r
   54 toOperation ["inc",[r]]          = Increment r
   55 toOperation ["jmp",offset]       = Jump  $ toInt offset
   56 toOperation ["jie",r:",",offset] = JIE r $ toInt offset
   57 toOperation ["jio",r:",",offset] = JIO r $ toInt offset
   58 toOperation _ = Jump 0
   59 
   60 toInt :: String -> Int
   61 toInt ('-':s) = negate $ read s
   62 toInt ('+':s) = read s
   63 toInt s = read s