+part2 network modules = foldl' lcm 1 cycleLengths
+ where (_, lxPulses) =
+ (!! 10000) $ iterate (pressAndEvaluate network part2Extractor) (state0, [(0, [])])
+ state0 = NetworkState modules Q.empty
+ lxHighs = filter (not . null . snd) lxPulses
+ cycleLengths = fmap (fst . head) $
+ fmap sort $
+ groupBy ((==) `on` (_source . snd)) $
+ sortBy (compare `on` (\(_, p) -> p ^. source)) $
+ fmap ((\(n, ps) -> (n, head ps))) lxHighs
+
+pressAndEvaluate :: Network -> (a -> [Pulse] -> a) -> (NetworkState, a) -> (NetworkState, a)
+pressAndEvaluate network resultExtractor (state0, result0) = (state1, result1)
+ where (state1, pulses) = buttonPress network state0
+ result1 = resultExtractor result0 pulses
+
+part1Extractor :: (Int, Int) -> [Pulse] -> (Int, Int)
+part1Extractor (highs, lows) pulses = (highs + length hs, lows + length ls)
+ where (hs, ls) = partition ((== High) . _level) pulses
+