图灵机找出磁带上出现次数最多的字符

Turing machine to find most occurring char on tape

所以我需要创建一个 TM 的文字表示,它可以找到磁带上出现次数最多的字符并擦除其他所有字符。 TM 只有一盘磁带,输入如下所示:

#a# => #a# #aaabbaac# => #a#

字母表是{a,b,c,d}。

我需要一些提示来解决这个问题,因为我发现自己卡住了。我的第一个想法是按顺序删除字符(例如,对于任何 'a',尝试删除另一个 'b' 然后 'c' 然后 'd' 如果可能的话)所以最后会有只保留最常出现的一个,但这似乎太复杂了。

有什么想法吗?

与任何编程任务一样,我们的想法是将其分解为您知道如何在机器中编码的可管理部分,这些部分将 运行 您的程序。一旦我们有了计划,我们就可以着急如何简化它并写下答案。

你的想法不错:我们可以看到第一个未擦除符号是什么,然后向右扫描并删除每个其他未擦除符号的一个实例,直到我们得到一个空白;然后,重新设置并重复,直到最后一次没有擦除任何符号为止。然后,找到最后剩下的未擦除符号,将其复制到磁带的前面,然后将其余部分空白,直到找到右侧的空白为止。这就是设计。

现在我们可以谈谈实现了。我们需要一种状态和转换的编码,它将具有执行上述操作的效果。我们需要做的第一件事是阅读磁带符号,找出第一个未擦除的符号是什么。我们知道 TM 无论如何都需要一个初始状态,所以这就是可能的状态。我们将调用状态 q0.

如果我们在 q0 并且看到一个空白,我们总是可以认为这意味着磁带是空的并且我们可以停止接受。请注意,问题描述不包括两种边缘情况:空字符串;具有相同数量的多个符号的字符串。如果某些符号出现相同的最大次数,我们是将它们全部显示还是什么都不显示?此推导假设我们可以不显示任何内容。

如果在 q0 中我们在磁带上看到 a,我们需要向右扫描并删除最多一个 bcd .我们甚至可以调用状态 qbcd 来提醒自己我们正在寻找什么。读到a,我们需要擦除它;我们不一定要用空白覆盖它,所以我们可以用一个特殊的符号B来表示擦除。对于其他磁带可能性,我们得到与 qacdqabdqabc 类似的过渡。

在状态 qxyz 中,其中 xyz 代表 ab 中的三个的某种组合、cd,我们希望删除 xyz 中的一个,但不会删除剩余的符号。所以,如果我们看到剩下的符号,我们就不要管磁带并向右移动;如果我们看到符号 xyz,那么我们将转换到对应于剩余要删除的两个符号的状态。会有六个这样的状态:qabqacqadqbcqbdqcd

在状态 qxy 中,其中 xy 代表 abc 中的两个的某种组合和 d,我们希望删除 xy 中的一个,但不会删除其他两个符号。所以,如果我们看到其他符号,我们就不要理会磁带并向右移动;如果我们看到符号 xy 然后我们转换到对应于唯一剩余要删除的符号的状态。会有四种这样的状态:qa, qb, qc, qd.

在状态 qx 中,其中 x 代表 abcd 之一,我们是希望删除其他三个符号的 x 但 none。所以,如果我们看到其他三个符号,我们就不要理会磁带并向右移动;如果我们看到符号 x 然后我们转换到指示每个符号之一已被删除的状态。调用此状态 qR.

如果在状态 qxyzqxyqx 中您发现一个真正的空白符号 - 表示输入已用完 - 这意味着您没有找到某些符号你想删除。这可以;在这种情况下,我们可以转换到与上一段中提到的相同状态:表示我们已经完成了一次通过并准备重复该过程的状态。

在状态 qR 中,您将磁带倒回到第一个真正空白所在的磁带开头,然后转换到我们称为 qF 的另一个状态。 qF 的唯一工作是向右扫描并找到第一个不是 B 的符号。然后,它的行为与初始状态完全一样,并重复上述过程。请注意,所有状态在读取磁带时应忽略 Bs,并跳过它们。我们甚至可以重复使用 q0,因为输入磁带最初不会有任何 B;使用此额外功能重载 q0 是安全的。

如果你到达磁带的右侧 - 所有原始输入后的空白 - 在其中一种状态 qxyz,这意味着你删除了第四个符号 w 但没有找到在同一遍中要擦除的任何其他符号。这意味着 w 最初是具有最多实例的符号。当我们检测到这种特殊情况时,我们可以转换到新状态 qa'qb'qc'qd',其中 return 到磁带的开头,然后过渡到状态 qa''qb''qc''qd'' 以写下它们的输入,然后过渡到 qE 以最终擦除磁带的其余部分,停止- 当到达输入末尾的空白时接受。

这在 TM 中是什么样子的?

