-
Notifications
You must be signed in to change notification settings - Fork 1
/
turing.hs
139 lines (101 loc) · 3.75 KB
/
turing.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import System.IO;
import System.Environment;
type Symbol = String
type State = String
-- Direction
data Direction = Left | Right | Still deriving (Show, Eq, Read)
-- Tape
data Tape = Tape { value :: Symbol
, leftPart :: [Symbol]
, rightPart :: [Symbol] } deriving Show
-- Rule
data Rule = Rule { prevSymbol :: Symbol
, prevState :: State
, nextState :: State
, nextSymbol :: Symbol
, direction :: Direction } deriving Show
-- TuringMachine
data TuringMachine = TuringMachine { currentState :: State
, finalStates :: [State]
, rules :: [Rule] } deriving Show
readSpecificationFile specFile = do
contents <- readFile specFile
let result = map (\el -> split el ';') (lines contents)
let initialState = (result !! 0) !! 0
let finalStates = result !! 1
let rulesList = map (\rule -> split rule ' ') (result !! 2)
let rules = map (\rule -> Rule (rule !! 0) (rule !! 1) (rule !! 2) (rule !! 3) (read (rule !! 4) :: Direction)) rulesList
let tm = TuringMachine { currentState = initialState
, finalStates = finalStates
, rules = rules }
return tm
readTape tapeFile = do
contents <- readFile tapeFile
let tapeList = split ((lines contents) !! 0) ';'
let tape = Tape { value = head tapeList
, leftPart = []
, rightPart = tail tapeList }
return tape
saveResult resultFile result = do
writeFile resultFile result
split :: String -> Char -> [String]
split "" _ = [""]
split (x:xs) ch =
if x == ch
then "" : rest
else (x : (head rest)) : (tail rest)
where
rest = (split xs ch)
runTM :: (TuringMachine, Tape) -> Tape
runTM (tm, tape) =
if currentState tm `elem` finalStates tm
then tape
else runTM $ moveTM (tm, tape)
moveTM :: (TuringMachine, Tape) -> (TuringMachine, Tape)
moveTM (tm, tape) =
let newTm = TuringMachine (nextState rule) (finalStates tm) (rules tm)
newTape = moveTape (Tape (nextSymbol rule) (leftPart tape) (rightPart tape)) (direction rule)
rule = findRule (currentState tm) (value tape) (rules tm)
in (newTm, newTape)
moveTape :: Tape -> Direction -> Tape
moveTape tape Main.Left = moveLeft tape
moveTape tape Main.Right = moveRight tape
moveTape tape _ = tape
moveLeft :: Tape -> Tape
moveLeft tape =
let left = leftPart tape
right = rightPart tape
val = value tape
in if null left
then Tape "*" [] (val:right)
else Tape (last left) (init left) (val:right)
moveRight :: Tape -> Tape
moveRight tape =
let left = leftPart tape
right = rightPart tape
val = value tape
in if null right
then Tape "*" (left ++ [val]) []
else Tape (head right) (left ++ [val]) (tail right)
findRule :: State -> Symbol -> [Rule] -> Rule
findRule state symbol rules =
head $ filter (\rule -> (prevState rule == state) && (prevSymbol rule == symbol)) rules
printTapeNicely tape =
print $ (leftPart tape) ++ ["__" ++ value tape ++ "__"] ++ (rightPart tape)
getNiceTape tape = show $ (leftPart tape) ++ ["__" ++ value tape ++ "__"] ++ (rightPart tape)
listToString list = show list
main = do
files <- getArgs
let specFile = files !! 0
tapeFile = files !! 1
resultFile = files !! 2
tm <- readSpecificationFile specFile
putStrLn $ "\nTURING MACHINE: "
print $ tm
tape <- readTape tapeFile
putStrLn $ "\nTAPE: "
printTapeNicely $ tape
putStrLn $ "\nRESULT: "
let resultTape = runTM (tm, tape)
printTapeNicely $ resultTape
saveResult resultFile (getNiceTape resultTape)