2016-12-15 9 views
1

このコードはオンラインで見つかったばかりで、入力をどのようにフォーマットするべきか分かりません。同じプログラマーからの同様の入力の例を以下に示します:Pushdown automaton implemented in CC言語のチューリングマシン実装の入力を理解できません

しかしそれでもそれほど助けにはなりません。 E01:

入力形式は以下のようである:E0の$:000111::広告:aeebの$:b0eb0:b10ce:c10ce:入力デCE $は は、セミコロンで区切られているここでは言っていることです":"、最初のセクションは "アルファベット入力"、 秒は "スタックアルファベット"、次に "入力"と最後の全体バンチは 遷移関数です。

入力の処理方法を教えてください。私は今、約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; 
} 
+0

なぜC++タグ? – saeleko

+0

だけでは、と単純化された質問 –

+0

チューリングマシンの正式な定義についてはウィキペディアで見て固定します。 –

答えて

3

ラインbuffer = strtok(NULL,":")の多用は、入力された文字列が(リンク先のコードのように)コロンで区切られていることを確認します。

struct defintionsは、入力をリバースエンジニアリングするためのキーです。

主構造体である:

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)2番目の部分は、テープのアルファベットです。このコードの残りの部分で何らかの役割を果たす唯一の文字が最初の文字です。メインシミュレーション機能のconst char blank = m->tape_alpha[0];行は、最初の文字がブランク文字の役割を果たしていることを示します。これは、テープの正方形が空であることを示す文字です。ブランクを正方形に書き込むことができるため、チューリングマシンは正方形のデータを消去できます。ある意味では、入力のこの部分は順序が狂っていることに注意してください。構造体定義の3番目のフィールドとしてリストされていますが、入力文字列の2番目のフィールドです。

3)thirs部分は、テープの最初の入力です。これは、すべての文字が最初の部分から引き出された文字列です。この状態を確認するには、関数is_valid_input()を使用します。

4)次の部分は、単一チャー

5)次の部分は再び単一文字である受け入れる状態であるから成る開始状態、です。したがって、TMのこのモデルでは、単一の受理状態

6)次の部分は、再び文字列の配列であり、以下では単一チャー

7)で表される拒否状態であり、リンクされた文字列のリストに入れられます。機能get_transition()で慎重に見て

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

あなたは遷移が表されていることを推測することができます:それはどのように機能するかを理解する上で重要な機能は、これらの遷移文字列のいずれかを取り、Transition構造体に変換get_transition()である、と宣言しました最後の文字がRまたはLのいずれかの長さ5の文字列。例では、「シンボル0をスキャンしながら、状態aである場合、状態bへの移行、シンボル1と右に移動を書く」のようなものを言うa1b0Rようなものになるだろう。

はすべて一緒にそれを置く、入力文字列のは次のようなものになるだろう:私はランダムにいくつかの遷移を行わ

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

に対応

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

、そしてどちらもノウハウもこの入力でプログラムが何をするかを気にしてください。これは、あなたがプログラムを試してみるのに十分なはずです。

関連する問題