【问题标题】:Cannot understand input of a Turing Machine Implementation in C无法理解 C 中图灵机实现的输入
【发布时间】:2017-05-01 12:44:03
【问题描述】:

我只是在网上找到了这段代码,不明白输入应该如何格式化。来自同一程序员的类似输入示例如下所示:Pushdown automaton implemented in C

但它仍然没有太大帮助。它是这样说的:

输入格式如下: e01:e0$:000111:a:ad:aeeb$:b0eb0:b10ce:c10ce:ce$de 输入是 用分号“:”隔开,第一部分是“输入字母”, 第二个是“堆栈字母”,然后是“输入”,最后一整串是 转换函数。

谁能提供一些如何处理输入的指导?我现在非常努力地努力了大约 6 个小时,但我终其一生都无法破译此代码的输入格式。

使用 gcc 编译后,运行它只需执行“./executable”并按 Enter。然后粘贴如上所示的示例输入字符串(尽管对于这个程序,我需要不同的输入)。

/* This C file implements a Turing Machine
 * author: Kevin Zhou
 * Computer Science and Electronics
 * University of Bristol
 * Date: 21st April 2010
 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct tapes {
    struct tapes *left;
    struct tapes *right;
    char content;
} Tape;

typedef enum { LEFT,RIGHT } Direction;

typedef struct transition {
    char current_state;
    char tape_symbol;
    char new_state;
    char new_tape_symbol;
    Direction dir;
} Transition;

typedef struct list {
    Transition *content;
    struct list *next;
} List;

typedef struct tm {
    char *input_alpha;
    char *input;
    char *tape_alpha;
    char start;
    char accept;
    char reject;
    List *transition;
} TM;

Tape *insert_tape(Tape *t, Direction dir, char c) {
    Tape *head = t;
    Tape *new1 = calloc(1,sizeof(Tape));;
    new1 -> content = c;
    if(dir == LEFT) {
        while(t->left != NULL) {
            t = t->left;
        }
        new1->right = t;
        new1->left = NULL;
        t->left = new1;
        return new1;
    }
    if(dir == RIGHT) {
        while(t->right != NULL) {
            t = t->right;
        }
        new1->left = t;
        new1->right = NULL;
        t->right = new1;
    }
    return head;
}

Tape *create_tape(char *input) {
    int i=1;
    Tape *t = calloc(1,sizeof(Tape));
    t->content = input[0];
    while(1) {
        if(input[i] == '\0') break;
        t = insert_tape(t,RIGHT,input[i]);
        i++;
    }
    return t;
}

/* turn the input string into Transition fields */
Transition *get_transition(char *s) {
    Transition *t = calloc(1,sizeof(Transition));
    Direction dir;
    t->current_state = s[0];
    t->tape_symbol = s[1];
    t->new_state = s[2];
    t->new_tape_symbol = s[3];
    dir = (s[4]=='R')? RIGHT:LEFT;
    t->dir = dir;
    return t;
}

/* turn the string into transitions and add into list */
List *insert_list( List *l, char *elem ) {
    List *t = calloc(1,sizeof(List));
    List *head = l;
    while(l->next!=NULL)
        l = l->next;
    t->content = get_transition(elem);
    t->next = NULL;
    l->next = t;
    return head;
}

/* insert a transition into a list */
List *insert_list_transition( List *l, Transition *tr) {
    List *t = calloc(1,sizeof(List));
    List *head = l;
    while(l->next!=NULL)
        l = l->next;
    t->content = tr;
    t->next = NULL;
    l->next = t;
    return head;
}

void print_tape( Tape *t,char blank) {
    char c;
    while(1) {
        if(t->content != blank) break;
        t= t->right;
    }
    while(1) {
        if(t==NULL) break;
        c = t->content;
        if(t->content != blank)
            putchar(c);
        t= t->right;
    }
    putchar('\n');
}

void print_transition (Transition *t) {
    char s1[] = "Left";
    char s2[] = "Right";
    if(t==NULL) {
        printf("NULL Transfer");
        return;
    }
    printf("current:%c tape:%c new state:%c new tape:%c direction %s\n",t->current_state,t->tape_symbol,t->new_state,t->new_tape_symbol,(t->dir == LEFT)?s1:s2);
}

/*test if the char c is in the string s */
int contains ( char c, char *s ) {
    int i=0;
    while(1) {
        if(c== s[i]) return 1;
        if(s[i] == '\0') return 0;
        i++;
    }
}

/* test if the input is a valid input */
int is_valid_input( char *input_alpha, char *input ) {
    int i=0;
    char c;
    while(1) {
        c = input[i];
        if(c == '\0') break;
        if(!contains(c,input_alpha)) return 0;
        i++;
    }
    return 1;
}

TM *createTM (char *input) {

    TM *m = calloc(1,sizeof(TM));
    List *tr = calloc(1,sizeof(List));
    char *buffer;
    /*read input alphabet of PDA*/
    buffer = strtok(input,":");
    if(buffer == NULL) {
        printf("Error in reading input alphabet!\n");
        exit(1);
    }
    m->input_alpha = buffer;

    /*read tape alphabet*/
    buffer = strtok(NULL,":");

    if(buffer == NULL) {
        printf("Error in reading tape alphabet!\n");
        exit(1);
    }
    m->tape_alpha = buffer;

    /*read input sequence*/
    buffer = strtok(NULL,":");
    if(buffer == NULL) {
        printf("Error in reading input sequence!\n");
        exit(1);
    }

    if(!is_valid_input(m->input_alpha,buffer)) {
        printf("Error! Input contains some invalid characters that don't match the input alphabet!\n");
        exit(1);
    }

    m->input = buffer;
    buffer = strtok(NULL,":");
    m->start = buffer[0];
    buffer = strtok(NULL,":");
    m->accept = buffer[0];
    buffer = strtok(NULL,":");
    m->reject = buffer[0];

    /*read tape transition*/
    while(1) {
        buffer = strtok(NULL,":");
        if(buffer == NULL) break;
        tr = insert_list(tr,buffer);
    }

    m->transition = tr->next;
    return m;
}

