Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
7 / 7 / 3
Регистрация: 22.09.2015
Сообщений: 173

Машина Тьюринга: не хватает одного IF в программе

04.10.2016, 11:53. Показов 2108. Ответов 8

Студворк — интернет-сервис помощи студентам
Добрый день.
Программа считывает вводимый мной файл (1.txt, 2.txt, 3.txt, 4.txt). Считываются положение головки, самой полосы данных и инструкции.
Программа работает со всеми, кроме 1.txt

C++
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
#include <iostream>
#include <string>
#include <fstream>
 
using namespace std;
 
int main()
{
    const int MAX = 100;
    
    int  header;
    int i = 0;
    int j = 0;
    int star;
 
    bool stop = 0;
    bool starexist = 0;
    bool exist = 0;
 
    char current_symbol[MAX];
    char new_symbol[MAX];
    char direction[MAX];
 
    string line;
    string filename;
    string chars = "RL*";
    string current_status[MAX];
    string new_status[MAX];
    string temp;
 
    cout << "Enter file name:" << endl;
    cin >> filename;
    ifstream object(filename.c_str());
 
    if (!object) {
        cerr << "Error, the file " << filename << " does not exist!"  << endl;
    return -1;
    }
 
    object >> header;
    header--;
    object >> line;
    
    while (!object.eof()) {
        object >> current_status[i] >> current_symbol[i] >> new_symbol[i] >> direction[i] >> new_status[i];
        i++;
    }
 
    object.close();
 
    temp = current_status[0];
    
    for (j = 0; j <= i; j++) {
        starexist = 0;
        exist = 0;
        if (current_status[j] == temp) {
            if (current_symbol[j] == chars[2]) {
                if (current_symbol[j] == line[header]) {
                    exist = 1;
                        line[header] = new_symbol[j];
                        if (direction[j] == chars[0]) header++;
                        if (direction[j] == chars[1]) header--;
                        if (direction[j] == chars[2]) header = header;
 
                    cout << line << endl;
                    temp = new_status[j];
                    j = -1;
                }
 
                else {
                    star = j;
                    j++;
                    starexist = 1;
                }
 
            }
 
            if (exist == 0 && current_symbol[j] == line[header]) {
                exist = 1;
                line[header] = new_symbol[j];
 
                if (direction[j] == chars[0]) header++;
                if (direction[j] == chars[1]) header--;
                if (direction[j] == chars[2]) header = header;
                cout << line << endl;
                temp = new_status[j];
                j = -1;
            }
        }
 
        if ((j == i) && (exist == 0)) {
            if (starexist == 1) {
                line[header] = new_symbol[star];
                if (direction[star] == chars[0]) header++;
                if (direction[star] == chars[1]) header--;
                if (direction[star] == chars[2]) header = header;
                cout << line << endl;
                temp = new_status[star];
                j = -1;
            }
 
            else {
                stop = 1;
                j = i + 1;
            }
 
        }
    }
    if (stop == 1) cout << "Finished!" << endl;
return 0;
}
Вот содержание 1.txt

C++
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
1
00V0000000001111*A000000000001111*B000000000000000000000000ZR000000000H000000
 
0 0 0 R 0
0 1 1 R 0
0 V V R 0 
0 * * L 1
 
1 0 * R 2
1 1 * R 3
1 V V R 20
1 V V R 20
 
2 * 0 R 4
3 * 1 R 5
 
4 A A R 4
4 0 0 R 4
4 1 1 R 4
5 A A R 5
5 0 0 R 5
5 1 1 R 5
 
4 * * L 6
5 * * L 7
 
6 0 * R 8
6 1 * R 9
7 0 * R 10
7 1 * R 11
6 A A R 20
7 A A R 20
 
8 * 0 R 12
9 * 1 R 13
10 * 0 R 14
11 * 1 R 15
 
12 B B R 12
12 0 0 R 12
12 1 1 R 12
13 B B R 13
13 0 0 R 13
13 1 1 R 13
14 B B R 14
14 0 0 R 14
14 1 1 R 14
15 B B R 15
15 0 0 R 15
15 1 1 R 15
 
12 Z 0 L 16
13 Z 1 L 16
14 Z 1 L 16
15 Z 0 L 17
 
12 C 1 L 16
13 C 0 L 17
14 C 0 L 17
15 C 1 L 17
 
