繁体   English   中英

图灵机Euclid算法找到最大公约数python

[英]Turing Machine Euclid's Algorithm for finding greatest common divisor python

我的代码位于底部:(如果某人有足够的耐心阅读所有内容,我会感到非常惊讶)

输出的数字不正确,但是我不知道为什么。 我已经遵循了算法。 输入必须是2个一元数,例如2和6 =>01101111110。如果有更简单的方法来编码此算法,请告诉我。 这是算法(摘自Roger Penrose的《皇帝的新思维》一书)

在此处输入图片说明

我的代码是:

x = input("Dos numeros en sistema unario separado por un 0: ")
x = list(x)
pos = 0
valorMaq = 0
while (True):
    if valorMaq==0 and x[pos]=='0':
        valorMaq=0
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==0 and x[pos]=='1':
        valorMaq=11
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==1 and x[pos]=='0':
        valorMaq=10
        x[pos]='1'
        pos=pos+1
        print(x)

    elif valorMaq==1 and x[pos]=='1':
        valorMaq=1
        x[pos]='1'
        pos=pos-1
        print(x)
############################################
    elif valorMaq==10 and x[pos]=='0':
        valorMaq=1010
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==10 and x[pos]=='1':
        valorMaq=11
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==11 and x[pos]=='0':
        valorMaq=100
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==11 and x[pos]=='1':
        valorMaq=11
        x[pos]='1'
        pos=pos+1
        print(x)
#############################################
    elif valorMaq==100 and x[pos]=='0':
        valorMaq=100
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==100 and x[pos]=='1':
        valorMaq=101
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==101 and x[pos]=='0':
        valorMaq=111
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==101 and x[pos]=='1':
        valorMaq=110
        x[pos]='1'
        pos=pos-1
        print(x)

    elif valorMaq==110 and x[pos]=='0':
        valorMaq=110
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==110 and x[pos]=='1':
        valorMaq=1
        x[pos]='1'
        pos=pos-1
        print(x)

    elif valorMaq==111 and x[pos]=='0':
        valorMaq=111
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==111 and x[pos]=='1':
        valorMaq=1000
        x[pos]='1'
        pos=pos-1
        print(x)
################################################
    elif valorMaq==1000 and x[pos]=='0':
        valorMaq=1001
        x[pos]='0'
        pos=pos-1
        print(x)

    elif valorMaq==1000 and x[pos]=='1':
        valorMaq=1000
        x[pos]='1'
        pos=pos-1

    elif valorMaq==1001 and x[pos]=='0':
        valorMaq=10
        x[pos]='0'
        pos=pos+1
        print(x)

    elif valorMaq==1001 and x[pos]=='1':
        valorMaq=1
        x[pos]='1'
        pos=pos-1
        print(x)

    elif valorMaq==1010 and x[pos]=='1':
        valorMaq=1010
        x[pos]='1'
        pos=pos+1
        print(x)

    elif valorMaq==1010 and x[pos]=='0':
        valorMaq=0
        x[pos]='0'
        pos=pos+1
        break
        print(x)

x = ''.join(x)
print("Maximo comun divisor: ", x)

尽管您写了什么,但我确实查看了代码的每一行。

您对第二条规则的实现不正确。 彭罗斯(Penrose)具有0 1 →1 1 L,但您已将其编程为0 1 →11 0L 。因此,将第12至16行更改为

elif valorMaq==0 and x[pos]=='1':
    valorMaq=1
    x[pos]='1'
    pos=pos-1
    print(x)

那是唯一错误的规则。 但是,您没有考虑图灵机的重要概念:它可能是无限的,并且每当读取头从当前定义的磁带移开时,都会自动将空白单元添加到磁带的任一端。 您可以通过在更改pos每个代码段中添加更多行来实现这一点。

但是,我建议您对代码进行彻底的更改。 您使代码变得比原本需要的困难。 例如,您可以使用制表符进行缩进,但这在Python中并不是一个好主意-每个缩进级别都使用4个空格。

