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-23 22:03:17 +00:00
|
|
|
import Element
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
|
|
|
input <- readFile "test.fac"
|
|
|
|
let internalFactory = stringsToFactory $ lines input
|
2021-05-23 22:03:17 +00:00
|
|
|
interpretLoop internalFactory [ Element
|
|
|
|
0
|
|
|
|
(1 + fst (entryPointLocation internalFactory))
|
|
|
|
(snd $ entryPointLocation internalFactory)]
|
|
|
|
-- , Element
|
|
|
|
-- 1
|
|
|
|
-- (2 + (fst $ entryPointLocation internalFactory))
|
|
|
|
-- (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-23 22:03:17 +00:00
|
|
|
if a == 'q' then return () else interpretLoop f elements
|
|
|
|
|
|
|
|
|
|
|
|
-- printing factory state with elements overlayed
|
|
|
|
replaceNth :: Int -> a -> [a] -> [a]
|
|
|
|
replaceNth _ _ [] = []
|
|
|
|
replaceNth 0 a (first:rest) = a : rest
|
|
|
|
replaceNth n a (first:rest) = first : replaceNth (n-1) a rest
|
|
|
|
|
|
|
|
changeLine :: Element -> (Int, [Char]) -> (Int, [Char])
|
|
|
|
changeLine e (index, line)
|
|
|
|
| yPos e == index = (index, replaceNth (xPos e) (head $ show $ value e) line)
|
|
|
|
| otherwise = (index, line)
|
|
|
|
|
|
|
|
changeTiles :: Element -> [(Int, [Char])] -> [(Int, [Char])]
|
|
|
|
changeTiles e [] = []
|
|
|
|
changeTiles e cs = map (changeLine e) cs
|
2021-05-19 20:15:40 +00:00
|
|
|
|
2021-05-23 22:03:17 +00:00
|
|
|
putElements :: [Element] -> [(Int, [Char])] -> [(Int, [Char])]
|
|
|
|
putElements [e] cs = changeTiles e cs
|
|
|
|
putElements (e:es) cs = changeTiles e (putElements es cs)
|
2021-05-19 20:15:40 +00:00
|
|
|
|
2021-05-23 22:03:17 +00:00
|
|
|
indexFactory :: Factory -> [(Int, [Tile])]
|
|
|
|
indexFactory tiles = indexed
|
|
|
|
where indexed = zip [0..] tiles
|
|
|
|
|
|
|
|
indexCharFactory :: Factory -> [(Int, [Char])]
|
|
|
|
indexCharFactory f = zip [0..] charFactory
|
|
|
|
where charFactory = showFactory f
|
|
|
|
|
|
|
|
showFactory :: Factory -> [[Char]]
|
|
|
|
showFactory [] = []
|
|
|
|
showFactory f = map (map (head . show)) f
|
|
|
|
|
|
|
|
printFactory :: Factory -> [Element] -> IO ()
|
|
|
|
printFactory f es = mapM_ (print . snd) lines
|
|
|
|
where lines = putElements es $ indexCharFactory f
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
type Entrypoint = Char
|
|
|
|
|
|
|
|
data Direction = North | South | East | West
|
|
|
|
deriving (Eq, Ord)
|
|
|
|
|
2021-05-23 22:03:17 +00:00
|
|
|
data ModifierKind = Increment | Decrement
|
|
|
|
deriving (Eq)
|
2021-05-19 20:15:40 +00:00
|
|
|
|
|
|
|
data Tile = Entrypoint
|
|
|
|
| Track Direction
|
2021-05-23 22:03:17 +00:00
|
|
|
| Modifier ModifierKind
|
|
|
|
| Machine Char -- user defined machines
|
2021-05-19 20:15:40 +00:00
|
|
|
| Ignored
|
|
|
|
deriving (Eq)
|
|
|
|
|
|
|
|
instance Show Tile where
|
|
|
|
show t = [tileToChar t]
|
|
|
|
|
|
|
|
type Factory = [[Tile]]
|
|
|
|
|
|
|
|
charToTile :: Char -> Tile
|
|
|
|
charToTile c = case c of
|
|
|
|
'E' -> Entrypoint
|
|
|
|
'>' -> Track East
|
|
|
|
'<' -> Track West
|
|
|
|
'v' -> Track South
|
|
|
|
'^' -> Track North
|
2021-05-23 22:03:17 +00:00
|
|
|
'+' -> Modifier Increment
|
|
|
|
'-' -> Modifier Decrement
|
2021-05-19 20:15:40 +00:00
|
|
|
_ -> Ignored
|
|
|
|
|
|
|
|
tileToChar :: Tile -> Char
|
|
|
|
tileToChar t = case t of
|
2021-05-23 22:03:17 +00:00
|
|
|
Entrypoint -> 'E'
|
|
|
|
Track East -> '>'
|
|
|
|
Track West -> '<'
|
|
|
|
Track South -> 'v'
|
|
|
|
Track North -> '^'
|
|
|
|
Modifier Increment -> '+'
|
|
|
|
Modifier Decrement -> '-'
|
|
|
|
_ -> ' '
|
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)
|
|
|
|
|
|
|
|
-- custom hashmap thingy, but uses lists so it's slow on large things (luckily this is small)
|
2021-05-23 22:03:17 +00:00
|
|
|
tileActionMap :: Tile -> [(Tile, Element -> Element)] -> (Element -> Element)
|
2021-05-19 20:15:40 +00:00
|
|
|
tileActionMap _ [] = id
|
|
|
|
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
|
|
|
|
spitOut :: Factory -> Element -> Element
|
|
|
|
spitOut f 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
|
|
|
|
| (f !! (yPos elem - 1)) !! xPos elem == Track North = decYPos elem
|
|
|
|
|
2021-05-19 20:15:40 +00:00
|
|
|
update :: Factory -> Element -> Element
|
|
|
|
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-23 22:03:17 +00:00
|
|
|
tileActions = [ (Track East, \e -> Element (value e) (xPos e + 1) (yPos e))
|
|
|
|
, (Track West, \e -> Element (value e) (xPos e - 1) (yPos e))
|
|
|
|
, (Track South, \e -> Element (value e) (xPos e) (yPos e + 1))
|
|
|
|
, (Track North, \e -> Element (value e) (xPos e) (yPos e - 1))
|
|
|
|
, (Modifier Increment, incVal . spitOut f)
|
|
|
|
, (Modifier Decrement, decVal . spitOut f)
|
2021-05-19 20:15:40 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
stepInterpret :: Factory -> [Element] -> [Element]
|
2021-05-23 22:03:17 +00:00
|
|
|
stepInterpret f = map (update f)
|