16 0 Z L 18
17 0 C L 18
 
18 A A L 18
18 B B L 18
18 * * L 18
18 0 0 L 18
18 1 1 L 18
18 V V R 0
 
20 A A R 20
20 B B R 20
20 * * R 20
20 0 0 R 20
20 1 1 R 20
20 Z 0 R 21
20 C 1 R 21
 
21 0 0 R X
21 1 1 R X
Программа дает такой результат;
C++
1
00V*0000000001111A00*0000000001111B0000000000000000000011110R000000000H000000
А должно быть так;

C++
1
00V0000000001111110000000000011111100000000000000000000000100000000000H000000
Помогите
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.10.2016, 11:53
Ответы с готовыми решениями:

Машина поста и машина тьюринга: необходимо написать алгоритм к данному изображению
нужно решение в виде команд МТ и МП

Сложение четырех целых без знака (Машина Поста), Троичное вычитание "-1" (Машина Тьюринга).
Здравствуйте! Можете пожалуйста помочь с задачками: Машина Поста: Сложение четырех целых без знака? Машина Тьюринга: Троичное...

Машины Поста и Тьюринга. Посчитать количество букв имени (4) и фамилии (7), а затем указать разницу
Помогите решить задачу. На Машине Поста нужно написать программу Необходимо посчитать количество букв имени(4) и фамилии (7) А затем...

8
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
04.10.2016, 12:14
Aliksan, можете выложить остальные входные файлы?

Bash
1
2
3
4
5
6
7
8
9
$> clang++ -std=c++11 -Wall -Wpedantic -Wextra -Werror -mtune=native -c machine.cpp
machine.cpp:63:62: error: explicitly assigning value of variable of type 'int' to itself [-Werror,-Wself-assign]
                        if (direction[j] == chars[2]) header = header;
                                                      ~~~~~~ ^ ~~~~~~
machine.cpp:84:54: error: explicitly assigning value of variable of type 'int' to itself [-Werror,-Wself-assign]
                if (direction[j] == chars[2]) header = header;
                                              ~~~~~~ ^ ~~~~~~
machine.cpp:96:57: error: explicitly assigning value of variable of type 'int' to itself [-Werror,-Wself-assign]
                if (direction[star] == chars[2]) header = header;
0
7 / 7 / 3
Регистрация: 22.09.2015
Сообщений: 173
04.10.2016, 21:08  [ТС]
Остальные файлы;
2.txt
C++
1
2
3
4
5
6
7
7
00000000000000000000000*0000
0 0 0 R 0
0 1 1 R 0
0 * * L 1
1 0 1 R 0
1 1 0 L 1
3.txt
C++
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
7
00000000000000000000000*0000
 
0 0 0 R 0
0 1 1 R 0
0 2 2 R 0
0 3 3 R 0
0 4 4 R 0
0 5 5 R 0
0 6 6 R 0
0 7 7 R 0
0 8 8 R 0
0 9 9 R 0
 
0 * * L 1
 
1 0 1 R 0
1 1 2 R 0
1 2 3 R 0
1 3 4 R 0
1 4 5 R 0
1 5 6 R 0
1 6 7 R 0
1 7 8 R 0
1 8 9 R 0
1 9 0 L 1
4.txt
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
7
000100000000000000001111111000000000000000010000
0 0 0 R 0
0 1 0 R 11
11 1 1 R 11
11 0 1 R 2
2 0 0 L 3
2 1 1 L 4
3 1 1 L 3
3 0 0 R 0
4 1 0 L 5
4 0 0 L 4
5 1 1 L 5
5 0 1 L 12
12 0 0 R 6
12 1 1 R 0
6 1 1 R 6
6 0 0 L 4
Добавлено через 1 минуту
Программа компилируется без ошибок и запускается в linux через g++.

Добавлено через 3 минуты
Для Windows, скорее всего надо поменять эту строчку
C++
1
ifstream object(filename.c_str());
на эту;
C++
1
ifstream object(filename);
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
05.10.2016, 04:42
Aliksan, а в самом файле 1.txt случайно нет ошибки?

моя реализация
C++
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**
 * @file machine.cpp
 * @compile g++ -std=c++11 -Wall -Wpedantic -Wextra -Werror -O2 -mtune=native machine.cpp -o machine
 * */
 
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <map>
 
namespace tools {
    std::string right_trim(const std::string &str) noexcept {
        std::string::size_type last_space = str.find_last_not_of(" \t\r\n");
        return last_space == std::string::npos ? "" : (
                str.size() == (last_space + 1) ? str : str.substr(0, last_space + 1)
        );
    }
}
 
namespace turing {
    /**
     * direction constants
     */
    enum directions {
        RIGHT = 'R',
        LEFT  = 'L',
        SAME  = '*'
    };
    template<typename T1, typename T2>
    using map = std::map<T1, T2>;
    using state_type = std::string;
    using symbol_type = char;
 
    /**
     * next state for turing::machine
     */
    struct next_state {
        /**
         * move direction
         */
        symbol_type direction;
        /**
         * next state
         */
        state_type next_state;
        /**
         * replace symbol
         */
        symbol_type next_char;
    };
 
    using state_list = map<symbol_type, next_state>;
    using state_map = map<state_type, state_list>;
 
    /**
     * machine state
     */
    struct machine {
        /**
         * current head position
         */
        size_t head_position;
        /**
         * current state
         */
        state_type state;
        /**
         * machine "tape"
         */
        std::string tape;
        /**
         * state table
         */
        state_map state_table;
    };
 
    /**
     * load machine state from input stream
     * 
     * @param input stream 
     * @return loaded state
     * @throw std::runtime_error if cant parse state line
     */
    machine load(std::istream& input) throw(std::runtime_error) {
        machine m;
        std::string line;
 
        input >> m.head_position;
        input >> m.tape;
 
        while (std::getline(input, line)) {
            line = tools::right_trim(line);
            if (line.empty())
                continue;
            std::istringstream parser(line);
            state_type current_state, next_state;
            symbol_type current_char, next_char, direction;
 
            parser >> current_state >> current_char >> next_char >> direction >> next_state;
            if (parser.fail()) {
                throw std::runtime_error("parser.fail()");
            }
            // fill state for current state+char pair
            {
                auto& state = m.state_table[current_state][current_char];
                state.direction  = direction;
                state.next_char  = next_char;
                state.next_state = next_state;
            }
        }
        m.state = m.state_table.begin()->first;
        m.tape = tools::right_trim(m.tape);
        --m.head_position;
        return m;
    }
 
    /**
     * run machine
     * @param m machine state
     * @return 0
     * @throw std::runtime_error if cant find next state
     * @throw std::out_of_range if head outside tape
     */
    int run(machine& m) throw(std::runtime_error, std::out_of_range) {
        bool in_cycle = false;
        bool stop = false;
 
        while (!stop) {
            state_map::iterator state;
            state_list::iterator next;
 
            // find state table for current state
            state = m.state_table.find(m.state);
            if (state == m.state_table.end()) {
                // m.state missing in m.state_table
                throw std::runtime_error("state == m.state_table.end()");
            }
            // find next state for current symbol
            const auto current_symbol = m.tape.at(m.head_position);
            next = state->second.find(current_symbol);
            if (next == state->second.end()) {
                // current_symbol missing in m.state_table[m.state]
                throw std::runtime_error("next == state->second.end()");
            }
            next_state new_state = next->second;
            m.tape[m.head_position] = new_state.next_char;
            m.state = new_state.next_state;
 
            switch (new_state.direction) {
                case RIGHT:
                    in_cycle = false;
                    m.head_position++;
                    break;
                case LEFT:
                    in_cycle = false;
                    m.head_position--;
                    break;
                case SAME:
                    if (in_cycle) {
                        throw std::runtime_error("loop detected");
                    }
                    in_cycle = true;
                    break;
                default:
                    throw std::runtime_error("wrong direction");
            }
            std::cout << m.tape << std::endl;
            stop = m.state == "X";
        }
        return 0;
    }
}
 
int main(int argc, char** argv) {
    std::string file_name;
    std::ifstream input;
 
 
    if (argc == 1) {
        std::cout << "Enter file name > ";
        std::cin >> file_name;
    } else {
        file_name = argv[1];
    }
 
    input.open(file_name);
 
    if (!input.is_open()) {
        std::cerr << "open fail" << std::endl;
        return 0xdead;
    }
    try
    {
        using namespace turing;
        machine m = load(input);
        return run(m);
    }
    catch (std::runtime_error& e) {
        std::cerr << "Aborted: " << e.what() << std::endl;
    }
    return 0xdead;
}

выдает
Code
1
00V*0000000001111A00*0000000001111B0000000000000000000011110R000000000H00000
1
7 / 7 / 3
Регистрация: 22.09.2015
Сообщений: 173
05.10.2016, 15:56  [ТС]
Очень сложно у вас написано, сразу чувствуется, что код писал не любитель программирования и даже не студент...
Буду смотреть ваш код. 1.тхт тестировался тут. И результат без знаков умножения и букв A, B, C.

Добавлено через 6 минут
Один студент сказал, что проблему решил после того, как отсортировал инструкции. Я взял и сортировку сделал не в коде а в 1.тхт, естественно, проблему это не решило.

Добавлено через 19 минут
Только что проверил ваш код на работоспособность, та же история ... 1.тхт тупит. Пытался подрихтовать сам 1.тхт, удалить пару тройку инструкций, кой-что изменить, но в итоге это еще сложнее, чем подправить код.
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
05.10.2016, 16:25
Лучший ответ Сообщение было отмечено Aliksan как решение

Решение

Цитата Сообщение от Aliksan Посмотреть сообщение
1.тхт тестировался тут.
переделал под те правила:
  • * в текущем символе означает "любой символ"
  • * в следующем символе означает "оставить как есть"
теперь выдает
Code
1
00V0000000001111110000000000011111100000000000000000000000100000000000H000000
реализация
C++
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
 * @file machine.cpp
 * @compile g++ -std=c++11 -Wall -Wpedantic -Wextra -Werror -O2 -mtune=native machine.cpp -o machine
 * */
 
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <map>
 
namespace tools {
    std::string right_trim(const std::string &str) noexcept {
        std::string::size_type last_space = str.find_last_not_of(" \t\r\n");
        return last_space == std::string::npos ? "" : (
                str.size() == (last_space + 1) ? str : str.substr(0, last_space + 1)
        );
    }
}
 
namespace turing {
    /**
     * direction constants
     */
    enum directions {
        RIGHT = 'R',
        LEFT  = 'L',
        SAME  = '*'
    };
    template<typename T1, typename T2>
    using map = std::map<T1, T2>;
    using state_type = std::string;
    using symbol_type = char;
 
    /**
     * next state for turing::machine
     */
    struct next_state {
        /**
         * move direction
         */
        symbol_type direction;
        /**
         * next state
         */
        state_type next_state;
        /**
         * replace symbol
         */
        symbol_type next_char;
    };
 
    using state_list = map<symbol_type, next_state>;
    using state_map = map<state_type, state_list>;
 
    /**
     * machine state
     */
    struct machine {
        /**
         * current head position
         */
        size_t head_position;
        /**
         * current state
         */
        state_type state;
        /**
         * machine "tape"
         */
        std::string tape;
        /**
         * state table
         */
        state_map state_table;
    };
 
    /**
     * load machine state from input stream
     * 
     * @param input stream 
     * @return loaded state
     * @throw std::runtime_error if cant parse state line
     */
    machine load(std::istream& input) throw(std::runtime_error) {
        machine m;
        std::string line;
 
        input >> m.head_position;
        input >> m.tape;
 
        while (std::getline(input, line)) {
            line = tools::right_trim(line);
            if (line.empty())
                continue;
            std::istringstream parser(line);
            state_type current_state, next_state;
            symbol_type current_char, next_char, direction;
 
            parser >> current_state >> current_char >> next_char >> direction >> next_state;
            if (parser.fail()) {
                throw std::runtime_error("parser.fail()");
            }
            // fill state for current state+char pair
            {
                auto& state = m.state_table[current_state][current_char];
                state.direction  = direction;
                state.next_char  = next_char;
                state.next_state = next_state;
            }
        }
        m.state = m.state_table.begin()->first;
        m.tape = tools::right_trim(m.tape);
        --m.head_position;
        return m;
    }
 