state    tape     |   new state    new tape    head direction
-------------------------------------------------------------
// find and erase the first symbol  /////////////////////////
-------------------------------------------------------------
q0       #        |   halt_accept  #           same
q0       B        |   q0           B           right
q0       a        |   qbcd         B           right
q0       b        |   qacd         B           right
q0       c        |   qabd         B           right
q0       d        |   qabc         B           right
-------------------------------------------------------------
// look for any of three targets ////////////////////////////
-------------------------------------------------------------
qbcd     #        |   qa'          #           left
qbcd     B,a      |   qbcd         B,a         right
qbcd     b        |   qcd          B           right
qbcd     c        |   qbd          B           right
qbcd     d        |   qbc          B           right
-------------------------------------------------------------
qacd     #        |   qb'          #           left
qacd     B,b      |   qacd         B,b         right
qacd     a        |   qcd          B           right
qacd     c        |   qad          B           right
qacd     d        |   qac          B           right
-------------------------------------------------------------
qabd     #        |   qc'          #           left
qabd     B,c      |   qabd         B,c         right
qabd     a        |   qbd          B           right
qabd     b        |   qad          B           right
qabd     d        |   qab          B           right
-------------------------------------------------------------
qabc     #        |   qd'          #           left
qabc     B,d      |   qabc         B,d         right
qabc     a        |   qbc          B           right
qabc     b        |   qac          B           right
qabc     c        |   qab          B           right
-------------------------------------------------------------
// look for any of two targets //////////////////////////////
-------------------------------------------------------------
qab      #        |   qR           #           left
qab      B,c,d    |   qab          B,c,d       right
qab      a        |   qb           B           right
qab      b        |   qa           B           right
-------------------------------------------------------------
qac      #        |   qR           #           left
qac      B,b,d    |   qac          B,b,d       right
qac      a        |   qc           B           right
qac      c        |   qb           B           right
-------------------------------------------------------------
qad      #        |   qR           #           left
qad      B,b,c    |   qad          B,b,c       right
qad      a        |   qd           B           right
qad      d        |   qa           B           right
-------------------------------------------------------------
qbc      #        |   qR           #           left
qbc      B,a,d    |   qbc          B,a,d,      right
qbc      b        |   qc           B           right
qbc      c        |   qb           B           right
-------------------------------------------------------------
qbd      #        |   qR           #           left
qbd      B,a,c    |   qbd          B,a,c       right
qbd      b        |   qd           B           right
qbd      d        |   qb           B           right
-------------------------------------------------------------
qcd      #        |   qR           #           left
qcd      B,a,b    |   qcd          B,a,b       right
qcd      c        |   qd           B           right
qcd      d        |   qc           B           right
-------------------------------------------------------------
// look for single target ///////////////////////////////////
-------------------------------------------------------------
qa       #,a      |   qR           #,B         left
qa       B,b,c,d  |   qa           B,b,c,d     right
-------------------------------------------------------------
qb       #,b      |   qR           #,B         left
qb       B,a,c,d  |   qb           B,a,c,d     right
-------------------------------------------------------------
qc       #,c      |   qR           #,B         left
qc       B,a,b,d  |   qc           B,a,b,d     right
-------------------------------------------------------------
qd       #,d      |   qR           #,B         left
qd       B,a,b,c  |   qd           B,a,b,c     right
-------------------------------------------------------------
// scan back to the beginning of the tape ///////////////////
-------------------------------------------------------------
qR       #        |   q0           #           right
qR       B,a,b,c,d|   qR           B,a,b,c,d   left
-------------------------------------------------------------
qa'      #        |   qa''         #           right
qa'      B,a,b,c,d|   qa'          B,a,b,c,d   left
-------------------------------------------------------------
qb'      #        |   qb''         #           right
qb'      B,a,b,c,d|   qb'          B,a,b,c,d   left
-------------------------------------------------------------
qc'      #        |   qc''         #           right
qc'      B,a,b,c,d|   qc'          B,a,b,c,d   left
-------------------------------------------------------------
qd'      #        |   qd''         #           right
qd'      B,a,b,c,d|   qd'          B,a,b,c,d   left
-------------------------------------------------------------
// write the output if we found one /////////////////////////
-------------------------------------------------------------
qa''     #        |   halt_accept  #           same
qa''     B,a,b,c,d|   qE           a           right
-------------------------------------------------------------
qb''     #        |   halt_accept  #           same
qb''     B,a,b,c,d|   qE           b           right
-------------------------------------------------------------
qc''     #        |   halt_accept  #           same
qc''     B,a,b,c,d|   qE           c           right
-------------------------------------------------------------
qd''     #        |   halt_accept  #           same
qd''     B,a,b,c,d|   qE           d           right
-------------------------------------------------------------
// erase the rest of the input tape /////////////////////////
-------------------------------------------------------------
qE       #        |   halt_accept  #           same
qE       B,a,b,c,d|   qE           #           right

如果您宁愿将磁带头留在磁带的前面,您可以编写特殊的磁带符号,如 ABCD 在双素数状态下,扫描到最后,向后擦除,直到找到 # 或上述符号之一。这意味着一些额外的状态,但在概念上很简单。

此 TM 有 24 个状态、96 个转换(如果完全展开)并且在每一遍中至少擦除一个符号;因此,它的 运行 时间在最坏的情况下是二次方的:输入大小 4n,每个符号的 n,算法执行 n 次传递并在每次传递中按 n 步的顺序,加上一些 o(n^2) 的东西擦除磁带的结尾。

也许这就是你的想法,但想得太复杂了。我承认写下来花了很长时间。然而,这在概念上非常简单,并且可能是单个磁带 TM 的最佳选择。