Quantcast
Channel: Bashタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 2722

決定性TMをシミュレートするシェルスクリプト

$
0
0

この休日、シェルスクリプトの基本を勉強したので、その記録として、決定性TM $M=(Q,S,S,\delta,q_0,\_,F)$ をシミュレートするシェルスクリプトを作りました。

TM.sh
#!/bin/bash# SettingsQ=(0 1 2)S=('_''a''b')q0=0;F=(2);L=-1;R=1;# delta: Q×S → Q×S×{L,R}d0_=end;d0a=(1 'a'$R);d0b=(0 'b'$R);d1_=(2 'a'$L);d1a=(1 'b'$R);d1b=(1 'a'$L);d2_=end;d2a=end;d2b=end;# Controllerq=$q0;w="$1";cur=0

echo"$w: "while
    if[ 0 -le$cur-a$cur-lt${#w}];then
        c=${w:$cur:1}else
        c='_'fi
    to=($(eval echo\${d"$q$c"\[\@\]}))echo'(q,w,cur): '"($q,$w,$cur)"if[$to= end ];then
        break
    fi
    q=${to[0]}if[ 0 -le$cur-a$cur-lt${#w}];then
        w=$(echo"$w" | sed-e"s/./${to[1]}/$((cur +1))")elif[$cur-lt 0 ];then
        for((i=0; i < -cur - 1; ++i));do
            w='_'"$w"done
        w="${to[1]}$w"cur=0
    else
        for((i=0; i < cur - ${#w}; ++i));do
            w="$w"'_'done
        w="$w${to[1]}"fi((cur +=${to[2]}))
    :
do :;done

for qf in"${F[@]}";do
    if[$qf-eq$q];then
        echo'Accepted'exit 0
    fi
done
echo'Rejected'exit 1

この設定では次のようなTMを表しています:
image.png
だから、例えば、

$ bash TM.sh ab
ab: 
(q,w,cur): (0,ab,0)(q,w,cur): (1,ab,1)(q,w,cur): (1,aa,0)(q,w,cur): (1,ba,1)(q,w,cur): (1,bb,2)(q,w,cur): (2,bba,1)
Accepted

とか、

$ bash TM.sh ababa
ababa: 
(q,w,cur): (0,ababa,0)(q,w,cur): (1,ababa,1)(q,w,cur): (1,aaaba,0)(q,w,cur): (1,baaba,1)(q,w,cur): (1,bbaba,2)(q,w,cur): (1,bbbba,3)(q,w,cur): (1,bbbaa,2)(q,w,cur): (1,bbaaa,1)(q,w,cur): (1,baaaa,0)(q,w,cur): (1,aaaaa,-1)(q,w,cur): (2,aaaaaa,-1)
Accepted

とか、

$ bash TM.sh bb
bb: 
(q,w,cur): (0,bb,0)(q,w,cur): (0,bb,1)(q,w,cur): (0,bb,2)
Rejected

など。深夜テンションで作ったので、間違い等あるかもしれません。

学べたこと

  • bashがとても書きやすいこと(算術式のfor文など)。
  • 多次元配列のサポートがないこと。
  • 外部コマンドを使うよりも組み込みのコマンドで構成したほうが随分と速いこと。特にループ中のインクリメント をexprで行うとたかだか100回のループでも体感できる程度の遅延があった。
  • 文字列の $n$ 文字目だけを置換するのが案外難しいこと。sedを使う方法しか思いつかなかった。

Viewing all articles
Browse latest Browse all 2722

Trending Articles