    /**
     * run machine
     * @param m machine state
     * @return 0
     * @throw std::runtime_error if cant find next state
     * @throw std::out_of_range if head outside tape
     */
    int run(machine& m) throw(std::runtime_error, std::out_of_range) {
        bool in_cycle = false;
        bool stop = false;
 
        while (!stop) {
            state_map::iterator state;
            state_list::iterator next;
 
            // find state table for current state
            state = m.state_table.find(m.state);
            if (state == m.state_table.end()) {
                // m.state missing in m.state_table
                throw std::runtime_error("state == m.state_table.end()");
            }
            // find next state for current symbol
            const auto current_symbol = m.tape.at(m.head_position);
            next = state->second.find(current_symbol);
            if (next == state->second.end()) {
                // no rule for current_symbol, try find rule for "any" symbol
                next = state->second.find('*');
            }
            if (next == state->second.end()) {
                // current_symbol missing in m.state_table[m.state]
                throw std::runtime_error("next == state->second.end()");
            }
            next_state new_state = next->second;
            // no change if next char == '*'
            if (new_state.next_char != '*') {
                m.tape[m.head_position] = new_state.next_char;
            }
            m.state = new_state.next_state;
 
            switch (new_state.direction) {
                case RIGHT:
                    in_cycle = false;
                    m.head_position++;
                    break;
                case LEFT:
                    in_cycle = false;
                    m.head_position--;
                    break;
                case SAME:
                    if (in_cycle) {
                        throw std::runtime_error("loop detected");
                    }
                    in_cycle = true;
                    break;
                default:
                    throw std::runtime_error("wrong direction");
            }
            std::cout << m.tape << std::endl;
            stop = m.state == "X";
        }
        return 0;
    }
}
 
int main(int argc, char** argv) {
    std::string file_name;
    std::ifstream input;
 
 
    if (argc == 1) {
        std::cout << "Enter file name > ";
        std::cin >> file_name;
    } else {
        file_name = argv[1];
    }
 
    input.open(file_name);
 
    if (!input.is_open()) {
        std::cerr << "open fail" << std::endl;
        return 0xdead;
    }
    try
    {
        using namespace turing;
        machine m = load(input);
        return run(m);
    }
    catch (std::runtime_error& e) {
        std::cerr << "Aborted: " << e.what() << std::endl;
    }
    return 0xdead;
}
1
7 / 7 / 3
Регистрация: 22.09.2015
Сообщений: 173
05.10.2016, 17:17  [ТС]
Господи, это работает ... Я неделю ломал голову над изменениями в своей программе, а вы в своей буквально сразу переделали под мой случай. Max Dark, большое вам спасибо. Вы очень мне помогли!
0
0 / 0 / 0
Регистрация: 15.02.2017
Сообщений: 1
15.02.2017, 21:49
Aliksan, Hello, i have a similar problem with my Turing machine, if still have it, could you write working code to me. I would really appreciate that.
0
7 / 7 / 3
Регистрация: 22.09.2015
Сообщений: 173
15.02.2017, 21:56  [ТС]
The program was written above.
C++
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
 * @file machine.cpp
 * @compile g++ -std=c++11 -Wall -Wpedantic -Wextra -Werror -O2 -mtune=native machine.cpp -o machine
 * */
 
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <map>
 
namespace tools {
    std::string right_trim(const std::string &str) noexcept {
        std::string::size_type last_space = str.find_last_not_of(" \t\r\n");
        return last_space == std::string::npos ? "" : (
                str.size() == (last_space + 1) ? str : str.substr(0, last_space + 1)
        );
    }
}
 
namespace turing {
    /**
     * direction constants
     */
    enum directions {
        RIGHT = 'R',
        LEFT  = 'L',
        SAME  = '*'
    };
    template<typename T1, typename T2>
    using map = std::map<T1, T2>;
    using state_type = std::string;
    using symbol_type = char;
 
    /**
     * next state for turing::machine
     */
    struct next_state {
        /**
         * move direction
         */
        symbol_type direction;
        /**
         * next state
         */
        state_type next_state;
        /**
         * replace symbol
         */
        symbol_type next_char;
    };
 
    using state_list = map<symbol_type, next_state>;
    using state_map = map<state_type, state_list>;
 
    /**
     * machine state
     */
    struct machine {
        /**
         * current head position
         */
        size_t head_position;
        /**
         * current state
         */
        state_type state;
        /**
         * machine "tape"
         */
        std::string tape;
        /**
         * state table
         */
        state_map state_table;
    };
 
    /**
     * load machine state from input stream
     * 
     * @param input stream 
     * @return loaded state
     * @throw std::runtime_error if cant parse state line
     */
    machine load(std::istream& input) throw(std::runtime_error) {
        machine m;
        std::string line;
 
        input >> m.head_position;
        input >> m.tape;
 
        while (std::getline(input, line)) {
            line = tools::right_trim(line);
            if (line.empty())
                continue;
            std::istringstream parser(line);
            state_type current_state, next_state;
            symbol_type current_char, next_char, direction;
 
            parser >> current_state >> current_char >> next_char >> direction >> next_state;
            if (parser.fail()) {
                throw std::runtime_error("parser.fail()");
            }
            // fill state for current state+char pair
            {
                auto& state = m.state_table[current_state][current_char];
                state.direction  = direction;
                state.next_char  = next_char;
                state.next_state = next_state;
            }
        }
        m.state = m.state_table.begin()->first;
        m.tape = tools::right_trim(m.tape);
        --m.head_position;
        return m;
    }
 
    /**
     * run machine
     * @param m machine state
     * @return 0
     * @throw std::runtime_error if cant find next state
     * @throw std::out_of_range if head outside tape
     */
    int run(machine& m) throw(std::runtime_error, std::out_of_range) {
        bool in_cycle = false;
        bool stop = false;
 
        while (!stop) {
            state_map::iterator state;
            state_list::iterator next;
 
            // find state table for current state
            state = m.state_table.find(m.state);
            if (state == m.state_table.end()) {
                // m.state missing in m.state_table
                throw std::runtime_error("state == m.state_table.end()");
            }
            // find next state for current symbol
            const auto current_symbol = m.tape.at(m.head_position);
            next = state->second.find(current_symbol);
            if (next == state->second.end()) {
                // no rule for current_symbol, try find rule for "any" symbol
                next = state->second.find('*');
            }
            if (next == state->second.end()) {
                // current_symbol missing in m.state_table[m.state]
                throw std::runtime_error("next == state->second.end()");
            }
            next_state new_state = next->second;
            // no change if next char == '*'
            if (new_state.next_char != '*') {
                m.tape[m.head_position] = new_state.next_char;
            }
            m.state = new_state.next_state;
 
            switch (new_state.direction) {
                case RIGHT:
                    in_cycle = false;
                    m.head_position++;
                    break;
                case LEFT:
                    in_cycle = false;
                    m.head_position--;
                    break;
                case SAME:
                    if (in_cycle) {
                        throw std::runtime_error("loop detected");
                    }
                    in_cycle = true;
                    break;
                default:
                    throw std::runtime_error("wrong direction");
            }
            std::cout << m.tape << std::endl;
            stop = m.state == "X";
        }
        return 0;
    }
}
 
int main(int argc, char** argv) {
    std::string file_name;
    std::ifstream input;
 
 
    if (argc == 1) {
        std::cout << "Enter file name > ";
        std::cin >> file_name;
    } else {
        file_name = argv[1];
    }
 
    input.open(file_name);
 
    if (!input.is_open()) {
        std::cerr << "open fail" << std::endl;
        return 0xdead;
    }
    try
    {
        using namespace turing;
        machine m = load(input);
        return run(m);
    }
    catch (std::runtime_error& e) {
        std::cerr << "Aborted: " << e.what() << std::endl;
    }
    return 0xdead;
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.02.2017, 21:56
Помогаю со студенческими работами здесь

Машина Поста и машина Тьюринга
Машина Поста и машина Тьюринга это одно и то же по сути ? Разница только в наборе команд ??? и алфавите?? Как я понял Машина Поста это ,как...

Реализовать двусвязный список. В разных узлах одного списка может быть любой объект одного из допустимых типов (своих знаний не хватает)
Вобщем делаю тестовые задания. На одно мне даже ответили, результат отрицательный. Помогите понять если кто поймёт его не так как я или...

машина Тьюринга
произвести замену буквы А на Б и подсчитать количество замен. пожааалуйста помогите

Машина Тьюринга: вставка символа A после первого символа непустого слова Р
нужно решение А={a,b,c}. Составьте программу для МТ вставки символа а после первого символа непустого слова Р.

Машина Тьюринга
Что будет на выходе, если послать 11111*11111 У меня почему-то не работает...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru