2021-05-19 20:15:40 +00:00
|
|
|
module Main where
|
|
|
|
|
2021-05-23 22:03:17 +00:00
|
|
|
-- TODO:
|
|
|
|
-- arithmetic
|
|
|
|
-- I/O
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
import Data.List
|
2021-05-25 13:00:17 +00:00
|
|
|
import System.Environment
|
|
|
|
import System.Exit
|
|
|
|
|
2021-05-23 22:03:17 +00:00
|
|
|
import Element
|
2021-05-25 13:00:17 +00:00
|
|
|
import Types
|
|
|
|
import Dirty
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
2021-05-25 13:00:17 +00:00
|
|
|
args <- getArgs
|
|
|
|
if length args < 1
|
|
|
|
then die "No filename provided."
|
|
|
|
else run $ args !! 0
|
|
|
|
|
|
|
|
run :: String -> IO ()
|
|
|
|
run inputFile = do
|
|
|
|
input <- readFile inputFile
|
2021-05-19 20:15:40 +00:00
|
|
|
let internalFactory = stringsToFactory $ lines input
|
2021-05-23 22:03:17 +00:00
|
|
|
interpretLoop internalFactory [ Element
|
|
|
|
0
|
2021-05-25 13:00:17 +00:00
|
|
|
(fst $ entryPointLocation internalFactory)
|
2021-05-23 22:03:17 +00:00
|
|
|
(snd $ entryPointLocation internalFactory)]
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
interpretLoop :: Factory -> [Element] -> IO ()
|
|
|
|
interpretLoop f es = do
|
|
|
|
let elements = stepInterpret f es
|
2021-05-23 22:03:17 +00:00
|
|
|
printFactory f elements
|
2021-05-19 20:15:40 +00:00
|
|
|
a <- getChar
|
2021-05-25 13:00:17 +00:00
|
|
|
case a of
|
|
|
|
'q' -> return ()
|
|
|
|
_ -> interpretLoop f elements
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
stringsToFactory :: [[Char]] -> [[Tile]]
|
2021-05-23 22:03:17 +00:00
|
|
|
stringsToFactory [] = []
|
|
|
|
stringsToFactory s = map (map charToTile) s
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
tupAdd :: (Num a, Num b) => (a, b) -> (a, b) -> (a, b)
|
|
|
|
tupAdd (a, b) (c, d) = (a + c, b + d)
|
|
|
|
|
|
|
|
entryPointLocation :: Factory -> (Int, Int)
|
|
|
|
entryPointLocation [] = error "Couldn't find an entrypoint (E)."
|
|
|
|
entryPointLocation (l:ls) = case index of
|
|
|
|
Nothing -> tupAdd (0, 1) (entryPointLocation ls)
|
|
|
|
Just x -> (x, 0)
|
|
|
|
where index = elemIndex Entrypoint l
|
|
|
|
|
|
|
|
oobCheck :: Factory -> Element -> Bool
|
|
|
|
oobCheck f e = yPos e >= length f
|
|
|
|
|| xPos e >= length (f !! yPos e)
|
|
|
|
|
2021-05-28 10:06:03 +00:00
|
|
|
singleton :: a -> [a]
|
|
|
|
singleton a = [a]
|
|
|
|
|
2021-05-19 20:15:40 +00:00
|
|
|
-- custom hashmap thingy, but uses lists so it's slow on large things (luckily this is small)
|
2021-05-28 10:06:03 +00:00
|
|
|
tileActionMap :: Tile -> [(Tile, Element -> [Element])] -> (Element -> [Element])
|
|
|
|
tileActionMap _ [] = singleton
|
2021-05-19 20:15:40 +00:00
|
|
|
tileActionMap tile (pair:rest)
|
|
|
|
| tile == fst pair = snd pair
|
|
|
|
| otherwise = tileActionMap tile rest
|
|
|
|
|
2021-05-23 22:03:17 +00:00
|
|
|
-- TODO: make this safe, aka boundary check
|
2021-05-28 10:06:03 +00:00
|
|
|
spitOut :: Direction -> Factory -> Element -> Element
|
|
|
|
spitOut dir f elem = case dir of
|
|
|
|
East -> spitOutEast f elem
|
|
|
|
South -> spitOutSouth f elem
|
|
|
|
West -> spitOutWest f elem
|
|
|
|
North -> spitOutNorth f elem
|
|
|
|
|
|
|
|
-- AAAAAAAA
|
|
|
|
spitOutEast :: Factory -> Element -> Element
|
|
|
|
spitOutEast f elem
|
2021-05-23 22:03:17 +00:00
|
|
|
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
|
|
|
|
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
|
|
|
|
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
|
|
|
|
|
2021-05-28 10:06:03 +00:00
|
|
|
spitOutSouth :: Factory -> Element -> Element
|
|
|
|
spitOutSouth f elem
|
|
|
|
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
|
|
|
|
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
|
|
|
|
|
|
|
|
spitOutWest :: Factory -> Element -> Element
|
|
|
|
spitOutWest f elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
|
|
|
|
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
|
|
|
|
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
|
|
|
|
|
|
|
|
spitOutNorth :: Factory -> Element -> Element
|
|
|
|
spitOutNorth f elem
|
|
|
|
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem + 1) == Track East = incXPos elem
|
|
|
|
| (f !! (yPos elem + 1)) !! xPos elem == Track South = incYPos elem
|
|
|
|
| (f !! yPos elem) !! (xPos elem - 1) == Track West = decXPos elem
|
|
|
|
|
|
|
|
duplicate :: Element -> [Element]
|
|
|
|
duplicate e = [e, e]
|
|
|
|
|
|
|
|
update :: Factory -> Element -> [Element]
|
2021-05-19 20:15:40 +00:00
|
|
|
update f e = if oobCheck f e then error "Element out of bounds check failed!"
|
2021-05-23 22:03:17 +00:00
|
|
|
else tileActionMap t tileActions e
|
2021-05-19 20:15:40 +00:00
|
|
|
where t = (f !! yPos e) !! xPos e
|
2021-05-28 10:06:03 +00:00
|
|
|
tileActions = [ (Track East, singleton . incXPos)
|
|
|
|
, (Track West, singleton . decXPos)
|
|
|
|
, (Track South, singleton . incYPos)
|
|
|
|
, (Track North, singleton . decYPos)
|
|
|
|
, (Modifier Increment, singleton . incVal . spitOut East f)
|
|
|
|
, (Modifier Decrement, singleton . decVal . spitOut East f)
|
|
|
|
, (Special Duplicate, dupFunc)
|
|
|
|
, (Entrypoint, singleton . spitOut East f)
|
2021-05-19 20:15:40 +00:00
|
|
|
]
|
2021-05-28 10:06:03 +00:00
|
|
|
dupFunc :: Element -> [Element]
|
|
|
|
dupFunc elem = [ spitOut East f elem
|
|
|
|
, spitOut South f elem
|
|
|
|
]
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
stepInterpret :: Factory -> [Element] -> [Element]
|
2021-05-28 10:06:03 +00:00
|
|
|
stepInterpret f = concat . map (update f)
|