另外,您有很多重复的代码,这违反了DRY( 请勿重复自己的原理。用诸如字典等数据结构表示规则来替换算法,并编写一个使用输入和该结构的小型引擎来例如, rules[(0, '0')]可以是表示停留在零状态的元组(0, '0', +1) ,向当前位置写入一个'0'字符,并将1加到当前位置(即向右移动一个单元格),第二个产生式将状态1,字符“ 1”的rules[(0, '1')]设为(1, '1', -1) ,然后向左移动STOP动作可以用机器永远不会移动的东西来表示,例如None(无),这样的代码将更容易理解和调试。

这是一些执行此操作的代码。 我还改进了打印输出,以显示磁带中的当前状态和位置,并删除了您的要求,即输入的两端必须有一个额外的'0'字符。 我还使代码更加灵活,可扩展和可测试。 我相信很清楚如何将规则转换为彭罗斯(Penrose)将其显示为规则字典中使用的格式,尽管为了方便和空间,我使用十进制数字而非彭罗斯(Penrose)的二进制数字。 此代码中没有错误检查。 我用成对的数字(每组从1到50)进行了测试,它始终以一进制格式给出正确的最大公约数。 彭罗斯(Penrose)的算法非常聪明-我从来没有想过这种算法,它不使用任何额外的字符。

"""Calculate the greatest common divisor of two unary numbers using
Penrose's algorithm for a Turing machine.

Suggested by <https://stackoverflow.com/questions/44467401/turing-
machine-euclids-algorithm-for-finding-greatest-common-divisor-python>
which itself uses Roger Penrose's *The Emperor's New Mind*, Oxford
University Press 1989 (paperback) p.41, the algorithm called EUC.

No error checking is done to the rules dictionary or the input line
that the correct format is followed.

Possible changes:
    1.  Enforce Penrose's requirement that the ending position is to
        the right of the answer (perhaps with blanks between the answer
        and the position).
        a.  Perhaps return ''.join(tape[:pos]).strip(BLANK) which
            removes anything at and right of the ending position.
        b.  Perhaps check that only blanks are at and right of the
            ending position.
"""

# Constants for magic numbers
BLANK = '0'  # blank character
STOP = None  # code to end the calcuation
STATEWIDTH = 3  # number of spaces to print current state in

# A rules dictionary, each entry in the format
#   (oldstate, currentcharacter): (newstate, newcharacter, move_or_stop)
EUC = {
    ( 0, '0'): ( 0, '0', +1),    ( 0, '1'): ( 1, '1', -1),  # state  0 =    0
    ( 1, '0'): ( 2, '1', +1),    ( 1, '1'): ( 1, '1', -1),  # state  1 =    1
    ( 2, '0'): (10, '0', +1),    ( 2, '1'): ( 3, '0', +1),  # state  2 =   10
    ( 3, '0'): ( 4, '0', +1),    ( 3, '1'): ( 3, '1', +1),  # state  3 =   11
    ( 4, '0'): ( 4, '0', +1),    ( 4, '1'): ( 5, '0', +1),  # state  4 =  100
    ( 5, '0'): ( 7, '0', -1),    ( 5, '1'): ( 6, '1', -1),  # state  5 =  101
    ( 6, '0'): ( 6, '0', -1),    ( 6, '1'): ( 1, '1', -1),  # state  6 =  110
    ( 7, '0'): ( 7, '0', -1),    ( 7, '1'): ( 8, '1', -1),  # state  7 =  111
    ( 8, '0'): ( 9, '0', -1),    ( 8, '1'): ( 8, '1', -1),  # state  8 = 1000
    ( 9, '0'): ( 2, '0', +1),    ( 9, '1'): ( 1, '1', -1),  # state  9 = 1001
    (10, '0'): ( 0, '0', STOP),  (10, '1'): (10, '1', +1),  # state 10 = 1010
}

def print_situation(state, tape, pos, printlines):
    if printlines:
        print(str(state).rjust(STATEWIDTH), ''.join(tape))
        print(''.rjust(STATEWIDTH), '^'.rjust(pos + 1))

def turing_machine(inputline, rules, printlines=True):
    tape = list(inputline)
    state = 0
    pos = 0
    print_situation(state, tape, pos, printlines)
    move = 1  # something other than STOP
    while move != STOP:
        # Do the next action
        state, tape[pos], move = rules[(state, tape[pos])]
        if move != STOP:
            pos += move
        else:
            pos += 1  # Penrose says all stops move right once
        # Add any needed blank characters to an end of the tape
        while pos < 0:
            tape.insert(0, BLANK)
            pos += 1  # pos is relative to left end of tape, so adjust both
        while pos >= len(tape):
            tape.append(BLANK)  # left end not changed so pos not adjusted
        # Print current situation
        print_situation(state, tape, pos, printlines)
    return ''.join(tape).strip(BLANK)

print(turing_machine(
        input("Enter two unary numbers separated by a '0': "), EUC))

当我输入2和6的代码时, 110111111 ,返回的结果是11 ,这是2的一元代码,整个打印输出是:

  0 110111111
    ^
  1 0110111111
    ^
  2 1110111111
     ^
  3 1010111111
      ^
  3 1010111111
       ^
  4 1010111111
        ^
  5 1010011111
         ^
  6 1010011111
        ^
  6 1010011111
       ^
  6 1010011111
      ^
  1 1010011111
     ^
  2 1110011111
      ^
  3 1100011111
       ^
  4 1100011111
        ^
  4 1100011111
         ^
  5 1100001111
          ^
  6 1100001111
         ^
  6 1100001111
        ^
  6 1100001111
       ^
  6 1100001111
      ^
  6 1100001111
     ^
  1 1100001111
    ^
  1 01100001111
    ^
  2 11100001111
     ^
  3 10100001111
      ^
  3 10100001111
       ^
  4 10100001111
        ^
  4 10100001111
         ^
  4 10100001111
          ^
  4 10100001111
           ^
  5 10100000111
            ^
  6 10100000111
           ^
  6 10100000111
          ^
  6 10100000111
         ^
  6 10100000111
        ^
  6 10100000111
       ^
  6 10100000111
      ^
  1 10100000111
     ^
  2 11100000111
      ^
  3 11000000111
       ^
  4 11000000111
        ^
  4 11000000111
         ^
  4 11000000111
          ^
  4 11000000111
           ^
  4 11000000111
            ^
  5 11000000011
             ^
  6 11000000011
            ^
  6 11000000011
           ^
  6 11000000011
          ^
  6 11000000011
         ^
  6 11000000011
        ^
  6 11000000011
       ^
  6 11000000011
      ^
  6 11000000011
     ^
  1 11000000011
    ^
  1 011000000011
    ^
  2 111000000011
     ^
  3 101000000011
      ^
  3 101000000011
       ^
  4 101000000011
        ^
  4 101000000011
         ^
  4 101000000011
          ^
  4 101000000011
           ^
  4 101000000011
            ^
  4 101000000011
             ^
  4 101000000011
              ^
  5 101000000001
               ^
  6 101000000001
              ^
  6 101000000001
             ^
  6 101000000001
            ^
  6 101000000001
           ^
  6 101000000001
          ^
  6 101000000001
         ^
  6 101000000001
        ^
  6 101000000001
       ^
  6 101000000001
      ^
  1 101000000001
     ^
  2 111000000001
      ^
  3 110000000001
       ^
  4 110000000001
        ^
  4 110000000001
         ^
  4 110000000001
          ^
  4 110000000001
           ^
  4 110000000001
            ^
  4 110000000001
             ^
  4 110000000001
              ^
  4 110000000001
               ^
  5 1100000000000
                ^
  7 1100000000000
               ^
  7 1100000000000
              ^
  7 1100000000000
             ^
  7 1100000000000
            ^
  7 1100000000000
           ^
  7 1100000000000
          ^
  7 1100000000000
         ^
  7 1100000000000
        ^
  7 1100000000000
       ^
  7 1100000000000
      ^
  7 1100000000000
     ^
  8 1100000000000
    ^
  8 01100000000000
    ^
  9 001100000000000
    ^
  2 001100000000000
     ^
 10 001100000000000
      ^
 10 001100000000000
       ^
 10 001100000000000
        ^
  0 001100000000000
         ^
11

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM