-- ACM Pacific NW Region Programming Contest, 11 November 2000 -- Problem H, Swampnet Routing -- Sergio Antoy, Tue Dec 4 15:36:09 PST 2001 -- updated: Mon Sep 23 15:22:15 PDT 2002 import Char import Read IPmask (IP n) (IP m) = IP (mask n m) where mask n m = if m == 0 then 0 else let p = 2 * mask (n `div` 2) (m `div` 2) q = if m `mod` 2 == 0 then 0 else n `mod` 2 in p + q data Packet = Packet IP Int IP Int Int data IP = IP Int data Port = Star | Regular Int | Range Int Int data Action = Permit | Deny data Access = Access Port IP IP Port IP IP Port Action dotted ip | ip =:= a++'.':b++'.':c++'.':d = IP ((((readInt a)*256+(readInt b))*256+(readInt c))*256+(readInt b)) where a,b,c,d free readPacket [] = [] readPacket (ip1:int1:ip2:int2:int3:rest) = packet : readPacket rest where srcIP = dotted ip1 srcPort = readInt int1 dstIP = dotted ip2 dstPort = readInt int2 protocol = readInt int3 packet = Packet srcIP srcPort dstIP dstPort protocol port s | s=:="*" = Star | s=:=a++'-':b = Range (readInt a) (readInt b) | digits s = Regular (readInt s) where a,b free digits [x] | isDigit x = success digits (x:xs) | isDigit x = digits xs readAccess [] = [] readAccess (int1:ip1:ip2:int2:ip3:ip4:int3:word:rest) = access : readAccess rest where protocol = port int1 srcIP = dotted ip1 srcMask = dotted ip2 srcPort = port int2 dstIP = dotted ip3 dstMask = dotted ip4 dstPort = port int3 action = if (map toUpper word == "DENY") then Deny else Permit access = Access protocol srcIP srcMask srcPort dstIP dstMask dstPort action process accessString packetString = putStrLn (show x ++ " " ++ show y ++ " " ++ show z) where access = readAccess (words (unlines accessString)) packet = readPacket (words (unlines packetString)) (x,y,z) = allPackets access packet allPackets _ [] = (0,0,0) allPackets a (p:ps) = let (x,y,z) = onePacket a p 0 (u,v,w) = allPackets a ps in (x+u,y+v,z+w) onePacket [] _ n = (n,0,0) onePacket (ac:acs) p n = if match ac p then if isPermit ac then (n+1,1,0) else (n+1,0,1) else onePacket acs p (n+1) isPermit (Access _ _ _ _ _ _ _ x) = x==Permit match (Access proto srcIP srcMask srcPort dstIP dstMask dstPort _) (Packet pSrcIP pSrcPort pDstIP pDstPort pProto) = matchSrcIP && matchDstIP && matchPort proto pProto && matchPort srcPort pSrcPort && matchPort dstPort pDstPort where matchPort Star _ = True matchPort (Regular p) q = p==q matchPort (Range x y) q = x<=q && q<=y matchSrcIP = IPmask pSrcIP srcMask==IPmask srcIP srcMask matchDstIP = IPmask pDstIP dstMask==IPmask dstIP dstMask doAll s = if s == [] then return () -- end of file else if head s == [] then doAll (tail s) -- separator else let (access, "":r1) = span (\x -> x /= "") s (packet, r2) = span (\x -> x /= "") r1 in process access packet >> doAll r2 main = do input <- readFile "h.dat" doSolve (input=:=input) doAll (lines input) -- end program