5 import qualified Data.Text.IO as TIO
7 import qualified Data.Map.Strict as M
8 import Data.Map.Strict ((!))
10 -- import Data.Function (on)
12 import Control.Monad.RWS.Strict
15 data EncapsulatedMacine = EncapsulatedMacine
17 , _executionState :: ExecutionState
18 , _currentInput :: [Integer]
19 , _machineOutput :: [Integer]
21 makeLenses ''EncapsulatedMacine
23 type Network = M.Map Integer EncapsulatedMacine
26 { _destination :: Integer
35 text <- TIO.readFile "data/advent23.txt"
36 let mem = parseMachineMemory text
41 part1 mem = runNetworkUntil255 net
42 where net = buildNetwork mem
44 runNetworkUntil255 :: Network -> Packet
45 runNetworkUntil255 net0
46 | not $ null goalPackets = head packets
47 | otherwise = runNetworkUntil255 net3
48 where net1 = runNetworkStep net0
49 (net2, packets) = extractPackets net1
50 net3 = enqueuePackets net2 packets
51 goalPackets = filter (packet255) packets
54 packet255 :: Packet -> Bool
55 packet255 packet = (packet ^. destination) == 255
58 buildNetwork :: [Integer] -> Network
59 buildNetwork mem = M.fromList $ map (\i -> (i, encapsulate mem i)) [0..49]
62 encapsulate :: [Integer] -> Integer -> EncapsulatedMacine
63 encapsulate mem input = EncapsulatedMacine
64 { _machine = makeMachine mem
65 , _executionState = Runnable
67 , _currentInput = [input]
73 -- pipelineTrace :: Pipeline -> String
74 -- pipelineTrace pipeline = show $ M.toList $ M.map emTrace pipeline
76 -- emTrace e = intercalate " ; " terms
77 -- where terms = [ show $ _executionState e
79 -- , show $ _currentInput e
81 -- , show $ _machineOutput e
84 runNetworkStep :: Network -> Network
85 runNetworkStep net = M.map runEncapsulatedMachine net
87 extractPackets :: Network -> (Network, [Packet])
88 extractPackets net = (net', packets)
89 where packets = concat $ M.elems $ M.map extractPacket net
90 net' = M.map stripPacket net
92 extractPacket :: EncapsulatedMacine -> [Packet]
93 extractPacket e = if length output >= 3
94 then [Packet { _destination = fromIntegral $ output!!0
95 , _packetX = output!!1
96 , _packetY = output!!2} ]
98 where output = (e ^. machineOutput)
100 stripPacket :: EncapsulatedMacine -> EncapsulatedMacine
101 stripPacket e = if length (e ^. machineOutput) >= 3
102 then e & machineOutput %~ (drop 3)
105 enqueuePackets :: Network -> [Packet] -> Network
106 enqueuePackets net packets = foldl' enqueuePacket net packets
108 enqueuePacket :: Network -> Packet -> Network
109 enqueuePacket net packet
110 | d `M.member` net = M.insert d e' net
112 where d = packet ^. destination
114 e' = e & currentInput %~ (++ [packet ^. packetX, packet ^. packetY])
117 runEncapsulatedMachine :: EncapsulatedMacine -> EncapsulatedMacine
118 runEncapsulatedMachine e = e & machine .~ m''
119 & executionState .~ halted'
120 & currentInput .~ input'
121 & machineOutput %~ ( ++ output' )
122 where (halted, m', output) = runRWS runNetworkMachineStep (e ^. currentInput) (e ^. machine)
123 input' = if halted == Blocked
124 then (e ^. currentInput) ++ [-1]
125 else e ^. currentInput
126 (halted', m'', output') = if halted == Blocked
127 then runRWS runNetworkMachineStep input' (e ^. machine)
128 else (halted, m', output)
131 runNetworkMachineStep :: ProgrammedMachine ExecutionState
132 runNetworkMachineStep = do
136 iIndex <- gets _inputIndex
137 let acutalInputLength = length input
138 let requiredInputLength = iIndex + 1
140 then return Terminated
141 else if (mem!ip == 3 && requiredInputLength > acutalInputLength)