-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
128 lines (109 loc) · 2.88 KB
/
main.go
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
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const PRINT_ALL_STATES = false
// Transition represents a single transition in the Turing machine.
type Transition struct {
Read int
Write int
Move string
NextState string
}
// TuringMachineProgram represents the entire Turing machine program.
type TuringMachineProgram map[string]map[int]Transition
// ParseFile parses the input file and returns the Turing machine program.
func ParseFile(filePath string) (TuringMachineProgram, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
program := make(TuringMachineProgram)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) == 0 || strings.HasPrefix(line, "#") {
continue
}
parts := strings.Split(line, ";")
if len(parts) != 5 {
return nil, fmt.Errorf("invalid line format: %s", line)
}
state := parts[0]
read, _ := strconv.Atoi(parts[1])
write, _ := strconv.Atoi(parts[2])
move := parts[3]
nextState := parts[4]
if _, exists := program[state]; !exists {
program[state] = make(map[int]Transition)
}
program[state][read] = Transition{
Read: read,
Write: write,
Move: move,
NextState: nextState,
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return program, nil
}
// Execute one instruction then return the new currentNode and currentState
func ExecuteInstruction(program TuringMachineProgram, tape *DoublyLinkedList, currentNode *Node, currentState string) (*Node, string) {
transition := program[currentState][currentNode.value]
currentNode.value = transition.Write
if transition.Move == "RIGHT" {
currentNode = currentNode.next
if currentNode == nil {
tape.AppendRight(0)
currentNode = tape.tail
}
}
if transition.Move == "LEFT" {
currentNode = currentNode.prev
if currentNode == nil {
tape.AppendLeft(0)
currentNode = tape.head
}
}
currentState = transition.NextState
return currentNode, currentState
}
// Execute the Program... be careful, it may not return
func ExecuteProgram(program TuringMachineProgram, tape *DoublyLinkedList, currentNode *Node, currentState string) {
i := 0
for {
i = i + 1
currentNode, currentState = ExecuteInstruction(program, tape, currentNode, currentState)
if PRINT_ALL_STATES {
fmt.Print(i, " : ", currentState, " : ")
tape.Display(60)
}
if currentState == "STOP" {
if !PRINT_ALL_STATES {
fmt.Print("Finished after ", i, " steps")
}
return
}
}
}
func main() {
program, err := ParseFile("sample.txt")
if err != nil {
fmt.Println("Error:", err)
return
}
// create a tape as a doubly linked list and create a first node 0
tape := &DoublyLinkedList{}
tape.AppendRight(0)
currentNode := tape.head
// initial state is "A"
currentState := "A"
ExecuteProgram(program, tape, currentNode, currentState)
}