icfp13/CircuitParser.hs

82 lines
2.2 KiB
Haskell
Raw Normal View History

2010-06-23 10:50:41 +00:00
module CircuitParser (parseCircuit, showCircuit) where
import Text.ParserCombinators.ReadP
import Data.List
import CircuitBase
-- instance Show Circuit where
-- show = showCircuit
showCircuit (Circuit op inpins) = (formatPin ip) ++ ":" ++ (joinWith "," (nodes inpins outpins)) ++ ":" ++ (formatPin op) where
nodes :: [Int] -> [Int] -> [String]
nodes [] [] = []
nodes (a:b:i) (c:d:o) = ((formatPin a) ++ (formatPin b) ++ "0#" ++ (formatPin c) ++ (formatPin d)):nodes i o
joinWith sep [] = []
joinWith sep (x:xs) = (x ++) $ concat $ map (sep ++) xs
-- build reverse pin mapping
(ip:outpins) = map snd $ sort $ zip (op:inpins) [-1..]
formatPin p = if (-1 == p) then "X" else (show (p `div` 2)) ++ (if even p then "L" else "R")
-- Circuit Syntax:
-- <inPin>:[<gates>]:<outPin>
-- each Pin is either "X" (circuit IN or OUT)
-- or <gate-number> + ("L" | "R")
-- gates are numbered from 0
-- one gate is <inPinLeft><inPinRight>0#<outPinLeft><outPinRight>
-- obviously you specify the connector of the other side
-- (0 is probably the gate "function")
-- this contains redundancy ofc, it would be enough to specify only the in pins of the gates and the circuit OUT
-- (internal representation)
readPlace :: ReadP Int
readPlace = (char 'L' >> return 0) <++ (char 'R' >> return 1)
readInt :: ReadP Int
readInt = readS_to_P reads
readPin :: ReadP Int
readPin = (char 'X' >> return (-1)) <++ do
i <- readInt
p <- readPlace
return $ (2*i) + p
readNode :: ReadP [Int]
readNode = do
a <- readPin
b <- readPin
char '0'
char '#'
readPin
readPin
return [a,b]
readNodes1 :: ReadP [Int]
readNodes1 = (do
char ','
x <- readNode
xl <- readNodes1
return $ x ++ xl
) <++ (return [])
readNodes :: ReadP [Int]
readNodes = (do
x <- readNode
xl <- readNodes1
return $ x ++ xl
) <++ (return [])
readCircuit :: ReadP Circuit
readCircuit = do
readPin
char ':'
nodes <- readNodes
char ':'
outPin <- readPin
return $ Circuit outPin nodes
doparse p s = fst $ head $ readP_to_S p s
parseCircuit s = doparse readCircuit s