Transition *find_transition(List * list,char state, char tape_symbol) {
    Transition *t;
    while(1) {
        if(list==NULL) return NULL;
        t = list -> content;
        if(t->current_state == state && t->tape_symbol == tape_symbol)
            return t;
        list = list->next;
    }
}

Tape *move(Tape *t,Direction dir, char blank) {
    if(dir == LEFT) {
        if(t->left==NULL) {
            t = insert_tape(t,LEFT,blank);
        }
        return t->left;
    }
    if(dir == RIGHT) {
        if(t->right==NULL) {
            t = insert_tape(t,RIGHT,blank);
        }
        return t->right;
    }
    return NULL;
}

void simulate( TM *m ) {
    /* first symbol in input symbol used to represent the blank symbol */
    const char blank = m->tape_alpha[0];
    char current_state = m->start;
    Tape *tape = create_tape(m->input);
    Tape *current_tape = tape;
    char current_tape_symbol;
    Transition *current_transition;
    while(1) {
        if(current_state == m->accept) {
            printf("Accept\n");
            print_tape(tape,blank);
            break;
        }
        if(current_state == m->reject) {
            printf("Reject\n");
            print_tape(tape,blank);
            break;
        }
        current_tape_symbol = (current_tape==NULL||current_tape ->content == '\0')?blank:current_tape->content;
        current_transition = find_transition(m->transition,current_state,current_tape_symbol);
        current_state = current_transition -> new_state;
        current_tape -> content = current_transition -> new_tape_symbol;
        current_tape = move( current_tape, current_transition ->dir, blank);
    }
}

int main(void) {
    char s[300];
    TM *p;
    scanf("%s",s);
    p = createTM(s);
    simulate(p);
    return 0;
}

【问题讨论】:

  • 为什么是 c++ 标签?
  • 刚刚解决了这个问题,并简化了问题
  • 在维基百科中查找图灵机的正式定义。
  • 图灵机和下推自动机不是一回事。该代码并未将自己标记为图灵机的实现。
  • 输入的描述不完整,没有说明:a:ad:这两个字段既不是输入字母也不是堆栈字母,也不是输入不是转换(长度为5的字段- - 对应于 Transition 结构中的 5 个字符)。我的猜测是a 是开始状态,ad 是接受状态。查看代码的作用,并将其与维基百科中 PDA 的正式定义进行比较。

标签: c turing-machines


【解决方案1】:

buffer = strtok(NULL,":") 行的大量使用确认输入字符串(如在链接到的代码中)以冒号分隔。

结构定义是对输入进行逆向工程的关键。

主要结构是:

typedef struct tm {
    char *input_alpha;
    char *input;
    char *tape_alpha;
    char start;
    char accept;
    char reject;
    List *transition;
} TM;

函数createTM() 是拆分: 上的输入并加载图灵机的函数。 struct tm 有 7 个字段,createTM() 有 7 个明确阶段

1) 第一部分是输入字母。大概这将是一个包含 1 个或多个字符的字符串,例如01.

2) 第二部分是磁带,是磁带字母表。在此代码的其余部分中起任何作用的唯一字符是第一个字符。主模拟函数中的const char blank = m-&gt;tape_alpha[0];行表示第一个字符扮演空白字符的角色——表示磁带方为空的字符。将空白写入正方形的能力允许图灵机擦除正方形中的数据。请注意,在某种意义上,这部分输入是无序的——它在结构定义中被列为第三个字段,但在输入字符串中是第二个字段。

3) 第三部分是磁带上的初始输入。它是一个字符串,其所有字符均来自第一部分。函数is_valid_input() 用于检查这种情况。

4) 下一部分是起始状态,由单个字符组成

5) 下一部分是接受状态,它还是一个字符。因此,在这个 TM 模型中,只有一个接受状态

6) 下一部分是拒绝状态,再次用单个字符表示

7) 接下来是一个字符串序列,输入到一个字符串链表中。了解其工作原理的关键函数是 get_transition(),它采用这些转换字符串之一并将其转换为 Transition 结构,声明为:

typedef struct transition {
    char current_state;
    char tape_symbol;
    char new_state;
    char new_tape_symbol;
    Direction dir;
} Transition;

仔细查看函数get_transition(),您可以推断出转换由长度为5 的字符串表示,其中最后一个字符是RL。例如a1b0R 之类的内容类似于“如果您在扫描符号0 时处于状态a,则转换到状态b,写入符号1 并向右移动”。

综上所述,输入字符串的形式如下:

01:_102:1001010101:$:a:r:$0b1R:b1b0L:a1b2R

对应

   01    _102    1001010101     $       a       r       $0b1R    b1b0L    a1b2R
 input   tape      input      start  accept  reject          transitions
|  alphabets |                 |     states        | 
(blank = '_')    

我只是随机进行了一些转换,既不知道也不关心程序会用这个输入做什么。这应该足以让您开始试验该程序。

【讨论】:

    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 2013-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 2014-01-25
    相关资源
    最近更新 更多